Subversion Repositories HelenOS

Rev

Rev 2714 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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