xref: /original-bsd/bin/sh/memalloc.c (revision 6923cb9f)
1c62477cfSbostic /*-
2*6923cb9fSbostic  * Copyright (c) 1991, 1993
3*6923cb9fSbostic  *	The Regents of the University of California.  All rights reserved.
4c62477cfSbostic  *
5c62477cfSbostic  * This code is derived from software contributed to Berkeley by
6c62477cfSbostic  * Kenneth Almquist.
7c62477cfSbostic  *
8c62477cfSbostic  * %sccs.include.redist.c%
9c62477cfSbostic  */
10c62477cfSbostic 
11c62477cfSbostic #ifndef lint
12*6923cb9fSbostic static char sccsid[] = "@(#)memalloc.c	8.1 (Berkeley) 05/31/93";
13c62477cfSbostic #endif /* not lint */
14c62477cfSbostic 
15c62477cfSbostic #include "shell.h"
16c62477cfSbostic #include "output.h"
17c62477cfSbostic #include "memalloc.h"
18c62477cfSbostic #include "error.h"
19c62477cfSbostic #include "machdep.h"
20c62477cfSbostic #include "mystring.h"
21c62477cfSbostic 
22c62477cfSbostic /*
23c62477cfSbostic  * Like malloc, but returns an error when out of space.
24c62477cfSbostic  */
25c62477cfSbostic 
26c62477cfSbostic pointer
27c62477cfSbostic ckmalloc(nbytes) {
28c62477cfSbostic 	register pointer p;
29c62477cfSbostic 	pointer malloc();
30c62477cfSbostic 
31c62477cfSbostic 	if ((p = malloc(nbytes)) == NULL)
32c62477cfSbostic 		error("Out of space");
33c62477cfSbostic 	return p;
34c62477cfSbostic }
35c62477cfSbostic 
36c62477cfSbostic 
37c62477cfSbostic /*
38c62477cfSbostic  * Same for realloc.
39c62477cfSbostic  */
40c62477cfSbostic 
41c62477cfSbostic pointer
42c62477cfSbostic ckrealloc(p, nbytes)
43c62477cfSbostic 	register pointer p;
44c62477cfSbostic 	{
45c62477cfSbostic 	pointer realloc();
46c62477cfSbostic 
47c62477cfSbostic 	if ((p = realloc(p, nbytes)) == NULL)
48c62477cfSbostic 		error("Out of space");
49c62477cfSbostic 	return p;
50c62477cfSbostic }
51c62477cfSbostic 
52c62477cfSbostic 
53c62477cfSbostic /*
54c62477cfSbostic  * Make a copy of a string in safe storage.
55c62477cfSbostic  */
56c62477cfSbostic 
57c62477cfSbostic char *
58c62477cfSbostic savestr(s)
59c62477cfSbostic 	char *s;
60c62477cfSbostic 	{
61c62477cfSbostic 	register char *p;
62c62477cfSbostic 
63c62477cfSbostic 	p = ckmalloc(strlen(s) + 1);
64c62477cfSbostic 	scopy(s, p);
65c62477cfSbostic 	return p;
66c62477cfSbostic }
67c62477cfSbostic 
68c62477cfSbostic 
69c62477cfSbostic /*
70c62477cfSbostic  * Parse trees for commands are allocated in lifo order, so we use a stack
71c62477cfSbostic  * to make this more efficient, and also to avoid all sorts of exception
72c62477cfSbostic  * handling code to handle interrupts in the middle of a parse.
73c62477cfSbostic  *
74c62477cfSbostic  * The size 504 was chosen because the Ultrix malloc handles that size
75c62477cfSbostic  * well.
76c62477cfSbostic  */
77c62477cfSbostic 
78c62477cfSbostic #define MINSIZE 504		/* minimum size of a block */
79c62477cfSbostic 
80c62477cfSbostic 
81c62477cfSbostic struct stack_block {
82c62477cfSbostic 	struct stack_block *prev;
83c62477cfSbostic 	char space[MINSIZE];
84c62477cfSbostic };
85c62477cfSbostic 
86c62477cfSbostic struct stack_block stackbase;
87c62477cfSbostic struct stack_block *stackp = &stackbase;
88c62477cfSbostic char *stacknxt = stackbase.space;
89c62477cfSbostic int stacknleft = MINSIZE;
90c62477cfSbostic int sstrnleft;
91c62477cfSbostic int herefd = -1;
92c62477cfSbostic 
93c62477cfSbostic 
94c62477cfSbostic 
95c62477cfSbostic pointer
96c62477cfSbostic stalloc(nbytes) {
97c62477cfSbostic 	register char *p;
98c62477cfSbostic 
99c62477cfSbostic 	nbytes = ALIGN(nbytes);
100c62477cfSbostic 	if (nbytes > stacknleft) {
101c62477cfSbostic 		int blocksize;
102c62477cfSbostic 		struct stack_block *sp;
103c62477cfSbostic 
104c62477cfSbostic 		blocksize = nbytes;
105c62477cfSbostic 		if (blocksize < MINSIZE)
106c62477cfSbostic 			blocksize = MINSIZE;
107c62477cfSbostic 		INTOFF;
108c62477cfSbostic 		sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
109c62477cfSbostic 		sp->prev = stackp;
110c62477cfSbostic 		stacknxt = sp->space;
111c62477cfSbostic 		stacknleft = blocksize;
112c62477cfSbostic 		stackp = sp;
113c62477cfSbostic 		INTON;
114c62477cfSbostic 	}
115c62477cfSbostic 	p = stacknxt;
116c62477cfSbostic 	stacknxt += nbytes;
117c62477cfSbostic 	stacknleft -= nbytes;
118c62477cfSbostic 	return p;
119c62477cfSbostic }
120c62477cfSbostic 
121c62477cfSbostic 
122c62477cfSbostic void
123c62477cfSbostic stunalloc(p)
124c62477cfSbostic 	pointer p;
125c62477cfSbostic 	{
126c62477cfSbostic 	if (p == NULL) {		/*DEBUG */
127c62477cfSbostic 		write(2, "stunalloc\n", 10);
128c62477cfSbostic 		abort();
129c62477cfSbostic 	}
130c62477cfSbostic 	stacknleft += stacknxt - (char *)p;
131c62477cfSbostic 	stacknxt = p;
132c62477cfSbostic }
133c62477cfSbostic 
134c62477cfSbostic 
135c62477cfSbostic 
136c62477cfSbostic void
137c62477cfSbostic setstackmark(mark)
138c62477cfSbostic 	struct stackmark *mark;
139c62477cfSbostic 	{
140c62477cfSbostic 	mark->stackp = stackp;
141c62477cfSbostic 	mark->stacknxt = stacknxt;
142c62477cfSbostic 	mark->stacknleft = stacknleft;
143c62477cfSbostic }
144c62477cfSbostic 
145c62477cfSbostic 
146c62477cfSbostic void
147c62477cfSbostic popstackmark(mark)
148c62477cfSbostic 	struct stackmark *mark;
149c62477cfSbostic 	{
150c62477cfSbostic 	struct stack_block *sp;
151c62477cfSbostic 
152c62477cfSbostic 	INTOFF;
153c62477cfSbostic 	while (stackp != mark->stackp) {
154c62477cfSbostic 		sp = stackp;
155c62477cfSbostic 		stackp = sp->prev;
156c62477cfSbostic 		ckfree(sp);
157c62477cfSbostic 	}
158c62477cfSbostic 	stacknxt = mark->stacknxt;
159c62477cfSbostic 	stacknleft = mark->stacknleft;
160c62477cfSbostic 	INTON;
161c62477cfSbostic }
162c62477cfSbostic 
163c62477cfSbostic 
164c62477cfSbostic /*
165c62477cfSbostic  * When the parser reads in a string, it wants to stick the string on the
166c62477cfSbostic  * stack and only adjust the stack pointer when it knows how big the
167c62477cfSbostic  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
168c62477cfSbostic  * of space on top of the stack and stackblocklen returns the length of
169c62477cfSbostic  * this block.  Growstackblock will grow this space by at least one byte,
170c62477cfSbostic  * possibly moving it (like realloc).  Grabstackblock actually allocates the
171c62477cfSbostic  * part of the block that has been used.
172c62477cfSbostic  */
173c62477cfSbostic 
174c62477cfSbostic void
175c62477cfSbostic growstackblock() {
176c62477cfSbostic 	char *p;
177c62477cfSbostic 	int newlen = stacknleft * 2 + 100;
178c62477cfSbostic 	char *oldspace = stacknxt;
179c62477cfSbostic 	int oldlen = stacknleft;
180c62477cfSbostic 	struct stack_block *sp;
181c62477cfSbostic 
182a65b7dceSmarc 	if (stacknxt == stackp->space && stackp != &stackbase) {
183c62477cfSbostic 		INTOFF;
184c62477cfSbostic 		sp = stackp;
185c62477cfSbostic 		stackp = sp->prev;
186c62477cfSbostic 		sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
187c62477cfSbostic 		sp->prev = stackp;
188c62477cfSbostic 		stackp = sp;
189c62477cfSbostic 		stacknxt = sp->space;
190c62477cfSbostic 		stacknleft = newlen;
191c62477cfSbostic 		INTON;
192c62477cfSbostic 	} else {
193c62477cfSbostic 		p = stalloc(newlen);
194c62477cfSbostic 		bcopy(oldspace, p, oldlen);
195c62477cfSbostic 		stacknxt = p;			/* free the space */
196c62477cfSbostic 		stacknleft += newlen;		/* we just allocated */
197c62477cfSbostic 	}
198c62477cfSbostic }
199c62477cfSbostic 
200c62477cfSbostic 
201c62477cfSbostic 
202c62477cfSbostic void
203c62477cfSbostic grabstackblock(len) {
204c62477cfSbostic 	len = ALIGN(len);
205c62477cfSbostic 	stacknxt += len;
206c62477cfSbostic 	stacknleft -= len;
207c62477cfSbostic }
208c62477cfSbostic 
209c62477cfSbostic 
210c62477cfSbostic 
211c62477cfSbostic /*
212c62477cfSbostic  * The following routines are somewhat easier to use that the above.
213c62477cfSbostic  * The user declares a variable of type STACKSTR, which may be declared
214c62477cfSbostic  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
215c62477cfSbostic  * the user uses the macro STPUTC to add characters to the string.  In
216c62477cfSbostic  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
217c62477cfSbostic  * grown as necessary.  When the user is done, she can just leave the
218c62477cfSbostic  * string there and refer to it using stackblock().  Or she can allocate
219c62477cfSbostic  * the space for it using grabstackstr().  If it is necessary to allow
220c62477cfSbostic  * someone else to use the stack temporarily and then continue to grow
221c62477cfSbostic  * the string, the user should use grabstack to allocate the space, and
222c62477cfSbostic  * then call ungrabstr(p) to return to the previous mode of operation.
223c62477cfSbostic  *
224c62477cfSbostic  * USTPUTC is like STPUTC except that it doesn't check for overflow.
225c62477cfSbostic  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
226c62477cfSbostic  * is space for at least one character.
227c62477cfSbostic  */
228c62477cfSbostic 
229c62477cfSbostic 
230c62477cfSbostic char *
231c62477cfSbostic growstackstr() {
232c62477cfSbostic 	int len = stackblocksize();
233a65b7dceSmarc 	if (herefd >= 0 && len >= 1024) {
234c62477cfSbostic 		xwrite(herefd, stackblock(), len);
235c62477cfSbostic 		sstrnleft = len - 1;
236c62477cfSbostic 		return stackblock();
237c62477cfSbostic 	}
238c62477cfSbostic 	growstackblock();
239c62477cfSbostic 	sstrnleft = stackblocksize() - len - 1;
240c62477cfSbostic 	return stackblock() + len;
241c62477cfSbostic }
242c62477cfSbostic 
243c62477cfSbostic 
244c62477cfSbostic /*
245c62477cfSbostic  * Called from CHECKSTRSPACE.
246c62477cfSbostic  */
247c62477cfSbostic 
248c62477cfSbostic char *
249c62477cfSbostic makestrspace() {
250c62477cfSbostic 	int len = stackblocksize() - sstrnleft;
251c62477cfSbostic 	growstackblock();
252c62477cfSbostic 	sstrnleft = stackblocksize() - len;
253c62477cfSbostic 	return stackblock() + len;
254c62477cfSbostic }
255c62477cfSbostic 
256c62477cfSbostic 
257c62477cfSbostic 
258c62477cfSbostic void
259c62477cfSbostic ungrabstackstr(s, p)
260c62477cfSbostic 	char *s;
261c62477cfSbostic 	char *p;
262c62477cfSbostic 	{
263c62477cfSbostic 	stacknleft += stacknxt - s;
264c62477cfSbostic 	stacknxt = s;
265c62477cfSbostic 	sstrnleft = stacknleft - (p - s);
266c62477cfSbostic }
267