home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Harvest C 1.3 / Source Code / ParseTree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  17.6 KB  |  628 lines  |  [TEXT/ALFA]

  1. /*
  2.     Harvest C
  3.     Copyright 1992 Eric W. Sink.  All rights reserved.
  4.     
  5.     This file is part of Harvest C.
  6.     
  7.     Harvest C is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU Generic Public License as published by
  9.     the Free Software Foundation; either version 2, or (at your option)
  10.     any later version.
  11.     
  12.     Harvest C is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.     
  17.     You should have received a copy of the GNU General Public License
  18.     along with Harvest C; see the file COPYING.  If not, write to
  19.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.     
  21.     Harvest C is not in any way a product of the Free Software Foundation.
  22.     Harvest C is not GNU software.
  23.     Harvest C is not public domain.
  24.  
  25.     This file may have other copyrights which are applicable as well.
  26.  
  27. */
  28.  
  29. /*
  30.  * Harvest C
  31.  * 
  32.  * Copyright 1991 Eric W. Sink   All rights reserved.
  33.  * 
  34.  * This file implements operations on ParseTrees.
  35.  * 
  36.  */
  37.  
  38. /*
  39.  * The following routines handle pointer generation, integer promotion, and
  40.  * coersion for assignment, math operations, comparisons, and function calls.
  41.  */
  42.  
  43. #include "conditcomp.h"
  44. #include <stdio.h>
  45. #include <string.h>
  46.  
  47. #include "structs.h"
  48.  
  49. #pragma segment ParseTrees
  50.  
  51. #include "TypeRecord.h"
  52. #include "ParseTree.h"
  53.  
  54. void
  55. PtrGenerate(ParseTreeVia_t * tree)
  56. /*
  57.  * This routine converts arrays to pointers and functions to pointers to
  58.  * functions.
  59.  */
  60. {
  61.     TypeRecordVia_t                 thetype;
  62.     thetype = StripTypedef(GetTreeTP(*tree));
  63.     switch (GetTPKind(thetype)) {
  64.     case TRC_array:
  65.     (*tree) = BuildTreeNode(PTF_gen_addrof, *tree, NULL, NULL);
  66.     SetTreeTP(*tree, BuildTypeRecord(isArrayType(thetype),
  67.                      TRC_pointer, SGN_unknown));
  68.     Via(*tree)->LValue = 0;
  69.     break;
  70.     case TRC_ANSIfunction:
  71.     case TRC_ANSIELLIPSISfunction:
  72.     case TRC_OLDfunction:
  73.     case TRC_NOARGSfunction:
  74.     (*tree) = BuildTreeNode(PTF_gen_addrof, *tree, NULL, NULL);
  75.     SetTreeTP(*tree, BuildTypeRecord(thetype,
  76.                      TRC_pointer, SGN_unknown));
  77.     Via((*tree))->LValue = 0;
  78.     break;
  79.     }
  80. }
  81.  
  82. void
  83. FuncPtrGenerate(ParseTreeVia_t * tree)
  84. {
  85.     TypeRecordVia_t                 thetype;
  86.     thetype = StripTypedef(GetTreeTP(*tree));
  87.     switch (GetTPKind(thetype)) {
  88.     case TRC_ANSIfunction:
  89.     case TRC_ANSIELLIPSISfunction:
  90.     case TRC_OLDfunction:
  91.     case TRC_NOARGSfunction:
  92.     (*tree) = BuildTreeNode(PTF_gen_addrof, *tree, NULL, NULL);
  93.     SetTreeTP(*tree, BuildTypeRecord(thetype,
  94.                      TRC_pointer, SGN_unknown));
  95.     Via((*tree))->LValue = 0;
  96.     break;
  97.     }
  98. }
  99.  
  100. ParseTreeVia_t
  101. TypeConvert(ParseTreeVia_t expr, TypeRecordVia_t newtype)
  102. {
  103.     /*
  104.      * We need to have a separate node here for a typechange, because some
  105.      * type changes and conversions require specific reformatting. For
  106.      * example, a float cast to an int requires significant changes.  A
  107.      * pointer cast to an int probably requires that the value be moved from
  108.      * an A register to a D register.
  109.      */
  110.     assert(!isFunctionType(GetTreeTP(expr)));
  111.     if (isFloatingType(newtype)) {
  112.     if (isIntegralType(GetTreeTP(expr))) {
  113.         if (!(GetTPSize(GetTreeTP(expr)) == 4 && GetTPSign(GetTreeTP(expr)) == SGN_signed)) {
  114.         expr = TypeConvert(expr, BuildTypeRecord(0, TRC_long, SGN_signed));
  115.         }
  116.     }
  117.     } else if (isIntegralType(newtype)) {
  118.     if (isFloatingType(GetTreeTP(expr))) {
  119.         if (!(GetTPSize(newtype) == 4 && GetTPSign(newtype) == SGN_signed)) {
  120.         expr = TypeConvert(expr, BuildTypeRecord(0, TRC_long, SGN_signed));
  121.         }
  122.     }
  123.     }
  124.     expr = BuildTreeNode(PTF_typechange, expr, NULL, NULL);
  125.     SetTreeTP(expr, newtype);
  126.     return expr;
  127. }
  128.  
  129. void
  130. StandardIntPromote(ParseTreeVia_t * a)
  131. {
  132.     /*
  133.      * TODO According to ANSI, this routine should convert unsigned char to
  134.      * int, and unsigned short to int iff sizeof(int) > sizeof(short)
  135.      */
  136.  
  137.     if (GetTPKind(GetTreeTP(*a)) == TRC_char) {
  138.     (*a) = TypeConvert((*a), BuildTypeRecord(0, TRC_int, SGN_signed));
  139.     }
  140.     if (GetTPKind(GetTreeTP(*a)) == TRC_short) {
  141.     (*a) = TypeConvert((*a), BuildTypeRecord(0, TRC_int, SGN_signed));
  142.     }
  143.     if (GetTPKind(GetTreeTP(*a)) == TRC_bitfield) {
  144.     (*a) = TypeConvert((*a), BuildTypeRecord(0, TRC_int, SGN_signed));
  145.     }
  146.     if (GetTPKind(GetTreeTP(*a)) == TRC_enum) {
  147.     SetTreeTP(*a, CopyTypeRecord(GetTreeTP(*a)));
  148.     SetTPKind(GetTreeTP(*a), TRC_int);
  149.     }
  150. }
  151.  
  152. void
  153. StandardFloatPromote(ParseTreeVia_t * a)
  154. {
  155.     if (GetTPKind(GetTreeTP(*a)) == TRC_float) {
  156.     (*a) = TypeConvert((*a), BuildTypeRecord(0, TRC_double, SGN_unknown));
  157.     }
  158. }
  159.  
  160. TypeRecordVia_t
  161. Coerce(ParseTreeVia_t * a, ParseTreeVia_t * b, int mixpointers)
  162. {
  163.     /*
  164.      * This routine will coerce the two operands into compatible types and
  165.      * return the type of the result.
  166.      */
  167.  
  168.     if (!((isArithmeticType(GetTreeTP(*b))) && (isArithmeticType(GetTreeTP(*a))))) {
  169.     if (isStructUnionType(GetTreeTP(*a))) {
  170.         TypeError("Illegal usage of struct/union");
  171.     }
  172.     if (isStructUnionType(GetTreeTP(*b))) {
  173.         TypeError("Illegal usage of struct/union");
  174.     }
  175.     PtrGenerate(a);
  176.     PtrGenerate(b);
  177.  
  178.     if (isFloatingType(GetTreeTP(*a))) {
  179.         if (isPointerType(GetTreeTP(*b))) {
  180.         TypeError("Floats and pointers may not be mixed in expressions");
  181.         }
  182.     } else if (isFloatingType(GetTreeTP(*b))) {
  183.         if (isPointerType(GetTreeTP(*a))) {
  184.         TypeError("Floats and pointers may not be mixed in expressions");
  185.         }
  186.     }
  187.     if ((isPointerType(GetTreeTP(*a))) && (isPointerType(GetTreeTP(*b)))) {
  188.         if (!SameType(GetTreeTP(*a), GetTreeTP(*b))) {
  189.         if (!mixpointers) {
  190.             TypeError("Pointers of unlike types may not be mixed.");
  191.         }
  192.         }
  193.     }
  194.     if ((!isPointerType(GetTreeTP(*a))) && (isPointerType(GetTreeTP(*b)))) {
  195.         StandardIntPromote(a);
  196.         return GetTreeTP(*b);
  197.     } else {
  198.         StandardIntPromote(b);
  199.         return GetTreeTP(*a);
  200.     }
  201.  
  202.     } else {
  203.     if (GetTPKind(GetTreeTP(*a)) == TRC_longdouble) {
  204.         if (GetTPKind(GetTreeTP(*b)) != TRC_longdouble) {
  205.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  206.         return GetTreeTP(*a);
  207.         }
  208.     } else if (GetTPKind(GetTreeTP(*b)) == TRC_longdouble) {
  209.         if (GetTPKind(GetTreeTP(*a)) != TRC_longdouble) {
  210.         (*a) = TypeConvert((*a), GetTreeTP(*b));
  211.         return GetTreeTP(*a);
  212.         }
  213.     }
  214.     if (GetTPKind(GetTreeTP(*a)) == TRC_double) {
  215.         if (GetTPKind(GetTreeTP(*b)) != TRC_double) {
  216.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  217.         return GetTreeTP(*a);
  218.         }
  219.     } else if (GetTPKind(GetTreeTP(*b)) == TRC_double) {
  220.         if (GetTPKind(GetTreeTP(*a)) != TRC_double) {
  221.         (*a) = TypeConvert((*a), GetTreeTP(*b));
  222.         return GetTreeTP(*a);
  223.         }
  224.     }
  225.     if (GetTPKind(GetTreeTP(*a)) == TRC_float) {
  226.         if (GetTPKind(GetTreeTP(*b)) != TRC_float) {
  227.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  228.         return GetTreeTP(*a);
  229.         }
  230.     } else if (GetTPKind(GetTreeTP(*b)) == TRC_float) {
  231.         if (GetTPKind(GetTreeTP(*a)) != TRC_float) {
  232.         (*a) = TypeConvert((*a), GetTreeTP(*b));
  233.         return GetTreeTP(*a);
  234.         }
  235.     }
  236.     StandardIntPromote(a);
  237.     StandardIntPromote(b);
  238.  
  239.     if ((GetTPKind(GetTreeTP(*a)) == TRC_long) && (GetTPSign(GetTreeTP(*a)) == SGN_unsigned)) {
  240.         if (!SameType(GetTreeTP(*a), GetTreeTP(*b))) {
  241.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  242.         return GetTreeTP(*a);
  243.         }
  244.     } else if ((GetTPKind(GetTreeTP(*b)) == TRC_long) && (GetTPSign(GetTreeTP(*b)) == SGN_unsigned)) {
  245.         if (!SameType(GetTreeTP(*b), GetTreeTP(*a))) {
  246.         (*a) = TypeConvert((*a), GetTreeTP(*b));
  247.         return GetTreeTP(*a);
  248.         }
  249.     }
  250.     if ((GetTPKind(GetTreeTP(*a)) == TRC_long)) {
  251.         if ((GetTPKind(GetTreeTP(*b)) == TRC_int) && (GetTPSign(GetTreeTP(*b)) == SGN_unsigned)) {
  252.         if (GetTPSize(GetTreeTP(*b)) < GetTPSize(GetTreeTP(*a))) {
  253.             (*b) = TypeConvert((*b), GetTreeTP(*a));
  254.             return GetTreeTP(*a);
  255.         } else {
  256.             TypeRecordVia_t                 temp;
  257.             temp = BuildTypeRecord(0, TRC_long, SGN_unsigned);
  258.             (*b) = TypeConvert((*b), temp);
  259.             (*a) = TypeConvert((*a), temp);
  260.             return GetTreeTP(*a);
  261.         }
  262.         }
  263.     } else if ((GetTPKind(GetTreeTP(*b)) == TRC_long)) {
  264.         if ((GetTPKind(GetTreeTP(*a)) == TRC_int) && (GetTPSign(GetTreeTP(*a)) == SGN_unsigned)) {
  265.         if (GetTPSize(GetTreeTP(*a)) < GetTPSize(GetTreeTP(*b))) {
  266.             (*a) = TypeConvert((*a), GetTreeTP(*b));
  267.             return GetTreeTP(*a);
  268.         } else {
  269.             TypeRecordVia_t                 temp;
  270.             temp = BuildTypeRecord(0, TRC_long, SGN_unsigned);
  271.             (*a) = TypeConvert((*a), temp);
  272.             (*b) = TypeConvert((*b), temp);
  273.             return GetTreeTP(*a);
  274.         }
  275.         }
  276.     }
  277.     if (GetTPKind(GetTreeTP(*a)) == TRC_long) {
  278.         if (GetTPKind(GetTreeTP(*b)) != TRC_long) {
  279.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  280.         return GetTreeTP(*a);
  281.         }
  282.     } else if (GetTPKind(GetTreeTP(*b)) == TRC_long) {
  283.         if (GetTPKind(GetTreeTP(*a)) != TRC_long) {
  284.         (*a) = TypeConvert((*a), GetTreeTP(*b));
  285.         return GetTreeTP(*a);
  286.         }
  287.     }
  288.     if (GetTPSign(GetTreeTP(*a)) == SGN_unsigned) {
  289.         if (GetTPSign(GetTreeTP(*b)) != SGN_unsigned) {
  290.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  291.         return GetTreeTP(*a);
  292.         }
  293.     } else if (GetTPSign(GetTreeTP(*b)) == SGN_unsigned) {
  294.         if (GetTPSign(GetTreeTP(*a)) != SGN_unsigned) {
  295.         (*a) = TypeConvert((*a), GetTreeTP(*b));
  296.         return GetTreeTP(*a);
  297.         }
  298.     }
  299.     /* Then, both are of type int. */
  300.     return GetTreeTP(*a);
  301.     }
  302.     TypeError("Incompatible types in expression.");
  303.     return 0;
  304. }
  305.  
  306. void
  307. RelateCoerce(ParseTreeVia_t * a, ParseTreeVia_t * b)
  308. {
  309.     (void) Coerce(a, b, 0);
  310.     if (isPointerType(GetTreeTP(*a)) && (isIntegralType(GetTreeTP(*b)))) {
  311.     UserWarning(WARN_comparepointerint);
  312.     }
  313.     if (isPointerType(GetTreeTP(*b)) && (isIntegralType(GetTreeTP(*a)))) {
  314.     UserWarning(WARN_comparepointerint);
  315.     }
  316. }
  317.  
  318. TypeRecordVia_t
  319. AssignCoerce(ParseTreeVia_t * a, ParseTreeVia_t * b)
  320. {
  321.     /*
  322.      * This routine is used during assignment, to ensure that the two
  323.      * expressions are of compatible type.
  324.      */
  325.     TypeRecordVia_t                 result;
  326.     result = 0;
  327.  
  328.     /* TODO Redo according to ANSI. */
  329.     PtrGenerate(b);
  330.  
  331.     if (isArithmeticType(GetTreeTP(*a))) {
  332.     if (!SameType(GetTreeTP(*a), GetTreeTP(*b))) {
  333.         if (isArithmeticType(GetTreeTP(*b))) {
  334.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  335.         }
  336.     }
  337.     } else if (isArithmeticType(GetTreeTP(*b))) {
  338.     if (!SameType(GetTreeTP(*a), GetTreeTP(*b))) {
  339.         if (isArithmeticType(GetTreeTP(*a))) {
  340.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  341.         }
  342.     }
  343.     }
  344.     if ((isStructUnionType(GetTreeTP(*a))) || (isStructUnionType(GetTreeTP(*b)))) {
  345.     if (!SameType(GetTreeTP(*a), GetTreeTP(*b))) {
  346.         /* These two types must be identical. */
  347.         TypeError("Invalid struct/union assignment");
  348.     }
  349.     }
  350.     if (isFloatingType(GetTreeTP(*a))) {
  351.     if (isPointerType(GetTreeTP(*b))) {
  352.         TypeError("Floats may not be assigned to pointers.");
  353.     }
  354.     } else if (isPointerType(GetTreeTP(*a))) {
  355.     if (!SameType(GetTreeTP(*a), GetTreeTP(*b))) {
  356.         if (isFloatingType(GetTreeTP(*b))) {
  357.         TypeError("Floats may not be assigned to pointers.");
  358.         }
  359.         /*
  360.          * The warning below should not be issued if the type of b is
  361.          * either (void *) or b is an integer constant with value of 0
  362.          * (in other words, NULL).
  363.          */
  364.         if (!((Via((*b))->kind == PTF_intconstant) && (Via((*b))->data.number == 0))) {
  365.         if (!isVoidPointerType(GetTreeTP(*b))) {
  366.             /*
  367.              * The SameType call above - these pointer types must be
  368.              * identical.
  369.              */
  370.             UserWarning(WARN_pointernonequivassign);
  371.         }
  372.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  373.         } else {
  374.         (*b) = TypeConvert((*b), GetTreeTP(*a));
  375.         }
  376.     }
  377.     }
  378.     result = GetTreeTP(*a);    /* What purpose does the return value of this
  379.                  * routine serve ? */
  380.  
  381.     return result;
  382. }
  383.  
  384. void
  385. ReturnCoerce(TypeRecordVia_t param, ParseTreeVia_t * expr)
  386. {
  387.     /*
  388.      * This routine handles type checking and coercion for function values
  389.      * returns.
  390.      */
  391.  
  392.     PtrGenerate(expr);
  393.  
  394.     if (isIntegralType(param)) {
  395.     if (isArithmeticType(GetTreeTP(*expr))) {
  396.         (*expr) = TypeConvert((*expr), param);
  397.     } else {
  398.         TypeError("Non arithmetic types may not be returned into integral types");
  399.     }
  400.     }
  401.     if (isFloatingType(param)) {
  402.     if (isArithmeticType(GetTreeTP(*expr))) {
  403.         (*expr) = TypeConvert((*expr), param);
  404.     } else {
  405.         TypeError("Non arithmetic types may not be returned into floating types");
  406.     }
  407.     } else if (isPointerType(param)) {
  408.     if (!SameType(param, GetTreeTP(*expr))) {
  409.         if (isFloatingType(GetTreeTP(*expr))) {
  410.         TypeError("Floats may not be returned into pointers");
  411.         }
  412.         /*
  413.          * The warning below should not be issued if the type of expr is
  414.          * either (void *) or expr is an integer constant with value of 0
  415.          * (in other words, NULL).
  416.          */
  417.         if (!((Via((*expr))->kind == PTF_intconstant) && (Via((*expr))->data.number == 0))) {
  418.         if ((!isVoidPointerType(param)) && (!isVoidPointerType(GetTreeTP(*expr)))) {
  419.             /*
  420.              * The SameType call above - these pointer types must be
  421.              * identical.
  422.              */
  423.             UserWarning(WARN_pointernonequivreturn);
  424.         } else {
  425.             (*expr) = TypeConvert((*expr), param);
  426.         }
  427.         } else {
  428.         (*expr) = TypeConvert((*expr), param);
  429.         }
  430.     }
  431.     }
  432. }
  433.  
  434. void
  435. CallCoerce(TypeRecordVia_t param, ParseTreeVia_t * expr)
  436. {
  437.     /*
  438.      * This routine handles type checking and coercion for ANSI function
  439.      * calls.
  440.      */
  441.  
  442.     PtrGenerate(expr);
  443.  
  444.     if (isIntegralType(param)) {
  445.     if (isArithmeticType(GetTreeTP(*expr))) {
  446.         (*expr) = TypeConvert((*expr), param);
  447.     } else {
  448.         TypeError("Non arithmetic types may not be passed into integral types");
  449.     }
  450.     }
  451.     if (isFloatingType(param)) {
  452.     if (isArithmeticType(GetTreeTP(*expr))) {
  453.         (*expr) = TypeConvert((*expr), param);
  454.     } else {
  455.         TypeError("Non arithmetic types may not be passed into floating types");
  456.     }
  457.     } else if (isPointerType(param)) {
  458.     if (!SameType(param, GetTreeTP(*expr))) {
  459.         if (isFloatingType(GetTreeTP(*expr))) {
  460.         TypeError("Floats may not be passed into pointers");
  461.         }
  462.         /*
  463.          * The warning below should not be issued if the type of expr is
  464.          * either (void *) or expr is an integer constant with value of 0
  465.          * (in other words, NULL).
  466.          */
  467.         if (!((Via((*expr))->kind == PTF_intconstant) && (Via((*expr))->data.number == 0))) {
  468.         if ((!isVoidPointerType(param)) && (!isVoidPointerType(GetTreeTP(*expr)))) {
  469.             /*
  470.              * The SameType call above - these pointer types must be
  471.              * identical.
  472.              */
  473.             UserWarning(WARN_pointernonequivarg);
  474.         }
  475.         (*expr) = TypeConvert((*expr), param);
  476.         } else {
  477.         (*expr) = TypeConvert((*expr), param);
  478.         }
  479.     }
  480.     }
  481.     if (!SameType(param, GetTreeTP(*expr))) {
  482.     TypeError("Type mismatch on argument passing");
  483.     }
  484. }
  485.  
  486. ParseTreeVia_t
  487. RawTreeNode(char *id)
  488. {
  489.     register ParseTreeVia_t         raw;
  490. #ifdef Undefined
  491.     if (id)
  492.     raw = Ealloc(sizeof(ParseTree_t) + strlen(id));
  493.     else
  494. #endif
  495.     raw = Ealloc(sizeof(ParseTree_t));
  496.     if (raw) {
  497.     Via(raw)->kind = 0;
  498.     Via(raw)->LValue = 0;
  499.     Via(raw)->data.number = 0;
  500.     SetTreeTP(raw, 0);
  501.     Via(raw)->a = NULL;
  502.     Via(raw)->b = NULL;
  503.     Via(raw)->c = NULL;
  504.     Via(raw)->for_Scopes.d = NULL;
  505.     if (id)
  506.         Via(raw)->data.identifier = PutString(ParserStrings, id);
  507.     }
  508.     return raw;
  509. }
  510.  
  511. ParseTreeVia_t
  512. BuildTreeNode(enum ParseTreeFormat kind, ParseTreeVia_t a, ParseTreeVia_t b, ParseTreeVia_t c)
  513. /*
  514.  * Principal routine for building expression trees.  Note that it accepts
  515.  * only subtrees a, b and c, while there is also a field d. This is because
  516.  * only for stmts used the d field, and I didn't want to waste so much
  517.  * time/space in argument passing all those NULLs.  The routine which handles
  518.  * for statements sets this field itelf.
  519.  */
  520. {
  521.     ParseTreeVia_t                  node;
  522.     node = RawTreeNode(NULL);
  523.     Via(node)->kind = kind;
  524.     Via(node)->a = a;
  525.     Via(node)->b = b;
  526.     Via(node)->c = c;
  527.     return node;
  528. }
  529.  
  530. ParseTreeVia_t
  531. BuildIDTreeNode(enum ParseTreeFormat kind, ParseTreeVia_t a, ParseTreeVia_t b, ParseTreeVia_t c, char *id)
  532. /*
  533.  * Principal routine for building expression trees.  Note that it accepts
  534.  * only subtrees a, b and c, while there is also a field d. This is because
  535.  * only for stmts used the d field, and I didn't want to waste so much
  536.  * time/space in argument passing all those NULLs.  The routine which handles
  537.  * for statements sets this field itelf.
  538.  */
  539. {
  540.     ParseTreeVia_t                  node;
  541.     node = RawTreeNode(id);
  542.     Via(node)->kind = kind;
  543.     Via(node)->a = a;
  544.     Via(node)->b = b;
  545.     Via(node)->c = c;
  546.     return node;
  547. }
  548.  
  549. ParseTreeVia_t
  550. GetTreeFour(ParseTreeVia_t tree)
  551. {
  552.     assert(tree);
  553.     return Via(tree)->for_Scopes.d;
  554. }
  555.  
  556. ScopesVia_t
  557. GetTreeScopes(ParseTreeVia_t tree)
  558. {
  559.     assert(tree);
  560.     return Via(tree)->for_Scopes.Scopes;
  561. }
  562.  
  563. void
  564. SetTreeFour(ParseTreeVia_t tree, ParseTreeVia_t d)
  565. {
  566.     assert(tree);
  567.     Via(tree)->for_Scopes.d = d;
  568. }
  569.  
  570. void
  571. SetTreeScopes(ParseTreeVia_t tree, ScopesVia_t s)
  572. {
  573.     assert(tree);
  574.     Via(tree)->for_Scopes.Scopes = s;
  575. }
  576.  
  577. void
  578. SetTreeTP(ParseTreeVia_t tree, TypeRecordVia_t TP)
  579. {
  580.     assert(tree);
  581.     Via(tree)->for_Scopes.TP = TP;
  582. }
  583.  
  584. TypeRecordVia_t
  585. GetTreeTP(ParseTreeVia_t tree)
  586. {
  587.     assert(tree);
  588.     return Via(tree)->for_Scopes.TP;
  589. }
  590.  
  591. short
  592. GetTreeLValue(ParseTreeVia_t tree)
  593. {
  594.     assert(tree);
  595.     return Via(tree)->LValue;
  596. }
  597.  
  598. void
  599. SetTreeLValue(ParseTreeVia_t tree, short v)
  600. {
  601.     assert(tree);
  602.     Via(tree)->LValue = v;
  603. }
  604.  
  605. void
  606. FreeTree(ParseTreeVia_t root)
  607. {
  608.     /*
  609.      * We need to consider disposal of Locals, Scopes, TP, a, b, c, and d
  610.      */
  611.     if (root) {
  612.     FreeTree(Via(root)->a);
  613.     FreeTree(Via(root)->b);
  614.     FreeTree(Via(root)->c);
  615.     if (Via(root)->kind == PTF_for_stmt)
  616.         FreeTree(GetTreeFour(root));
  617.     else if (Via(root)->kind == PTF_compound_stmt)
  618.         if (GetTreeScopes(root)) {
  619.         FreeSymbolList(Via(GetTreeScopes(root))->Symbols, 1);
  620.         FreeSymbolList(Via(GetTreeScopes(root))->Tags, 1);
  621.         FreeSymbolList(Via(GetTreeScopes(root))->Labels, 1);
  622.         FreeSymbolList(Via(GetTreeScopes(root))->Enums, 1);
  623.         Efree(GetTreeScopes(root));
  624.         }
  625.     Efree(root);
  626.     }
  627. }
  628.