memalloc.c revision 39049
150476Speter/*- 215903Swosch * Copyright (c) 1991, 1993 315903Swosch * The Regents of the University of California. All rights reserved. 431074Swosch * 515903Swosch * This code is derived from software contributed to Berkeley by 615903Swosch * Kenneth Almquist. 715903Swosch * 815903Swosch * Redistribution and use in source and binary forms, with or without 915903Swosch * modification, are permitted provided that the following conditions 1015903Swosch * are met: 1115903Swosch * 1. Redistributions of source code must retain the above copyright 1215903Swosch * notice, this list of conditions and the following disclaimer. 1315903Swosch * 2. Redistributions in binary form must reproduce the above copyright 1415903Swosch * notice, this list of conditions and the following disclaimer in the 1515903Swosch * documentation and/or other materials provided with the distribution. 1615903Swosch * 3. All advertising materials mentioning features or use of this software 1715903Swosch * must display the following acknowledgement: 1815903Swosch * This product includes software developed by the University of 1915903Swosch * California, Berkeley and its contributors. 2015903Swosch * 4. Neither the name of the University nor the names of its contributors 2115903Swosch * may be used to endorse or promote products derived from this software 2274806Sru * without specific prior written permission. 2315903Swosch * 2415903Swosch * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2523546Swosch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2623546Swosch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2715903Swosch * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2815903Swosch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2915903Swosch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3015903Swosch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3115903Swosch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3215903Swosch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3315903Swosch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3415903Swosch * SUCH DAMAGE. 3515903Swosch */ 3620935Swosch 3720935Swosch#ifndef lint 3860749Shoek#if 0 3917511Speterstatic char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95"; 4015903Swosch#endif 4127659Spststatic const char rcsid[] = 4227659Spst "$Id: memalloc.c,v 1.10 1998/09/06 21:13:09 tegge Exp $"; 4327659Spst#endif /* not lint */ 4427659Spst 4527659Spst#include "shell.h" 4615903Swosch#include "output.h" 4715903Swosch#include "memalloc.h" 4815903Swosch#include "error.h" 4915903Swosch#include "machdep.h" 5015903Swosch#include "mystring.h" 511638Srgrimes#include "expand.h" 5211468Sbde#include <stdlib.h> 531638Srgrimes#include <unistd.h> 5427659Spst 5527659Spst/* 5672942Sru * Like malloc, but returns an error when out of space. 5727659Spst */ 5823546Swosch 5923546Swoschpointer 6011468Sbdeckmalloc(nbytes) 6138898Sjb int nbytes; 6211468Sbde{ 6311623Sbde pointer p; 6474806Sru 6574806Sru if ((p = malloc(nbytes)) == NULL) 6674806Sru error("Out of space"); 6711623Sbde return p; 6874806Sru} 6911623Sbde 7074806Sru 7111623Sbde/* 7211623Sbde * Same for realloc. 7374806Sru */ 7411468Sbde 7511468Sbdepointer 7611468Sbdeckrealloc(p, nbytes) 7711623Sbde pointer p; 7818314Speter int nbytes; 7918314Speter{ 8018314Speter 8118314Speter if ((p = realloc(p, nbytes)) == NULL) 8218314Speter error("Out of space"); 8318314Speter return p; 8418314Speter} 8518314Speter 8618314Speter 871844Swollman/* 881638Srgrimes * Make a copy of a string in safe storage. 8917511Speter */ 9074806Sru 9174806Sruchar * 9274806Srusavestr(s) 9374806Sru char *s; 9418314Speter { 9517511Speter char *p; 9617511Speter 9717831Speter p = ckmalloc(strlen(s) + 1); 9817511Speter scopy(s, p); 9927673Sbde return p; 10027659Spst} 10127659Spst 10227659Spst 10327659Spst/* 10417511Speter * Parse trees for commands are allocated in lifo order, so we use a stack 10517511Speter * to make this more efficient, and also to avoid all sorts of exception 10617511Speter * handling code to handle interrupts in the middle of a parse. 10717511Speter * 10827659Spst * The size 504 was chosen because the Ultrix malloc handles that size 10974806Sru * well. 11074806Sru */ 11127673Sbde 11274806Sru#define MINSIZE 504 /* minimum size of a block */ 11327659Spst 11427659Spst 11527659Spststruct stack_block { 11627659Spst struct stack_block *prev; 11727659Spst char space[MINSIZE]; 11827659Spst}; 11927659Spst 12027659Spststruct stack_block stackbase; 12127659Spststruct stack_block *stackp = &stackbase; 12217511Speterchar *stacknxt = stackbase.space; 12311468Sbdeint stacknleft = MINSIZE; 1241844Swollmanint sstrnleft; 12523546Swoschint herefd = -1; 12611136Swollman 12774806Sru 12874806Sru 12974806Srupointer 13074806Srustalloc(nbytes) 13123546Swosch int nbytes; 13211468Sbde{ 13311468Sbde char *p; 13417831Speter 13523546Swosch nbytes = ALIGN(nbytes); 13617511Speter if (nbytes > stacknleft) { 13723546Swosch int blocksize; 13817511Speter struct stack_block *sp; 13911136Swollman 14027673Sbde blocksize = nbytes; 14127659Spst if (blocksize < MINSIZE) 14227659Spst blocksize = MINSIZE; 14327659Spst INTOFF; 14427659Spst sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize); 14527659Spst sp->prev = stackp; 14627659Spst stacknxt = sp->space; 14727659Spst stacknleft = blocksize; 14827659Spst stackp = sp; 14911136Swollman INTON; 15011468Sbde } 15111136Swollman p = stacknxt; 15227659Spst stacknxt += nbytes; 15311136Swollman stacknleft -= nbytes; 1541638Srgrimes return p; 1551844Swollman} 15611623Sbde 15774806Sru 15874806Sruvoid 15911136Swollmanstunalloc(p) 16018314Speter pointer p; 16174806Sru { 16227659Spst if (p == NULL) { /*DEBUG */ 16374806Sru write(2, "stunalloc\n", 10); 16427673Sbde abort(); 16527659Spst } 16674806Sru stacknleft += stacknxt - (char *)p; 16727659Spst stacknxt = p; 16818314Speter} 16918314Speter 17074806Sru 17174806Sru 17274806Sruvoid 17374806Srusetstackmark(mark) 17474806Sru struct stackmark *mark; 17574806Sru { 17674806Sru mark->stackp = stackp; 17774806Sru mark->stacknxt = stacknxt; 17874806Sru mark->stacknleft = stacknleft; 17974806Sru} 18074806Sru 18127673Sbde 18274806Sruvoid 18327659Spstpopstackmark(mark) 18474806Sru struct stackmark *mark; 18527659Spst { 18618314Speter struct stack_block *sp; 18727659Spst 1881844Swollman INTOFF; 18974806Sru while (stackp != mark->stackp) { 19074806Sru sp = stackp; 19174806Sru stackp = sp->prev; 19227673Sbde ckfree(sp); 19327659Spst } 19474806Sru stacknxt = mark->stacknxt; 19574806Sru stacknleft = mark->stacknleft; 19627659Spst INTON; 1971844Swollman} 1981844Swollman 19911468Sbde 20020935Swosch/* 20115902Swosch * When the parser reads in a string, it wants to stick the string on the 20215902Swosch * stack and only adjust the stack pointer when it knows how big the 20315902Swosch * string is. Stackblock (defined in stack.h) returns a pointer to a block 20415902Swosch * of space on top of the stack and stackblocklen returns the length of 20515902Swosch * this block. Growstackblock will grow this space by at least one byte, 20615902Swosch * possibly moving it (like realloc). Grabstackblock actually allocates the 20715902Swosch * part of the block that has been used. 20815902Swosch */ 20915902Swosch 21015902Swoschvoid 2112353Sbdegrowstackblock() { 21223546Swosch char *p; 2131844Swollman int newlen = ALIGN(stacknleft * 2 + 100); 21415902Swosch char *oldspace = stacknxt; 21527673Sbde int oldlen = stacknleft; 21627659Spst struct stack_block *sp; 21727659Spst 21827659Spst if (stacknxt == stackp->space && stackp != &stackbase) { 21927659Spst INTOFF; 22027659Spst sp = stackp; 22127659Spst stackp = sp->prev; 22227659Spst sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen); 22327659Spst sp->prev = stackp; 22427659Spst stackp = sp; 22527659Spst stacknxt = sp->space; 22627659Spst stacknleft = newlen; 22727659Spst INTON; 22827659Spst } else { 22927659Spst p = stalloc(newlen); 2301638Srgrimes memcpy(p, oldspace, oldlen); 23127659Spst stacknxt = p; /* free the space */ 232 stacknleft += newlen; /* we just allocated */ 233 } 234} 235 236 237 238void 239grabstackblock(len) 240 int len; 241{ 242 len = ALIGN(len); 243 stacknxt += len; 244 stacknleft -= len; 245} 246 247 248 249/* 250 * The following routines are somewhat easier to use that the above. 251 * The user declares a variable of type STACKSTR, which may be declared 252 * to be a register. The macro STARTSTACKSTR initializes things. Then 253 * the user uses the macro STPUTC to add characters to the string. In 254 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is 255 * grown as necessary. When the user is done, she can just leave the 256 * string there and refer to it using stackblock(). Or she can allocate 257 * the space for it using grabstackstr(). If it is necessary to allow 258 * someone else to use the stack temporarily and then continue to grow 259 * the string, the user should use grabstack to allocate the space, and 260 * then call ungrabstr(p) to return to the previous mode of operation. 261 * 262 * USTPUTC is like STPUTC except that it doesn't check for overflow. 263 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there 264 * is space for at least one character. 265 */ 266 267 268char * 269growstackstr() { 270 int len = stackblocksize(); 271 if (herefd >= 0 && len >= 1024) { 272 xwrite(herefd, stackblock(), rmquotes(stackblock(), len)); 273 sstrnleft = len - 1; 274 return stackblock(); 275 } 276 growstackblock(); 277 sstrnleft = stackblocksize() - len - 1; 278 return stackblock() + len; 279} 280 281 282/* 283 * Called from CHECKSTRSPACE. 284 */ 285 286char * 287makestrspace() { 288 int len = stackblocksize() - sstrnleft; 289 growstackblock(); 290 sstrnleft = stackblocksize() - len; 291 return stackblock() + len; 292} 293 294 295 296void 297ungrabstackstr(s, p) 298 char *s; 299 char *p; 300 { 301 stacknleft += stacknxt - s; 302 stacknxt = s; 303 sstrnleft = stacknleft - (p - s); 304} 305