Magellan Linux

Annotation of /trunk/mkinitrd-magellan/klibc/usr/dash/memalloc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 7898 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 niro 532 /*-
2     * Copyright (c) 1991, 1993
3     * The Regents of the University of California. All rights reserved.
4     * Copyright (c) 1997-2005
5     * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
6     *
7     * This code is derived from software contributed to Berkeley by
8     * Kenneth Almquist.
9     *
10     * Redistribution and use in source and binary forms, with or without
11     * modification, are permitted provided that the following conditions
12     * are met:
13     * 1. Redistributions of source code must retain the above copyright
14     * notice, this list of conditions and the following disclaimer.
15     * 2. Redistributions in binary form must reproduce the above copyright
16     * notice, this list of conditions and the following disclaimer in the
17     * documentation and/or other materials provided with the distribution.
18     * 3. Neither the name of the University nor the names of its contributors
19     * may be used to endorse or promote products derived from this software
20     * without specific prior written permission.
21     *
22     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25     * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32     * SUCH DAMAGE.
33     */
34    
35     #include <stdlib.h>
36     #include <unistd.h>
37    
38     #include "shell.h"
39     #include "output.h"
40     #include "memalloc.h"
41     #include "error.h"
42     #include "machdep.h"
43     #include "mystring.h"
44     #include "system.h"
45    
46     /*
47     * Like malloc, but returns an error when out of space.
48     */
49    
50     pointer
51     ckmalloc(size_t nbytes)
52     {
53     pointer p;
54    
55     p = malloc(nbytes);
56     if (p == NULL)
57     sh_error("Out of space");
58     return p;
59     }
60    
61    
62     /*
63     * Same for realloc.
64     */
65    
66     pointer
67     ckrealloc(pointer p, size_t nbytes)
68     {
69     p = realloc(p, nbytes);
70     if (p == NULL)
71     sh_error("Out of space");
72     return p;
73     }
74    
75    
76     /*
77     * Make a copy of a string in safe storage.
78     */
79    
80     char *
81     savestr(const char *s)
82     {
83     char *p = strdup(s);
84     if (!p)
85     sh_error("Out of space");
86     return p;
87     }
88    
89    
90     /*
91     * Parse trees for commands are allocated in lifo order, so we use a stack
92     * to make this more efficient, and also to avoid all sorts of exception
93     * handling code to handle interrupts in the middle of a parse.
94     *
95     * The size 504 was chosen because the Ultrix malloc handles that size
96     * well.
97     */
98    
99     /* minimum size of a block */
100     #define MINSIZE SHELL_ALIGN(504)
101    
102     struct stack_block {
103     struct stack_block *prev;
104     char space[MINSIZE];
105     };
106    
107     struct stack_block stackbase;
108     struct stack_block *stackp = &stackbase;
109     struct stackmark *markp;
110     char *stacknxt = stackbase.space;
111     size_t stacknleft = MINSIZE;
112     char *sstrend = stackbase.space + MINSIZE;
113     int herefd = -1;
114    
115     pointer
116     stalloc(size_t nbytes)
117     {
118     char *p;
119     size_t aligned;
120    
121     aligned = SHELL_ALIGN(nbytes);
122     if (aligned > stacknleft) {
123     size_t len;
124     size_t blocksize;
125     struct stack_block *sp;
126    
127     blocksize = aligned;
128     if (blocksize < MINSIZE)
129     blocksize = MINSIZE;
130     len = sizeof(struct stack_block) - MINSIZE + blocksize;
131     if (len < blocksize)
132     sh_error("Out of space");
133     INTOFF;
134     sp = ckmalloc(len);
135     sp->prev = stackp;
136     stacknxt = sp->space;
137     stacknleft = blocksize;
138     sstrend = stacknxt + blocksize;
139     stackp = sp;
140     INTON;
141     }
142     p = stacknxt;
143     stacknxt += aligned;
144     stacknleft -= aligned;
145     return p;
146     }
147    
148    
149     void
150     stunalloc(pointer p)
151     {
152     #ifdef DEBUG
153     if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
154     write(2, "stunalloc\n", 10);
155     abort();
156     }
157     #endif
158     stacknleft += stacknxt - (char *)p;
159     stacknxt = p;
160     }
161    
162    
163    
164     void
165     setstackmark(struct stackmark *mark)
166     {
167     mark->stackp = stackp;
168     mark->stacknxt = stacknxt;
169     mark->stacknleft = stacknleft;
170     mark->marknext = markp;
171     markp = mark;
172     }
173    
174    
175     void
176     popstackmark(struct stackmark *mark)
177     {
178     struct stack_block *sp;
179    
180     INTOFF;
181     markp = mark->marknext;
182     while (stackp != mark->stackp) {
183     sp = stackp;
184     stackp = sp->prev;
185     ckfree(sp);
186     }
187     stacknxt = mark->stacknxt;
188     stacknleft = mark->stacknleft;
189     sstrend = mark->stacknxt + mark->stacknleft;
190     INTON;
191     }
192    
193    
194     /*
195     * When the parser reads in a string, it wants to stick the string on the
196     * stack and only adjust the stack pointer when it knows how big the
197     * string is. Stackblock (defined in stack.h) returns a pointer to a block
198     * of space on top of the stack and stackblocklen returns the length of
199     * this block. Growstackblock will grow this space by at least one byte,
200     * possibly moving it (like realloc). Grabstackblock actually allocates the
201     * part of the block that has been used.
202     */
203    
204     void
205     growstackblock(void)
206     {
207     size_t newlen;
208    
209     newlen = stacknleft * 2;
210     if (newlen < stacknleft)
211     sh_error("Out of space");
212     if (newlen < 128)
213     newlen += 128;
214    
215     if (stacknxt == stackp->space && stackp != &stackbase) {
216     struct stack_block *oldstackp;
217     struct stackmark *xmark;
218     struct stack_block *sp;
219     struct stack_block *prevstackp;
220     size_t grosslen;
221    
222     INTOFF;
223     oldstackp = stackp;
224     sp = stackp;
225     prevstackp = sp->prev;
226     grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
227     sp = ckrealloc((pointer)sp, grosslen);
228     sp->prev = prevstackp;
229     stackp = sp;
230     stacknxt = sp->space;
231     stacknleft = newlen;
232     sstrend = sp->space + newlen;
233    
234     /*
235     * Stack marks pointing to the start of the old block
236     * must be relocated to point to the new block
237     */
238     xmark = markp;
239     while (xmark != NULL && xmark->stackp == oldstackp) {
240     xmark->stackp = stackp;
241     xmark->stacknxt = stacknxt;
242     xmark->stacknleft = stacknleft;
243     xmark = xmark->marknext;
244     }
245     INTON;
246     } else {
247     char *oldspace = stacknxt;
248     int oldlen = stacknleft;
249     char *p = stalloc(newlen);
250    
251     /* free the space we just allocated */
252     stacknxt = memcpy(p, oldspace, oldlen);
253     stacknleft += newlen;
254     }
255     }
256    
257     void
258     grabstackblock(size_t len)
259     {
260     len = SHELL_ALIGN(len);
261     stacknxt += len;
262     stacknleft -= len;
263     }
264    
265     /*
266     * The following routines are somewhat easier to use than the above.
267     * The user declares a variable of type STACKSTR, which may be declared
268     * to be a register. The macro STARTSTACKSTR initializes things. Then
269     * the user uses the macro STPUTC to add characters to the string. In
270     * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
271     * grown as necessary. When the user is done, she can just leave the
272     * string there and refer to it using stackblock(). Or she can allocate
273     * the space for it using grabstackstr(). If it is necessary to allow
274     * someone else to use the stack temporarily and then continue to grow
275     * the string, the user should use grabstack to allocate the space, and
276     * then call ungrabstr(p) to return to the previous mode of operation.
277     *
278     * USTPUTC is like STPUTC except that it doesn't check for overflow.
279     * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
280     * is space for at least one character.
281     */
282    
283     void *
284     growstackstr(void)
285     {
286     size_t len = stackblocksize();
287     if (herefd >= 0 && len >= 1024) {
288     xwrite(herefd, stackblock(), len);
289     return stackblock();
290     }
291     growstackblock();
292     return stackblock() + len;
293     }
294    
295     /*
296     * Called from CHECKSTRSPACE.
297     */
298    
299     char *
300     makestrspace(size_t newlen, char *p)
301     {
302     size_t len = p - stacknxt;
303     size_t size = stackblocksize();
304    
305     for (;;) {
306     size_t nleft;
307    
308     size = stackblocksize();
309     nleft = size - len;
310     if (nleft >= newlen)
311     break;
312     growstackblock();
313     }
314     return stackblock() + len;
315     }
316    
317     char *
318     stnputs(const char *s, size_t n, char *p)
319     {
320     p = makestrspace(n, p);
321     p = mempcpy(p, s, n);
322     return p;
323     }
324    
325     char *
326     stputs(const char *s, char *p)
327     {
328     return stnputs(s, strlen(s), p);
329     }