home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 297_01 / pralloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-30  |  17.5 KB  |  603 lines

  1. /* pralloc.c */
  2. /* allocation */
  3. /* 21/12/91 
  4.    dump_stack renamed dump_ancestors 
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include "prtypes.h"
  9.  
  10. #define NDEBUG 1 /* turn off checking */
  11. #define PAIRS_TOGETHER 1 
  12. /* Only pairs are allocated on heap.
  13. * This is useful in the case of 8086 architercture.
  14. * as pairs take up a lot of room.
  15. */
  16. /* define STATISTICS used to see how much each structure takes */
  17. #define DEFAULTSIZE 32000     /* default memory zone size     */
  18. #define BUFFSIZE 1000        /* io buffer sizes        */
  19.  
  20. /* error messages */
  21. #define OVERFLOW "overflow"
  22. #define SUBSTSPACE "substitution stack"
  23. #define DYNSPACE "control stack"
  24. #define TRAILSPACE "trail"
  25. #define HEAPSPACE "heap"
  26. #define STRINGSPACE "string zone"
  27. #define TEMPSPACE "temp"
  28. #define SEESTACK "Stack dump?(y/n)"
  29. #define WILDPOINTER "stray pointer!"
  30.  
  31. /* byte alignment */
  32. #define ALIGN(X) X>>=2,X<<=2,X+=4;
  33.  
  34. /* #define CAN_ALLOC(HOWMUCH, MAXPTR, CURRPTR)  (((MAXPTR)-(CURRPTR)) > HOWMUCH)*/
  35. #define CAN_ALLOC(HOWMUCH, MAXPTR, CURRPTR)  ((CURRPTR + HOWMUCH) < MAXPTR)
  36. /* This macro is used in the following circumstance:
  37.  *  MAXPTR is the top of a zone,
  38.  *  CURRPTR is the current pointer in the zone, it is less than MAXPTR.
  39.  *  HOWMUCH is an integer that says how much you want to increase CURRPTR
  40.  *  but you must stay less than MAXPTR.
  41. */
  42.  
  43. #define ADDRESS_DIFF(PTR1, PTR2) (char *)(PTR1) - (char *)(PTR2)
  44. typedef char *void_ptr_t;
  45.  
  46. void alloc_err(), fatal_alloc_err(), clean_pred();
  47.  
  48. #ifdef STATISTICS
  49. /* These numbers let you monitor how much the different 
  50.   * structures consume.
  51.   * It may suprise you to know that integers and variables 
  52.   * consume nothing because they are stored directly in a node.
  53.   */
  54. zone_size_t Atom_consumption;
  55. zone_size_t Pair_consumption;
  56. zone_size_t Node_consumption;
  57. zone_size_t Clause_consumption;
  58. zone_size_t String_consumption;
  59. zone_size_t Predrec_consumption;
  60. #ifdef REAL
  61. zone_size_t Real_consumption;
  62. #endif
  63. #ifdef CHARACTER
  64. zone_size_t Char_consumption;
  65. #endif
  66. #endif
  67.  
  68.  
  69. char *Read_buffer;        /* read tokens into this */
  70. char *Print_buffer;        /* used by pr_string */
  71. clause_ptr_t Bltn_pseudo_clause; /* see prlush.c  */
  72. node_ptr_t Printing_var_nodeptr; /* see prprint.c */
  73.  
  74. static char *Heap_mem; /* bottom of heap */
  75. static char *Heap_ptr; /* allocate from this and move this up */
  76. static char *HighHeap_ptr; /* top of heap */
  77.  
  78. static char *Str_mem; /* this is used to allocate permanent strings 
  79.             and perhaps other objects if you want to keep the pairs
  80.             together
  81.             */
  82. static char *Str_ptr; /* allocate from this and move this up */
  83. static char *HighStr_ptr; /* top of zone */
  84.  
  85. dyn_ptr_t Dyn_mem; /* bottom of control stack 
  86.            (and zone for those temporary objects that disappear on backtrack,
  87.             although the substitution zone could do as well) */
  88. dyn_ptr_t Dyn_ptr; /* allocate from this and move this up */
  89. dyn_ptr_t HighDyn_ptr; /* top of control stack */
  90.  
  91. node_ptr_t **Trail_mem; /* the trail (used to reset variable bindings) */
  92. node_ptr_t **Trail_ptr; /* like the others */
  93. node_ptr_t **HighTrail_ptr;/* top of zone */
  94.  
  95. subst_ptr_t Subst_mem; /* bottom of (global) variable bindings stack */
  96. subst_ptr_t Subst_ptr; /* allocate from this and move this up */
  97. subst_ptr_t HighSubst_ptr;/* top of zone */
  98.  
  99. temp_ptr_t Temp_mem; /*  For things you might want to 
  100.             create with temp_assert...
  101.             clean with clean_temp */
  102. temp_ptr_t Temp_ptr; /* allocate from this and move this up */
  103. temp_ptr_t HighTemp_ptr;/* top of zone */
  104.  
  105. int    Max_Readbuffer, Max_Printbuffer;
  106.  
  107. atom_ptr_t Nil;
  108. node_ptr_t NilNodeptr;
  109.  
  110. /*******************************************************************************
  111.             ini_alloc()
  112.  Reserve zones and io buffers. 
  113.  ******************************************************************************/
  114. void ini_alloc()
  115. {
  116.     zone_size_t heap_size, str_size, dyn_size, trail_size, subst_size, temp_size;
  117.     extern void_ptr_t os_alloc(); /* see the machine dependent file */
  118.     extern int read_config();   /* see the machine dependent file */
  119.  
  120.     if(!read_config(&heap_size, &str_size, &dyn_size, &trail_size, &subst_size, &temp_size,
  121.         &Max_Readbuffer, &Max_Printbuffer))
  122.     {
  123.         heap_size = DEFAULTSIZE;
  124.         str_size = DEFAULTSIZE;
  125.         dyn_size = DEFAULTSIZE;
  126.         trail_size = DEFAULTSIZE;
  127.         subst_size = DEFAULTSIZE;
  128.         temp_size = DEFAULTSIZE;
  129.         Max_Readbuffer = BUFFSIZE;
  130.         Max_Printbuffer =  BUFFSIZE;
  131.     }
  132.  
  133.     Heap_mem = os_alloc(heap_size);
  134.     Heap_ptr = Heap_mem;
  135.     HighHeap_ptr = Heap_mem + heap_size;
  136.  
  137.     Str_mem = os_alloc(str_size);
  138.     Str_ptr = Str_mem;
  139.     HighStr_ptr = Str_mem + str_size;
  140.  
  141.     Dyn_mem = (dyn_ptr_t)os_alloc(dyn_size);
  142.     Dyn_ptr = Dyn_mem;
  143.     HighDyn_ptr = (dyn_ptr_t)((char *)Dyn_mem + dyn_size);
  144.  
  145.     Trail_mem = (node_ptr_t **)os_alloc(trail_size);
  146.     Trail_ptr = Trail_mem;
  147.     HighTrail_ptr = (node_ptr_t **)((char *)Trail_mem + trail_size);
  148.  
  149.  
  150.     Subst_mem = (subst_ptr_t)os_alloc(subst_size);
  151.     Subst_ptr = Subst_mem;
  152.     HighSubst_ptr = (subst_ptr_t)((char *)Subst_mem + subst_size);
  153.     while(Subst_ptr < HighSubst_ptr)
  154.     {
  155.         Subst_ptr->skel = (node_ptr_t)NULL;
  156.         Subst_ptr++;
  157.     }
  158.  
  159.     Subst_ptr = Subst_mem;
  160.  
  161.     Temp_mem = (temp_ptr_t)os_alloc(temp_size);
  162.     Temp_ptr = Temp_mem;
  163.     HighTemp_ptr = (temp_ptr_t)((char *)Temp_mem + temp_size);
  164.  
  165.     Read_buffer = os_alloc((zone_size_t)Max_Readbuffer);
  166.     Print_buffer = os_alloc((zone_size_t)Max_Printbuffer);
  167. }
  168.  
  169. /*******************************************************************************
  170.             my_Heap_alloc()
  171.  ******************************************************************************/
  172. static void_ptr_t my_Heap_alloc(how_much)
  173. my_alloc_size_t how_much;
  174. {
  175.     void_ptr_t ret;
  176.     ALIGN(how_much);
  177.  
  178.     if(!CAN_ALLOC(how_much ,HighHeap_ptr, Heap_ptr))
  179.     {
  180.         fatal_alloc_err(HEAPSPACE);
  181.     }
  182.     else
  183.         ret = Heap_ptr;
  184.     Heap_ptr += how_much;
  185.     return(ret);
  186. }
  187.  
  188. /*******************************************************************************
  189.             my_Str_alloc()
  190. Allocate on permanent string space. 
  191.  ******************************************************************************/
  192. static void_ptr_t my_Str_alloc(how_much)
  193. my_alloc_size_t how_much;
  194. {
  195.     void_ptr_t ret;
  196.     ALIGN(how_much);
  197.  
  198.     if(!(CAN_ALLOC(how_much, HighStr_ptr, Str_ptr)))
  199.     {
  200.         fatal_alloc_err(STRINGSPACE);
  201.     }
  202.     else
  203.         ret = Str_ptr;
  204.     Str_ptr += how_much;
  205.     return(ret);
  206. }
  207.  
  208. /********************************************************************************
  209.             my_Dyn_alloc()
  210. Allocate on the control stack. 
  211. This is for objects that disappear on backtracking.
  212.  ******************************************************************************/
  213. dyn_ptr_t my_Dyn_alloc(how_much)
  214. my_alloc_size_t how_much; /* in bytes */
  215. {
  216.     dyn_ptr_t ret;
  217.     ALIGN(how_much);
  218.     if(!(CAN_ALLOC(how_much ,HighDyn_ptr, Dyn_ptr)))
  219.     {
  220.         alloc_err(DYNSPACE);
  221.     }
  222.     else
  223.         ret = Dyn_ptr;
  224.     Dyn_ptr += how_much;
  225.     return(ret);
  226. }
  227.  
  228. /*******************************************************************************
  229.             my_Trail_alloc()
  230.  Allocate one trail element.
  231.  ******************************************************************************/
  232. node_ptr_t ** my_Trail_alloc()
  233. {
  234.     node_ptr_t ** ret;
  235.  
  236.     if( Trail_ptr >= HighTrail_ptr)
  237.     {
  238.         alloc_err(TRAILSPACE);
  239.     }
  240.     else
  241.         ret = Trail_ptr;
  242.     Trail_ptr ++;
  243.     return(ret);
  244. }
  245.  
  246. /*******************************************************************************
  247.             my_Subst_alloc()
  248. Allocate how_much bytes on the substitution stack.
  249. This is more speed-efficient than allocating struct substs on an array of 
  250.  structures, as there is no multiplication.
  251.  ******************************************************************************/
  252. subst_ptr_t my_Subst_alloc(how_much)
  253. my_alloc_size_t how_much; /* in bytes */
  254. {
  255.     subst_ptr_t ret;
  256. #ifndef  NDEBUG
  257.     if(how_much % sizeof(struct subst))INTERNAL_ERROR("alignment");
  258. #endif    
  259.     if(! CAN_ALLOC(how_much ,HighSubst_ptr, Subst_ptr))
  260.     {
  261.         alloc_err(SUBSTSPACE);
  262.     }
  263.     else
  264.         ret = Subst_ptr;
  265.     Subst_ptr += how_much;
  266.     return(ret);
  267. }
  268.  
  269. /********************************************************************************
  270.             my_Temp_alloc()
  271. Allocate in temporary memory.
  272. This is for objects that disappear
  273. when you clean that zone.
  274.  ******************************************************************************/
  275. temp_ptr_t my_Temp_alloc(how_much)
  276. my_alloc_size_t how_much; /* in bytes */
  277. {
  278.     temp_ptr_t ret;
  279.     ALIGN(how_much);
  280.     if(!(CAN_ALLOC(how_much, HighTemp_ptr, Temp_ptr)))
  281.     {
  282.         fatal_alloc_err(TEMPSPACE);
  283.     }
  284.     else
  285.         ret = Temp_ptr;
  286.     Temp_ptr += how_much;
  287.     return(ret);
  288. }
  289.  
  290. /*******************************************************************************
  291.             my_alloc()
  292.  Allocate anywhere.
  293.  ******************************************************************************/
  294. char *my_alloc(how_much, status)
  295. my_alloc_size_t how_much;
  296. int status;
  297. {
  298. #ifdef DEBUG
  299. char buff[80];
  300. sprintf(buff, "my_alloc allocating %d of type %d\n",
  301. #endif
  302.     switch(status)
  303.     {
  304.     case PERMANENT:
  305.         return(my_Heap_alloc(how_much));
  306.     case DYNAMIC:
  307.         return(my_Dyn_alloc(how_much));
  308.     case TEMPORARY:
  309.         return(my_Temp_alloc(how_much));
  310.     case PERM_STRING:
  311.         return(my_Str_alloc(how_much));
  312.     default:
  313.         INTERNAL_ERROR("status");
  314.         return(NULL);/* for lint */
  315.     }
  316. }
  317.  
  318. /*******************************************************************************
  319.             offset_subst()
  320.  Check your compiler on this !! This should return the difference
  321.  between two far pointers 
  322.  ******************************************************************************/
  323.  
  324. long offset_subst(substptr)
  325. subst_ptr_t substptr;
  326. {
  327.     return((long)(substptr - (subst_ptr_t)Subst_mem));
  328. }
  329.  
  330. /*******************************************************************************
  331.             get_string()
  332. Allocate a string of length (how_much - 1)
  333.  ******************************************************************************/
  334. string_ptr_t get_string(how_much, status)
  335. my_alloc_size_t how_much;
  336. {
  337. #ifdef STATISTICS
  338.     String_consumption += how_much;
  339. #endif
  340.     return((string_ptr_t)my_alloc(how_much, status));
  341. }
  342.  
  343. #ifdef REAL
  344. /*******************************************************************************
  345.             get_real()
  346.  There is no need for a get_integer, as integers fit in a node.
  347.  ******************************************************************************/
  348. real_ptr_t get_real(status)
  349. {
  350. #ifdef STATISTICS
  351.     Real_consumption += sizeof(real);
  352. #endif
  353. #ifdef PAIRS_TOGETHER
  354.     if(status == PERMANENT)status = PERM_STRING;
  355. #endif
  356.     return((real_ptr_t)my_alloc((my_alloc_size_t)sizeof(real), status));
  357. }
  358. #endif
  359.  
  360. /*******************************************************************************
  361.             get_atom();
  362.  ******************************************************************************/
  363. atom_ptr_t get_atom(status)
  364. {
  365. #ifdef STATISTICS
  366.     Atom_consumption += sizeof(struct atom);
  367. #endif
  368. #ifdef PAIRS_TOGETHER
  369.     if(status == PERMANENT)status = PERM_STRING;
  370. #endif
  371.     return((atom_ptr_t)my_alloc((my_alloc_size_t)sizeof(struct atom), status));
  372. }
  373.  
  374. /*******************************************************************************
  375.             get_pair()
  376.  ******************************************************************************/
  377. pair_ptr_t get_pair(status)
  378. {
  379. #ifdef STATISTICS
  380.     Pair_consumption += sizeof(struct pair);
  381. #endif
  382.     return((pair_ptr_t)my_alloc((my_alloc_size_t)sizeof(struct pair), status));
  383. }
  384.  
  385. /*******************************************************************************
  386.             get_node()
  387. It might be an idea to actually allocate a pair and return the pointer 
  388. to the head. This would simplify garbage collection.
  389.  ******************************************************************************/
  390. node_ptr_t get_node(status)
  391. {
  392. #ifdef STATISTICS
  393.     Node_consumption += sizeof(struct node);
  394. #endif
  395. #ifdef PAIRS_TOGETHER
  396.     if(status == PERMANENT)status = PERM_STRING;
  397. #endif
  398.     return((node_ptr_t)my_alloc((my_alloc_size_t)sizeof(struct node), status));
  399. }
  400.  
  401. /*******************************************************************************
  402.              get_clause();
  403.  Allocate a clause.
  404.  ******************************************************************************/
  405. clause_ptr_t get_clause(status)
  406. {
  407. clause_ptr_t result;
  408. #ifdef STATISTICS
  409.     Clause_consumption += sizeof(struct clause);
  410. #endif
  411. #ifdef PAIRS_TOGETHER
  412.     if(status == PERMANENT)status = PERM_STRING;
  413. #endif
  414. result = (clause_ptr_t) my_alloc((my_alloc_size_t)sizeof(struct clause), status);
  415. if(status == TEMPORARY)
  416.   CLAUSEPTR_FLAGS(result) = 0x1;
  417. else
  418.   CLAUSEPTR_FLAGS(result) = 0x0;
  419.     return( result );
  420. }
  421.  
  422. /*******************************************************************************
  423.                 get_pred()
  424. This is called whenever a new predicate is defined.
  425.  ******************************************************************************/
  426. pred_rec_ptr_t get_pred()
  427. {
  428.     pred_rec_ptr_t ret;
  429.     int status = PERMANENT;
  430.  
  431. #ifdef STATISTICS
  432.     Predrec_consumption += sizeof(struct predicate_record);
  433. #endif
  434. #ifdef PAIRS_TOGETHER
  435.     if(status == PERMANENT)status = PERM_STRING;
  436. #endif
  437.     ret = (pred_rec_ptr_t)my_alloc((my_alloc_size_t)sizeof(struct predicate_record), status);
  438.     ret->next_pred = NULL;
  439.     ret->atom = Nil;
  440.     return(ret);
  441. }
  442.  
  443. /*******************************************************************************
  444.                 alloc_err()
  445.  ******************************************************************************/
  446. void alloc_err(s)
  447. char *s;
  448. {
  449.     extern dyn_ptr_t Parent;
  450.     char msg[100];
  451.  
  452.     sprintf(msg, "%s %s\n", s, OVERFLOW);
  453.     errmsg(msg);
  454.     tty_pr_string(SEESTACK);
  455.     if(read_yes())
  456.       dump_ancestors(Parent);
  457.     exit_term();
  458.     exit(1);
  459. }
  460. /*******************************************************************************
  461.             fatal_alloc_err()
  462.  ******************************************************************************/
  463. void fatal_alloc_err(s)
  464. char *s;
  465. {
  466.     extern dyn_ptr_t Parent;
  467.     char msg[100];
  468.  
  469.     sprintf(msg, "%s %s\n", s, OVERFLOW);
  470.     errmsg(msg);
  471.     exit_term();
  472.     exit(1);
  473. }
  474. /*******************************************************************************
  475.             check_object()
  476. This should be used to check the internal consistency of the interpreter.
  477. It doesnt make much sense on an IBM PC, because you can only meaningfully 
  478. compare pointers from the same segment.
  479.  ******************************************************************************/
  480. int check_object(objptr)
  481. char *objptr;
  482. {
  483.     if(((objptr >= HighHeap_ptr)||(objptr < Heap_mem))
  484.         && ((objptr >= HighDyn_ptr)||(objptr < Dyn_mem))
  485.         && ((objptr >= HighTemp_ptr)||(objptr < Temp_mem))
  486.         && ((objptr >= HighStr_ptr)||(objptr < Str_mem))
  487.         )
  488.     {
  489.         errmsg(WILDPOINTER);
  490.  
  491. #ifndef HUNTBUGS
  492.         exit_term();
  493.                 exit(1);
  494. #endif
  495.         return(0);
  496.     }
  497.     else
  498.     return(1);
  499. }
  500.  
  501.  
  502. /*********************************************************************
  503.             clean_temp()
  504. Clean the temporary zone.
  505. ***************************************************************************************************************************************/
  506. void clean_temp()
  507. {
  508.     extern pred_rec_ptr_t First_pred;
  509.     extern atom_ptr_t LastBuiltin;
  510.     pred_rec_ptr_t predptr;
  511.  
  512.     for(predptr = First_pred; predptr != NULL; predptr = predptr->next_pred)
  513.     {
  514.         if(predptr->atom > LastBuiltin)
  515.             clean_pred(predptr->atom);
  516.     }/* for */
  517.     Temp_ptr = Temp_mem;
  518. }
  519.  
  520. /*********************************************************************
  521.             clean_pred()
  522. Clean all temporary clauses from an atom.
  523. ***************************************************************************************************************************************/
  524. void clean_pred(atomptr)
  525. atom_ptr_t atomptr;
  526. {
  527.     clause_ptr_t previous, first, clauseptr;
  528. #ifdef DEBUG
  529.     tty_pr_string(ATOMPTR_NAME (atomptr));
  530.     tty_pr_string(" cleaned \n");
  531. #endif
  532.     clauseptr = ATOMPTR_CLAUSE(atomptr);
  533.     first = clauseptr;
  534.     while(first != NULL && IS_TEMPORARY_CLAUSE(first))
  535.     {
  536.         first = CLAUSEPTR_NEXT(first);
  537.     }
  538.     ATOMPTR_CLAUSE(atomptr) = first;
  539.     if(first == NULL)return;
  540.     else
  541.         clauseptr = first;
  542.     while(clauseptr)
  543.     {
  544.         while(clauseptr && !(IS_TEMPORARY_CLAUSE(clauseptr)))
  545.         {
  546.             previous = clauseptr;
  547.             clauseptr = CLAUSEPTR_NEXT(clauseptr);
  548.         }
  549.         if(clauseptr == NULL)return;
  550.         else
  551.             while(clauseptr && IS_TEMPORARY_CLAUSE(clauseptr))
  552.             {
  553.                 clauseptr = CLAUSEPTR_NEXT(clauseptr);
  554.             }
  555.         CLAUSEPTR_NEXT(previous) = clauseptr;
  556.     }
  557. }
  558.  
  559. /*********************************************************************************
  560.             space_left()
  561.  
  562.  ********************************************************************************/
  563. void space_left(ph, pstr, pd, ps, ptr, pte)
  564. zone_size_t *ph, *pstr, *pd, *ps, *ptr, *pte;
  565. {
  566.     *ph = ADDRESS_DIFF(HighHeap_ptr, Heap_ptr);
  567.     *pstr = ADDRESS_DIFF(HighStr_ptr, Str_ptr);
  568.     *pd = ADDRESS_DIFF(HighDyn_ptr, Dyn_ptr);
  569.     *ps = ADDRESS_DIFF(HighTrail_ptr, Trail_ptr);
  570.     *ptr = ADDRESS_DIFF(HighSubst_ptr, Subst_ptr);
  571.     *pte = ADDRESS_DIFF(HighTemp_ptr, Temp_ptr);
  572. }
  573.  
  574. /*******************************************************************************
  575.             ini_globals().
  576. This is where global structures that are used everywhere are allocated 
  577.  ******************************************************************************/
  578. void ini_globals()
  579. {
  580.     extern FILE * Curr_infile, *Curr_outfile;
  581.     extern node_ptr_t Printing_var_nodeptr;
  582.     atom_ptr_t intern();
  583.  
  584.     Nil = intern("()");
  585.  
  586.     Curr_infile = stdin; /* Initially all input is from terminal */
  587.     Curr_outfile = stdout;/* Initially all output is to terminal */
  588.  
  589.     NilNodeptr = get_node(PERMANENT);
  590.     NODEPTR_TYPE(NilNodeptr) = ATOM;
  591.     NODEPTR_ATOM(NilNodeptr) = Nil;
  592.  
  593.     Bltn_pseudo_clause = get_clause(PERMANENT);/* see prlush.c */
  594.     CLAUSEPTR_GOALS(Bltn_pseudo_clause) = NilNodeptr;
  595.     CLAUSEPTR_HEAD(Bltn_pseudo_clause) = NilNodeptr;
  596.  
  597.     Printing_var_nodeptr = get_node(PERMANENT); /* used by pr_solution */
  598.     NODEPTR_TYPE(Printing_var_nodeptr) = VAR;
  599. }
  600.  
  601. /* end of file */
  602.  
  603.