BSD 4_3_Net_2 development
[unix-history] / usr / src / usr.bin / gas / obstack.c
CommitLineData
ce19ed84
C
1/* obstack.c - subroutines used implicitly by object stack macros
2 Copyright (C) 1988 Free Software Foundation, Inc.
3
4This program is free software; you can redistribute it and/or modify it
5under the terms of the GNU General Public License as published by the
6Free Software Foundation; either version 1, or (at your option) any
7later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18#include "obstack.h"
19
20#ifdef __STDC__
21#define POINTER void *
22#else
23#define POINTER char *
24#endif
25
26/* Determine default alignment. */
27struct fooalign {char x; double d;};
28#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
29/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
30 But in fact it might be less smart and round addresses to as much as
31 DEFAULT_ROUNDING. So we prepare for it to do that. */
32union fooround {long x; double d;};
33#define DEFAULT_ROUNDING (sizeof (union fooround))
34
35/* When we copy a long block of data, this is the unit to do it with.
36 On some machines, copying successive ints does not work;
37 in such a case, redefine COPYING_UNIT to `long' (if that works)
38 or `char' as a last resort. */
39#ifndef COPYING_UNIT
40#define COPYING_UNIT int
41#endif
42
43/* The non-GNU-C macros copy the obstack into this global variable
44 to avoid multiple evaluation. */
45
46struct obstack *_obstack;
47\f
48/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
49 Objects start on multiples of ALIGNMENT (0 means use default).
50 CHUNKFUN is the function to use to allocate chunks,
51 and FREEFUN the function to free them. */
52
53void
54_obstack_begin (h, size, alignment, chunkfun, freefun)
55 struct obstack *h;
56 int size;
57 int alignment;
58 POINTER (*chunkfun) ();
59 void (*freefun) ();
60{
61 register struct _obstack_chunk* chunk; /* points to new chunk */
62
63 if (alignment == 0)
64 alignment = DEFAULT_ALIGNMENT;
65 if (size == 0)
66 /* Default size is what GNU malloc can fit in a 4096-byte block. */
67 {
68 /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
69 Use the values for range checking, because if range checking is off,
70 the extra bytes won't be missed terribly, but if range checking is on
71 and we used a larger request, a whole extra 4096 bytes would be
72 allocated.
73
74 These number are irrelevant to the new GNU malloc. I suspect it is
75 less sensitive to the size of the request. */
76 int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
77 + 4 + DEFAULT_ROUNDING - 1)
78 & ~(DEFAULT_ROUNDING - 1));
79 size = 4096 - extra;
80 }
81
82 h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
83 h->freefun = freefun;
84 h->chunk_size = size;
85 h->alignment_mask = alignment - 1;
86
87 chunk = h->chunk = (*h->chunkfun) (h->chunk_size);
88 h->next_free = h->object_base = chunk->contents;
89 h->chunk_limit = chunk->limit
90 = (char *) chunk + h->chunk_size;
91 chunk->prev = 0;
92}
93
94/* Allocate a new current chunk for the obstack *H
95 on the assumption that LENGTH bytes need to be added
96 to the current object, or a new object of length LENGTH allocated.
97 Copies any partial object from the end of the old chunk
98 to the beginning of the new one. */
99
100void
101_obstack_newchunk (h, length)
102 struct obstack *h;
103 int length;
104{
105 register struct _obstack_chunk* old_chunk = h->chunk;
106 register struct _obstack_chunk* new_chunk;
107 register long new_size;
108 register int obj_size = h->next_free - h->object_base;
109 register int i;
110 int already;
111
112 /* Compute size for new chunk. */
113 new_size = (obj_size + length) + (obj_size >> 3) + 100;
114 if (new_size < h->chunk_size)
115 new_size = h->chunk_size;
116
117 /* Allocate and initialize the new chunk. */
118 new_chunk = h->chunk = (*h->chunkfun) (new_size);
119 new_chunk->prev = old_chunk;
120 new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
121
122 /* Move the existing object to the new chunk.
123 Word at a time is fast and is safe if the object
124 is sufficiently aligned. */
125 if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
126 {
127 for (i = obj_size / sizeof (COPYING_UNIT) - 1;
128 i >= 0; i--)
129 ((COPYING_UNIT *)new_chunk->contents)[i]
130 = ((COPYING_UNIT *)h->object_base)[i];
131 /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
132 but that can cross a page boundary on a machine
133 which does not do strict alignment for COPYING_UNITS. */
134 already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
135 }
136 else
137 already = 0;
138 /* Copy remaining bytes one by one. */
139 for (i = already; i < obj_size; i++)
140 new_chunk->contents[i] = h->object_base[i];
141
142 /* If the object just copied was the only data in OLD_CHUNK,
143 free that chunk and remove it from the chain. */
144 if (h->object_base == old_chunk->contents)
145 {
146 new_chunk->prev = old_chunk->prev;
147 (*h->freefun) (old_chunk);
148 }
149
150 h->object_base = new_chunk->contents;
151 h->next_free = h->object_base + obj_size;
152}
153
154/* Return nonzero if object OBJ has been allocated from obstack H.
155 This is here for debugging.
156 If you use it in a program, you are probably losing. */
157
158int
159_obstack_allocated_p (h, obj)
160 struct obstack *h;
161 POINTER obj;
162{
163 register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
164 register struct _obstack_chunk* plp; /* point to previous chunk if any */
165
166 lp = (h)->chunk;
167 while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
168 {
169 plp = lp -> prev;
170 lp = plp;
171 }
172 return lp != 0;
173}
174
175/* Free objects in obstack H, including OBJ and everything allocate
176 more recently than OBJ. If OBJ is zero, free everything in H. */
177
178void
179#ifdef __STDC__
180#undef obstack_free
181obstack_free (struct obstack *h, POINTER obj)
182#else
183_obstack_free (h, obj)
184 struct obstack *h;
185 POINTER obj;
186#endif
187{
188 register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
189 register struct _obstack_chunk* plp; /* point to previous chunk if any */
190
191 lp = (h)->chunk;
192 /* We use >= because there cannot be an object at the beginning of a chunk.
193 But there can be an empty object at that address
194 at the end of another chunk. */
195 while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
196 {
197 plp = lp -> prev;
198 (*h->freefun) (lp);
199 lp = plp;
200 }
201 if (lp)
202 {
203 (h)->object_base = (h)->next_free = (char *)(obj);
204 (h)->chunk_limit = lp->limit;
205 (h)->chunk = lp;
206 }
207 else if (obj != 0)
208 /* obj is not in any of the chunks! */
209 abort ();
210}
211
212/* Let same .o link with output of gcc and other compilers. */
213
214#ifdef __STDC__
215void
216_obstack_free (h, obj)
217 struct obstack *h;
218 POINTER obj;
219{
220 obstack_free (h, obj);
221}
222#endif
223\f
224#if 0
225/* These are now turned off because the applications do not use it
226 and it uses bcopy via obstack_grow, which causes trouble on sysV. */
227
228/* Now define the functional versions of the obstack macros.
229 Define them to simply use the corresponding macros to do the job. */
230
231#ifdef __STDC__
232/* These function definitions do not work with non-ANSI preprocessors;
233 they won't pass through the macro names in parentheses. */
234
235/* The function names appear in parentheses in order to prevent
236 the macro-definitions of the names from being expanded there. */
237
238POINTER (obstack_base) (obstack)
239 struct obstack *obstack;
240{
241 return obstack_base (obstack);
242}
243
244POINTER (obstack_next_free) (obstack)
245 struct obstack *obstack;
246{
247 return obstack_next_free (obstack);
248}
249
250int (obstack_object_size) (obstack)
251 struct obstack *obstack;
252{
253 return obstack_object_size (obstack);
254}
255
256int (obstack_room) (obstack)
257 struct obstack *obstack;
258{
259 return obstack_room (obstack);
260}
261
262void (obstack_grow) (obstack, pointer, length)
263 struct obstack *obstack;
264 POINTER pointer;
265 int length;
266{
267 obstack_grow (obstack, pointer, length);
268}
269
270void (obstack_grow0) (obstack, pointer, length)
271 struct obstack *obstack;
272 POINTER pointer;
273 int length;
274{
275 obstack_grow0 (obstack, pointer, length);
276}
277
278void (obstack_1grow) (obstack, character)
279 struct obstack *obstack;
280 int character;
281{
282 obstack_1grow (obstack, character);
283}
284
285void (obstack_blank) (obstack, length)
286 struct obstack *obstack;
287 int length;
288{
289 obstack_blank (obstack, length);
290}
291
292void (obstack_1grow_fast) (obstack, character)
293 struct obstack *obstack;
294 int character;
295{
296 obstack_1grow_fast (obstack, character);
297}
298
299void (obstack_blank_fast) (obstack, length)
300 struct obstack *obstack;
301 int length;
302{
303 obstack_blank_fast (obstack, length);
304}
305
306POINTER (obstack_finish) (obstack)
307 struct obstack *obstack;
308{
309 return obstack_finish (obstack);
310}
311
312POINTER (obstack_alloc) (obstack, length)
313 struct obstack *obstack;
314 int length;
315{
316 return obstack_alloc (obstack, length);
317}
318
319POINTER (obstack_copy) (obstack, pointer, length)
320 struct obstack *obstack;
321 POINTER pointer;
322 int length;
323{
324 return obstack_copy (obstack, pointer, length);
325}
326
327POINTER (obstack_copy0) (obstack, pointer, length)
328 struct obstack *obstack;
329 POINTER pointer;
330 int length;
331{
332 return obstack_copy0 (obstack, pointer, length);
333}
334
335#endif /* __STDC__ */
336
337#endif /* 0 */