home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 357_01 / cstar1.exe / MEM.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  11KB  |  519 lines

  1. /*
  2.     C* -- Memory management routines and node allocation routines.
  3.  
  4.     source:  mem.c
  5.     started: September 20, 1985
  6.     version:
  7.         May 8, 1987
  8.         March 7, 1989
  9.  
  10.     PUBLIC DOMAIN SOFTWARE
  11.  
  12.     The CSTAR program was placed in    the public domain on June 15, 1991,
  13.     by its author and sole owner,
  14.  
  15.         Edward K. Ream
  16.         1617 Monroe Street
  17.         Madison, WI 53711
  18.         (608) 257-0802
  19.  
  20.     CSTAR may be used for any commercial or non-commercial purpose.
  21.  
  22.     See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
  23. */
  24. #include "cstar.h"
  25.  
  26. /*
  27.     ----- NODE ALLOCATION ROUTINES -----
  28. */
  29. struct node *    new_pnode    (int size);
  30. void *        node_dupl    (byte *s, int size);
  31. struct type_node *
  32.         new_tnode    (void);
  33. struct node *    new_cnode    (void);
  34. struct node *    new_rloc    (int regfield);
  35. struct node *    new_grloc    (int regfield);
  36. struct node *    new_cloc    (long constant);
  37. struct node *    new_clabel    (void);
  38. struct node *    new_culabel    (char * symbol);
  39. struct iblock *    new_iblock    (unsigned long size);
  40. void *        mg_alloc    (int n);
  41. void        mg_free        (char *p);
  42. void *        ml_alloc    (int n);
  43. void        ml_release    (void);
  44. void        mm_init        (void);
  45. void        mm_stat        (void);
  46.  
  47. /*
  48.       Create a parse node which is generally compatible with other nodes
  49.     contained within expressions, and then get_token().
  50.  
  51.     node is zero-filled.
  52. */
  53. struct node *
  54. new_pnode(int size)
  55. {
  56.     register struct node *p;
  57.  
  58.     TRACEPB("new_pnode", printf("(%d)\n", size));
  59.  
  60.     /* allocate the node */
  61.     p = (struct node *) ml_alloc(size);
  62.     p -> n_type    = t_type;
  63.     p -> n_linno   = t_line;
  64.  
  65.     RETURN_PTR("new_pnode", p);
  66. }
  67.  
  68. /*
  69.     Reproduce a parse node
  70. */
  71. void *
  72. node_dupl(register byte *s, register int size)
  73. {
  74.     register byte *d, *dd;
  75.     register int i;
  76.  
  77.     TRACEPB("node_dupl", printf("(%s, %d)\n", s, size));
  78.  
  79.     if (sizeof(int) == 2) {
  80.         i = size >> 1;
  81.     }
  82.     else {
  83.         fatal("mem: node_dupl: check sizeof(int)");
  84.     }
  85.     d = dd = ml_alloc(size);
  86.  
  87.     while (i--) {
  88.         *((int *)d)++ = *((int *)s)++;
  89.     }
  90.     RETURN_PTR("node_dupl", dd);
  91. }
  92.  
  93. /*
  94.     Create a new type_node, and fill it as though it is a base
  95.     integer type, so as to help prevent crashes from unset
  96.     entries.
  97.  
  98.     type_nodes are always to be copied if they need to
  99.     be altered in a context separate from their creation,
  100.     since there may always be more than one link into any
  101.     given node
  102.         
  103.     node is zero filled
  104. */
  105. struct type_node *
  106. new_tnode(void)
  107. {
  108.     register struct type_node *t;
  109.  
  110.     TICKB("new_tnode");
  111.  
  112.     switch(scope.s_scope) {
  113.  
  114.     case FILE_SCOPE:
  115.     case FNDEF_SCOPE:
  116.         TRACEP("new_tnode", printf("global\n"));
  117.         t = (struct type_node *) mg_alloc(sizeof(struct type_node));
  118.         break;
  119.  
  120.     default:
  121.         t = (struct type_node *) ml_alloc(sizeof(struct type_node));
  122.         break;
  123.     }
  124.     t -> t_typtok = INT_TYPE;
  125.     t -> t_tsize = 2L;
  126.  
  127.     RETURN_PTR("new_tnode", t);
  128. }
  129.  
  130. /*
  131.     Allocate a new code node with two arg fields.
  132.     CAUTION: the peephole requires that nodes be of uniform size,
  133.     since it occasionally adds an argument to a node.
  134. */
  135. struct node *
  136. new_cnode(void)
  137. {
  138.     register struct node *p;
  139.  
  140.     TICKB("new_cnode");
  141.  
  142.     p = (struct node *) ml_alloc(sizeof(struct code_node));
  143.  
  144.     RETURN_PTR("new_cnode", p);
  145. }
  146.  
  147. /*
  148.     Allocate a loc node standing for a register.
  149. */
  150. struct node *
  151. new_rloc(register int regfield)
  152. {
  153.     register struct node *p;
  154.  
  155.     TRACEPB("new_rloc", printf("(%d)\n", regfield));
  156.  
  157.     p = (struct node *) ml_alloc(sizeof (struct loc_node));
  158.     p -> n_linno   = t_line;
  159.  
  160.     p -> n_type = ID_TOK;
  161.     p -> n_reg1 = regfield;
  162.  
  163.     RETURN_PTR("new_rloc", p);
  164. }
  165.  
  166. struct node *
  167. new_grloc(register int regfield)
  168. {
  169.     register struct node *p;
  170.  
  171.     TRACEPB("new_grloc", printf("(%d)\n", regfield));
  172.  
  173.     p = (struct node *) mg_alloc(sizeof (struct loc_node));
  174.     p -> n_linno = t_line;
  175.  
  176.     p -> n_type = ID_TOK;
  177.     p -> n_reg1 = regfield;
  178.  
  179.     RETURN_PTR("new_grloc", p);
  180. }
  181.  
  182. /*
  183.     Allocate a loc node standing for a constant.
  184. */
  185. struct node *
  186. new_cloc(long constant)
  187. {
  188.     register struct node *p;
  189.  
  190.     TRACEPB("new_cloc", printf("(%ld)\n", constant));
  191.  
  192.     p = (struct node *) ml_alloc(sizeof (struct loc_node));
  193.     p -> n_linno   = t_line;
  194.  
  195.     p -> n_type = ID_TOK;
  196.     p -> n_const = constant;
  197.  
  198.     RETURN_PTR("new_cloc", p);
  199. }
  200.  
  201. /*
  202.     Return a pointer to a new internal label code node.
  203.     All fields are filled in with default values.
  204. */
  205. struct node *
  206. new_clabel(void)
  207. {
  208.     register struct node *p;
  209.  
  210.     TICKB("new_clabel");
  211.  
  212.     p = (struct node *) ml_alloc(sizeof(struct clabel_node));
  213.  
  214.     p -> c_code     = O_LABEL;    /* Header fields. */
  215.     p -> c_mark    = FALSE;    /* Non-header fields. */
  216.     p -> c_labnum   = ++cur_lab;
  217.  
  218.     RETURN_PTR("new_clabel", p);
  219. }
  220.  
  221. /*
  222.     Return a pointer to a new internal label code node.
  223.     All fields are filled in with default values.
  224. */
  225. struct node *
  226. new_culabel(char * symbol)
  227. {
  228.     register struct node *p;
  229.  
  230.     TRACEPB("new_culabel", printf("(%s)\n", symbol));
  231.  
  232.     p = (struct node *) ml_alloc(sizeof(struct culabel_node));
  233.  
  234.     p -> c_code     = O_ULABEL;    /* Header fields. */
  235.     p -> c_mark    = FALSE;    /* Non-header fields. */
  236.     p -> c_labsym   = str_lalloc(symbol);
  237.     p -> c_labnum     = ++u_lab;    /* First assignment is 1! */
  238.  
  239.     RETURN_PTR("new_culabel", p);
  240. }
  241.  
  242. /*
  243.     Return an initializer block of a given data size, measured in long
  244.     entries.  These blocks are made in the local scope even for file
  245.     scope initializers.  If it becomes necessary to group initializers,
  246.     these blocks will have to be made in file scope, as will all
  247.     declarations, typenodes, etc.
  248. */
  249. struct iblock *
  250. new_iblock(unsigned long size)
  251. {
  252.     register struct iblock *p;
  253.  
  254.     TRACEPB("new_iblock", printf("(%lu)\n", size));
  255.  
  256.     if (size > IDATA_SIZE) {
  257.         size = IDATA_SIZE;
  258.     }
  259.     p = (struct iblock *) ml_alloc( (unsigned int) 
  260.         (sizeof(*p) + sizeof(p -> idata[0]) * (unsigned int) size) );
  261.     p -> idim = size;
  262.  
  263.     RETURN_PTR("new_iblock", p);
  264. }
  265.  
  266. /*
  267.     ----- MEMORY ALLOCATION ROUTINES -----
  268.  
  269.     These routines handle two kinds of memory:
  270.  
  271.     local memory:
  272.  
  273.     This memory is deallocated at the end of every function.
  274.  
  275.     The ml_alloc() routine gets local memory.
  276.     The ml_release() routine releases ALL local memory.
  277.  
  278.     The local memory is obtained from the system in fixed-sized chunks.
  279.     Each chunk contains a pointer to the next chunk.
  280.     The ml_alloc() routine allocates another chunk if needed, then returns
  281.     a pointer into the latest chunk.
  282.     The ml_release() routine just releases all chunks.
  283.  
  284.     global memory:
  285.  
  286.     This memory is used for global information that is NEVER deallocated.
  287.     It is also possible to use this memory for temporary memory, although
  288.     it is more efficient to use local memory if not too much is needed.
  289.  
  290.     The mg_alloc() routine gets global memory.
  291.     The mg_free() routine releases memory obtained by mg_free().
  292.  
  293.     This memory is allocated and released using alloc() and free().
  294. */
  295.  
  296.  
  297. /*
  298.     Define variables used by this routine.
  299. */
  300.  
  301. static struct chunk {
  302.     struct chunk * mm_next;        /* Next pointer    */
  303.     char     mm_data [DATA_SIZE];    /* Data area    */
  304. };
  305.  
  306. static struct chunk * local_list;
  307. static struct chunk * free_list;
  308.  
  309. static long   ml_c;    /* Current local count.        */
  310. static char * ml_p;    /* Current local pointer.    */
  311.  
  312. static long g_tot;    /* Total global memory allocated.    */
  313. static long l_tot;    /* Cumulative local memory allocation.    */
  314. static long l_blocks;    /* Non-cumulative local chunks allocated.    */
  315.  
  316.  
  317. /*
  318.     Allocate n bytes using calloc(), assumed to get memory from system
  319.  
  320.     The returned memory IS zeroed.
  321. */
  322. void *
  323. mg_alloc(int n)
  324. {
  325.     register byte *p;
  326.  
  327.     TRACEPB("mg_alloc", printf("(%d) ", n));
  328.  
  329.     /* Align the request now. */
  330.     while (n & (sizeof(short int)-1) ) {
  331.         n++;
  332.     }
  333.  
  334.     p = calloc(1, n);
  335.     if (p == NULL) {
  336.         printf("sorry, out of memory\n");
  337.         printf("%ld (0x%lx) bytes allocated\n", g_tot, g_tot);
  338.         exit(0);
  339.     }
  340.  
  341.     /* Update statistic. */
  342.     g_tot += (long)n;
  343.  
  344.     RETURN_PTR("mg_alloc", p);
  345. }
  346.  
  347.  
  348. /*
  349.     Free memory allocated by mg_alloc().
  350. */
  351. void
  352. mg_free(char *p)
  353. {
  354.     TRACEP("mg_free", printf("(%p)\n", p));
  355.  
  356.     free(p);
  357. }
  358.  
  359. /*
  360.     Allocate bytes from local memory area.
  361.     Return pointer to allocated area or NULL.
  362. */
  363. void *
  364. ml_alloc(register int n)
  365. {
  366.     register byte *p;
  367.     register int x;
  368.     struct chunk *cp;
  369.  
  370.     /* Align the request now. */
  371.  
  372.     TRACEPB("ml_alloc", printf("(%d) ", n));
  373.  
  374.     if (n & 1) {
  375.         n++;
  376.     }
  377.  
  378.     /* Check to see if there is room in the current chunk. */
  379.     if ((long)n > ml_c) {
  380.         if (cp = free_list) {
  381.             /* Get block from the free list. */
  382.             free_list = cp -> mm_next;
  383.  
  384.             /* set ml_p to its beginning */
  385.             ml_p      = &((cp -> mm_data)[0]);
  386.  
  387.             /* clear the block */
  388.             p = (void *) ml_p;
  389.             x = DATA_SIZE / sizeof(long);
  390.             do {
  391.                 * ((long *) p)++ = 0L;
  392.             }
  393.             while (--x);
  394.         }
  395.         else {
  396.             /* Get a newly allocated and cleared block. */
  397.             cp = (struct chunk *)mg_alloc(sizeof(struct chunk));
  398.  
  399.             ml_p      = &((cp -> mm_data)[0]);
  400.  
  401.             /* Update statistic. */
  402.             l_blocks++;
  403.         }
  404.         /* Link the block to the local list. */
  405.         cp -> mm_next = local_list;
  406.         local_list      = cp;
  407.  
  408.         ml_c = DATA_SIZE;
  409.  
  410.         /* Check for oversize request. */
  411.         if (n > DATA_SIZE) {
  412.             fatal("ml_alloc: requested chunk too long");
  413.         }
  414.     }
  415.  
  416.     /* Allocate the memory. */
  417.     p = ml_p;
  418.     ml_p  += n;
  419.     ml_c  -= (long)n;
  420.  
  421.     l_tot += (long)n;
  422.  
  423.     RETURN_PTR("ml_alloc", p);
  424. }
  425.  
  426. /* Deallocate all local memory. */
  427. void
  428. ml_release(void)
  429. {
  430.     register struct chunk *p, *q;
  431.  
  432. #ifdef SHERLOCK
  433.     register long c = 0;
  434. #endif /* SHERLOCK */
  435.  
  436.     /* Put all local chunks on the free list. */
  437.  
  438.     TICKB("ml_release");
  439.  
  440.     if (local_list) {
  441.         p = local_list;
  442.         while(p -> mm_next) {
  443.             p = p -> mm_next;
  444.         }
  445.         /* p points to last of local list */
  446.  
  447.         /* Put the local list at the head of the free list. */
  448.         p -> mm_next = free_list;
  449.         free_list    = local_list;
  450.     }
  451.     TRACEP("ml_release",
  452.         p = free_list;
  453.         while (p) {
  454.             c++;
  455.             p = p -> mm_next;
  456.         }
  457.         printf("%ld blocks on free list 0x%lx bytes\n",c, c*DATA_SIZE);
  458.     );
  459.             
  460.  
  461.     /* Initialize. */
  462.     local_list = NULL;
  463.     ml_c = 0L;
  464.     ml_p = NULL;
  465.  
  466.     TICKX("ml_release");
  467. }
  468.  
  469. /* Define TPA block for BDOS get TPA call. */
  470. struct TPAB {
  471.     int    param;    /* 0 for get,  1 or 2 for set */
  472.     char *    low;    
  473.     char *    high;
  474. };
  475.  
  476. /* Define format of the start of the base page. */
  477. struct BASE_PAGE {
  478.     long    lowtpa;
  479.     long    hightpa;
  480.     char *    text_start;
  481.     long    text_length;
  482.     char *    data_start;
  483.     long    data_length;
  484.     char *    bss_start;
  485.     long    bss_length;
  486. };
  487.  
  488. /*
  489.     Initialize the memory manager.
  490. */
  491. void
  492. mm_init(void)
  493. {
  494.     TICK("mm_init");
  495.         
  496.     /* Initialize local memory. */
  497.     local_list = NULL;
  498.     free_list = NULL;
  499.     ml_c = 0;
  500.  
  501.     /* Initialize statistics. */
  502.     g_tot = 0;
  503.     l_tot = 0;
  504.     l_blocks = 0;
  505. }
  506.  
  507. /*
  508.     Print statistics about memory manager.
  509. */
  510. void
  511. mm_stat(void)
  512. {
  513.     SL_DISABLE();
  514.  
  515.     printf("mm_stat: l_tot: %ld (0x%lx), l_blocks: %ld\n",
  516.                         l_tot, l_tot, l_blocks);
  517.     printf("mm_stat: g_tot: %ld (0x%lx)\n", g_tot, g_tot);
  518. }
  519.