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