home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume10 / ifp / part06 / interp / node.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-07-06  |  9.8 KB  |  423 lines

  1.  
  2. /****** node.c ********************************************************/
  3. /**                                                                  **/
  4. /**                    University of Illinois                        **/
  5. /**                                                                  **/
  6. /**                Department of Computer Science                    **/
  7. /**                                                                  **/
  8. /**   Tool: IFP                         Version: 0.5                 **/
  9. /**                                                                  **/
  10. /**   Author:  Arch D. Robison          Date:   May 1, 1985          **/
  11. /**                                                                  **/
  12. /**   Revised by: Arch D. Robison       Date:  Nov 23, 1985          **/
  13. /**                                                                  **/
  14. /**   Principal Investigators: Prof. R. H. Campbell                  **/
  15. /**                            Prof. W. J. Kubitz                    **/
  16. /**                                                                  **/
  17. /**                                                                  **/
  18. /**------------------------------------------------------------------**/
  19. /**   (C) Copyright 1987  University of Illinois Board of Trustees   **/
  20. /**                       All Rights Reserved.                       **/
  21. /**********************************************************************/
  22.  
  23. #include <stdio.h>
  24. #include "struct.h"
  25. #include "node.h"
  26. #include "umax.h"
  27. #include "string.h"
  28.  
  29. /********************************* NODE RULES ******************************
  30.  
  31. Function definitions are stored in nodes, which are arranged in a tree
  32. structure mimicking the UNIX file structure.  Below is an example:
  33.  
  34.            Rm
  35.            |
  36.            Am---Bi----Cm-------Dd
  37.            |          |
  38.            Xd         Yd--Zd
  39.  
  40. Rm is the root node, with children Am,Bi,Cm, and Dd. Nodes can be one of three
  41. types: module (m), import (i), or definition (d).  Only definition nodes
  42. have a reference count greater than 1.  Only module nodes have children.
  43.  
  44.  ****************************** end of node rules **************************/
  45.  
  46. NodePtr RootNode,SysNode,LogicNode,ArithNode;
  47.  
  48. /* Free nodes have NREF == 0 and are linked by NodeSib field */
  49. NodePtr FreeNode = NULL;
  50.  
  51. /*
  52.  * DelNPtr
  53.  *
  54.  * Note: node pointers always have a parent pointer to them, so
  55.  *       we don't have to delete them here.
  56.  *
  57.  * Input
  58.  *    N = pointer to node
  59.  */
  60. void DelNPtr (N)
  61.    NodePtr N;
  62.    {
  63.       rsemaphore_enter (NRefSemaphore);
  64.       if (N != NULL) N->NRef--;
  65.       rsemaphore_exit (NRefSemaphore);
  66.    }
  67.  
  68.  
  69. /*
  70.  * CopyNPtr
  71.  */
  72. NodePtr CopyNPtr (N)
  73.    NodePtr N;
  74.    {
  75.       rsemaphore_enter (NRefSemaphore);
  76.       if (N != NULL && !++N->NRef) IntError ("CopyNPtr: too many refs");
  77.       rsemaphore_exit (NRefSemaphore);
  78.       return N;
  79.    }
  80.     
  81.  
  82. /*
  83.  * NewNode
  84.  *
  85.  * Point *N to new node from free list.  The input value of *N is
  86.  * put in the NodeSib field of the new node.
  87.  *
  88.  * A SysError may occur, in which case *N is unchanged.
  89.  */
  90. private void NewNode (N)
  91.    NodePtr *N;
  92.    {
  93.       extern NodePtr AllocNodePage ();
  94.       register NodePtr T;
  95.  
  96.       rsemaphore_enter (NRefSemaphore);
  97.       if (FreeNode == NULL && (FreeNode = AllocNodePage ()) == NULL) {
  98.      printf ("NO MORE NODE CELLS LEFT\n");
  99.      SysError = NO_NODE_FREE;
  100.       } else {
  101.      T = FreeNode;
  102.      FreeNode = FreeNode->NodeSib;
  103.      T->NodeSib = *N;
  104.      *N = T;
  105.       }
  106.       rsemaphore_exit (NRefSemaphore);
  107.    }
  108.     
  109.  
  110. /*
  111.  * FindNode
  112.  *
  113.  * Find a node within a module with a specified name.
  114.  *
  115.  * Input
  116.  *      M = pointer to module node
  117.  *      S = pointer to string
  118.  *
  119.  * Output
  120.  *      result = NULL if node not found, pointer to node otherwise
  121.  */
  122. NodePtr FindNode (M,S)
  123.    register NodePtr M;
  124.    StrPtr S;
  125.    {
  126.       if (M->NodeType == MODULE)
  127.      for (M = M->NodeData.NodeMod.FirstChild; M!=NULL; M=M->NodeSib)
  128.         if (0==StrComp (M->NodeName,S)) return M;
  129.       return NULL;
  130.    }
  131.     
  132.  
  133. /*
  134.  * MakePath
  135.  *
  136.  * Make the path list for a given node
  137.  *
  138.  * Input
  139.  *      *N = module node
  140.  * Output
  141.  *      *result = path list
  142.  */
  143. ListPtr MakePath (N)
  144.    NodePtr N;
  145.    {
  146.       ListPtr P;
  147.  
  148.       rsemaphore_enter (NRefSemaphore);
  149.       P = NULL;
  150.       while (N->NodeParent != NULL) {
  151.      NewList (&P,1L);
  152.      P->Val.Tag = STRING;
  153.      P->Val.String = CopySPtr (N->NodeName);
  154.      N = N->NodeParent;
  155.       }
  156.       rsemaphore_exit (NRefSemaphore);
  157.       return P;
  158.    }
  159.  
  160.  
  161. /*
  162.  * MakeChild
  163.  *
  164.  * Find (or create if necessary) a new child node with a specified name.
  165.  *
  166.  * Input
  167.  *    M = Parent node
  168.  *    S = name of child
  169.  *
  170.  * Output
  171.  *    N = pointer to child
  172.  *
  173.  * A SysError may occur.
  174.  */
  175. NodePtr MakeChild  (M,S)
  176.    NodePtr M;
  177.    StrPtr S;
  178.    {
  179.       register NodePtr N;
  180.  
  181.       rsemaphore_enter (NRefSemaphore);
  182.       N = FindNode (M,S);
  183.       if (N==NULL) {
  184.      NewNode (&M->NodeData.NodeMod.FirstChild);
  185.      if (SysError) {
  186.         N = NULL;
  187.         goto exit;
  188.      }
  189.      N = M->NodeData.NodeMod.FirstChild;
  190.      N->NodeParent = M;
  191.      N->NodeName = CopySPtr (S);
  192.      N->NodeType = NEWNODE;
  193.       }
  194. exit:
  195.       rsemaphore_exit (NRefSemaphore);
  196.       return N;
  197.    }
  198.  
  199. /*
  200.  * Initialize a module node
  201.  *
  202.  * Input
  203.  *      M = pointer to new node
  204.  */
  205. void InitModule (M)
  206.    register NodePtr M;
  207.    {
  208.       M->NodeType = MODULE;
  209.       M->NodeData.NodeMod.FirstChild = NULL;
  210.       ReadImport (M);
  211.    }
  212.  
  213. /*
  214.  * MakeNode
  215.  *
  216.  * Create all nodes required by a path.
  217.  *
  218.  * Input
  219.  *      Path = pointer to path list
  220.  *      Type = type to make node if new node
  221.  * Output
  222.  *      result = pointer to node specified by path or
  223.  *               NULL if an error occurred.
  224.  */
  225. NodePtr MakeNode (Path,Type)
  226.    ListPtr Path;
  227.    int Type;
  228.    {
  229.       register NodePtr M;
  230.       register ListPtr P;
  231.  
  232.       rsemaphore_enter (NRefSemaphore);
  233.       M = RootNode;
  234.       for (P=Path; P != NULL; P=P->Next)
  235.      if (P->Val.Tag != STRING) return NULL;
  236.      else {
  237.         M = MakeChild (M,P->Val.String);
  238.         if (M->NodeType == NEWNODE)
  239.            if (P->Next!=NULL) InitModule (M);
  240.            else
  241.           switch (M->NodeType = Type) {
  242.              case DEF:
  243.             M->NodeData.NodeDef.DefCode.Tag = BOTTOM;
  244.             M->NodeData.NodeDef.DefFlags = 0;
  245.             break;
  246.              case MODULE:
  247.             InitModule (M);
  248.             break;
  249.           }
  250.      }
  251.       rsemaphore_exit (NRefSemaphore);
  252.       return M;
  253.    }
  254.  
  255.  
  256. /*
  257.  * DelImport
  258.  *
  259.  * Delete all information affected by the %IMPORT file for a module node
  260.  * in preparation for rereading the %IMPORT file.
  261.  *
  262.  * Input
  263.  *      M = pointer to module node
  264.  *
  265.  * Notes
  266.  *      IMPORT nodes can be returned to the free list since their
  267.  *      reference counts are always 1.
  268.  */
  269. void DelImport (M)
  270.    NodePtr M;
  271.    {
  272.       register NodePtr *L;
  273.       register NodePtr N;
  274.  
  275.       rsemaphore_enter (NRefSemaphore);
  276.       for (L = &M->NodeData.NodeMod.FirstChild; (N = *L)!= NULL; )
  277.  
  278.      switch (N->NodeType) {
  279.     
  280.         case IMPORT:        /* Return IMPORT nodes to free list */
  281.            DelSPtr (N->NodeName);
  282.            RepTag (&N->NodeData.NodeImp.ImpDef,BOTTOM);
  283.            Rot3 ((MetaPtr) &FreeNode, (MetaPtr) L, (MetaPtr) &N->NodeSib);
  284.            break;
  285.  
  286.         case DEF:           /* Delete local function definitions */
  287.            if (N->NodeData.NodeDef.DefCode.Tag != CODE) 
  288.           RepTag (&N->NodeData.NodeDef.DefCode,BOTTOM);
  289.            L = &N->NodeSib;
  290.            break;
  291.  
  292.         case MODULE:
  293.            L = &N->NodeSib;
  294.            break;
  295.  
  296.         default:
  297.            printf ("Invalid NodeType in node tree: %d\n",N->NodeType);
  298.            L = &N->NodeSib;
  299.            break;
  300.      }
  301.       rsemaphore_exit (NRefSemaphore);
  302.    }
  303.  
  304.  
  305. /*
  306.  * LinkPath
  307.  *
  308.  * Convert a path list to a node if possible.
  309.  *
  310.  * Input
  311.  *      *Def = path list
  312.  *      Type = NodeType value if new node
  313.  *
  314.  * Output
  315.  *      *Def = node or not changed if error occurs
  316.  */
  317. void LinkPath (Path,Type)
  318.    ObjectPtr Path;
  319.    int Type;
  320.    {
  321.       register NodePtr N;
  322.  
  323.       rsemaphore_enter (NRefSemaphore);
  324.       N = MakeNode (Path->List,Type);
  325.       if (N != NULL) {
  326.      RepTag (Path,NODE);
  327.      Path->Node = CopyNPtr (N);
  328.       }
  329.       rsemaphore_exit (NRefSemaphore);
  330.    }
  331.  
  332. /*
  333.  * SignExtend
  334.  *
  335.  * Sign extend a byte.  Not all machines have signed characters.
  336.  */    
  337. #define SignExtend(B) ((((B) + 0x80) & 0xFF) - 0x80)
  338.  
  339. /*
  340.  * PrimDef
  341.  *
  342.  * Define a primitive function
  343.  *
  344.  * Input
  345.  *      *F = object code for function
  346.  *      S = name of function
  347.  *      M = module to put function in
  348.  *      K = code parameter value
  349.  *
  350.  * Output
  351.  *      result = pointer to node containing function
  352.  */
  353. /* VARARGS3 */
  354. NodePtr PrimDef (F,S,M,K)
  355.    int (*F) ();
  356.    char *S;        
  357.    NodePtr M;
  358.    char K;
  359.    {
  360.       register NodePtr N;
  361.       StrPtr T;
  362.       T = MakeString (S);
  363.       N = MakeChild (M,T);
  364.       N->NodeType = DEF;
  365.       N->NodeData.NodeDef.DefCode.Tag = CODE;
  366.       N->NodeData.NodeDef.DefFlags = 0;
  367.       N->NodeData.NodeDef.DefCode.Code.CodePtr = F;
  368.       N->NodeData.NodeDef.DefCode.Code.CodeParam = SignExtend (K);
  369.       DelSPtr (T);
  370.       return N;
  371.    }
  372.  
  373.  
  374. /*
  375.  * GroupDef
  376.  *
  377.  * Define a group of functions
  378.  *
  379.  * Input
  380.  *     T = pointer to table of functions
  381.  *     N = number entries in table
  382.  *     M = module node
  383.  */
  384. void GroupDef (T,N,M)
  385.    register OpDef *T;
  386.    int N;
  387.    NodePtr M;
  388.    {
  389.       while (--N >= 0) 
  390.      (void) PrimDef (T->OpPtr,T->OpName,M,T->OpParam),
  391.      T++;
  392.    }
  393.  
  394.  
  395. /*
  396.  * Initialize root node and 'sys' subnode.
  397.  */
  398. void InitNode ()
  399.    {
  400.       register NodePtr R;
  401.  
  402.       if (Debug & DebugInit) printf ("enter InitNode\n");
  403.       RootNode = NULL;
  404.       NewNode (&RootNode);
  405.       R = RootNode;
  406.       R->NodeSib = NULL;
  407.       R->NodeParent = NULL;
  408.       R->NodeType = MODULE;
  409.       R->NodeName = MakeString ("ROOT");
  410.       R->NodeData.NodeMod.FirstChild = NULL;
  411.       SysNode = MakeChild (R,MakeString ("sys"));
  412.       InitModule (SysNode);
  413.       R = MakeChild (R,MakeString ("math"));
  414.       InitModule (R);
  415.       ArithNode = MakeChild (R,MakeString ("arith"));
  416.       InitModule (ArithNode);
  417.       LogicNode = MakeChild (R,MakeString ("logic"));
  418.       InitModule (LogicNode);
  419.       if (Debug & DebugInit) printf ("exit InitNode\n");
  420.    }
  421.  
  422. /****************************** end of node.c ******************************/
  423.