home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / smail-3.1.28 / pd / pathalias / mem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-03  |  4.9 KB  |  276 lines

  1. /* Smail SCCS ID: @(#)pd/pathalias/mem.c    1.5 %G 00:43:38 */
  2. /* pathalias -- by steve bellovin, as told to peter honeyman */
  3. #ifndef lint
  4. static char    *sccsid = "@(#)mem.c    9.2 88/06/10";
  5. #endif
  6.  
  7. #include "def.h"
  8.  
  9. /* exports */
  10. long Ncount;
  11. extern void freelink(), wasted(), freetable();
  12. extern long allocation();
  13.  
  14. /* imports */
  15. extern char *Netchars;
  16. extern int Vflag;
  17. #if defined(SMAIL_3) && defined(ANSI_C) && !defined(NO_VOID_SBRK)
  18. extern void *sbrk();
  19. #else
  20. extern char *sbrk();
  21. #endif
  22. extern void die();
  23. #ifndef SMAIL_3
  24. extern int strlen();
  25. #endif
  26.  
  27. /* privates */
  28. STATIC void nomem();
  29. static link *Lcache;
  30. static unsigned int Memwaste;
  31.  
  32. link    *
  33. newlink()
  34. {    register link *rval;
  35.  
  36.     if (Lcache) {
  37.          rval = Lcache;
  38.         Lcache = Lcache->l_next;
  39.         strclear((char *) rval, sizeof(link));
  40.     } else if ((rval = (link * ) calloc(1, sizeof(link))) == 0)
  41.         nomem();
  42.     return rval;
  43. }
  44.  
  45. /* caution: this destroys the contents of l_next */
  46. void
  47. freelink(l)
  48.     link *l;
  49. {
  50.     l->l_next = Lcache;
  51.     Lcache = l;
  52. }
  53.  
  54. node    *
  55. newnode()
  56. {    register node *rval;
  57.  
  58.     if ((rval = (node * ) calloc(1, sizeof(node))) == 0)
  59.         nomem();
  60.     Ncount++;
  61.     return rval;
  62. }
  63.  
  64. char    *
  65. strsave(s)
  66.     char *s;
  67. {    register char *r;
  68.  
  69.     if ((r = malloc((unsigned) strlen(s) + 1)) == 0)
  70.         nomem();
  71.     (void) strcpy(r, s);
  72.     return r;
  73. }
  74.  
  75. #ifndef strclear
  76. void
  77. strclear(str, len)
  78.     register char *str;
  79.     register long len;
  80. {
  81.     while (--len >= 0)
  82.         *str++ = 0;
  83. }
  84. #endif /*strclear*/
  85.  
  86. node    **
  87. newtable(size)
  88.     long size;
  89. {    register node **rval;
  90.  
  91.     if ((rval = (node **) calloc(1, (unsigned int) size * sizeof(node *))) == 0) 
  92.         nomem();
  93.     return rval;
  94. }
  95.  
  96. void
  97. freetable(t, size)
  98.     node **t;
  99.     long size;
  100. {
  101. #ifdef MYMALLOC
  102.     extern void addtoheap();
  103.  
  104.     addtoheap((char *) t, size * sizeof(node *));
  105. #else
  106.     free((char *) t);
  107. #endif
  108. }
  109.  
  110. STATIC void
  111. nomem()
  112. {
  113.     static char epitaph[128];
  114.  
  115.     sprintf(epitaph, "out of memory (%ldk allocated)", allocation());
  116.     die(epitaph);
  117. }
  118.  
  119. /* data space allocation -- main sets `dataspace' very early */
  120. long
  121. allocation()
  122. {
  123.     static char *dataspace;
  124.     long rval;
  125.  
  126.     if (dataspace == 0) {        /* first time */
  127.         dataspace = sbrk(0);    /* &end? */
  128.         return 0;
  129.     }
  130. #ifdef SMAIL_3
  131.     rval = ((char *)sbrk(0) - dataspace)/1024;
  132. #else
  133.     rval = (sbrk(0) - dataspace)/1024;
  134. #endif
  135.     if (rval < 0)            /* funny architecture? */
  136.         rval = -rval;
  137.     return rval;
  138. }
  139.  
  140. /* how much memory has been wasted? */
  141. void
  142. wasted()
  143. {
  144.     if (Memwaste == 0)
  145.         return;
  146.     vprintf(stderr, "memory allocator wasted %ld bytes\n", Memwaste);
  147. }
  148.  
  149. #ifdef MYMALLOC
  150.  
  151. /* use c library malloc/calloc here, and here only */
  152. #undef malloc
  153. #undef calloc
  154.  
  155. /* imports */
  156. #if defined(SMAIL_3) && defined(ANSI_C) && !defined(NO_VOID_MALLOC)
  157. extern void *malloc();
  158. #else
  159. extern char *malloc();
  160. #endif
  161. #if defined(SMAIL_3) && defined(ANSI_C) && !defined(NO_VOID_CALLOC)
  162. extern void *calloc();
  163. #else
  164. extern char *calloc();
  165. #endif
  166.  
  167. /* private */
  168. STATIC int align();
  169.  
  170. /* allocate in MBUFSIZ chunks.  4k works ok (less 16 for malloc quirks). */
  171. #define MBUFSIZ (4 * 1024 - 16)
  172.  
  173. /* 
  174.  * mess with ALIGN at your peril.  longword (== 0 mod 4)
  175.  * alignment seems to work everywhere.
  176.  */
  177.  
  178. #define ALIGN 2
  179.  
  180. typedef struct heap heap;
  181. struct heap {
  182.     heap *h_next;
  183.     long h_size;
  184. };
  185.  
  186. static heap *Mheap;    /* not to be confused with a priority queue */
  187.  
  188. STATIC void
  189. addtoheap(p, size)
  190.     char *p;
  191.     long size;
  192. {    int adjustment;
  193.     heap *pheap;
  194.  
  195.     /* p is aligned, but it doesn't hurt to check */
  196.     adjustment = align(p);
  197.     p += adjustment;
  198.     size -= adjustment;
  199.  
  200.     if (size < 1024)
  201.         return;        /* can't happen */
  202.     pheap = (heap *) p;    /* pheap is shorthand */
  203.     pheap->h_next = Mheap;
  204.     pheap->h_size = size;
  205.     Mheap = pheap;
  206. }
  207.  
  208. /*
  209.  * buffered malloc()
  210.  *    returns space initialized to 0.  calloc isn't used, since
  211.  *    strclear can be faster.
  212.  *
  213.  * free is ignored, except for very large objects,
  214.  * which are returned to the heap with addtoheap(). 
  215.  */
  216.  
  217. #if    defined(SMAIL_3) && defined(ANSI_C) && !defined(NO_VOID_MALLOC)
  218. void    *
  219. #else
  220. char    *
  221. #endif
  222. mymalloc(n)
  223.     register unsigned int n;
  224. {    static unsigned int size; /* how much do we have on hand? */
  225.     static char *mstash;      /* where is it? */
  226.     register char *rval;
  227.  
  228.     if (n >= 1024) {        /* for hash table */
  229.         rval = malloc(n);    /* aligned */
  230.         if (rval)
  231.             strclear(rval, n);
  232.         return rval;
  233.     }
  234.  
  235.     n += align((char *) n);    /* keep everything aligned */
  236.  
  237.     if (n > size) {
  238.         Memwaste += size;    /* toss the fragment */
  239.         /* look in the heap */
  240.         if (Mheap) {
  241.             mstash = (char *) Mheap;    /* aligned */
  242.             size = Mheap->h_size;
  243.             Mheap = Mheap->h_next;
  244.         } else {
  245.             mstash = malloc(MBUFSIZ);    /* aligned */
  246.             if (mstash == 0) {
  247.                 size = 0;
  248.                 return 0;
  249.             }
  250.             size = MBUFSIZ;
  251.         }
  252.         strclear(mstash, size);        /* what if size > 2^16? */
  253.     }
  254.     rval = mstash;
  255.     mstash += n;
  256.     size -= n;
  257.     return rval;
  258. }
  259.  
  260. /*
  261.  * what's the (mis-)alignment of n?  return the complement of
  262.  * n mod 2^ALIGN
  263.  */
  264. STATIC int
  265. align(n)
  266.     char *n;
  267. {    register int abits;    /* misalignment bits in n */
  268.  
  269.     abits = (int) n & ~(0xff << ALIGN) & 0xff;
  270.     if (abits == 0)
  271.         return 0;
  272.     return (1 << ALIGN) - abits;
  273. }
  274.  
  275. #endif /*MYMALLOC*/
  276.