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