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 / EXP.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  64KB  |  2,710 lines

  1. /*
  2.     C* -- Expression parsing routines.
  3.  
  4.     source:  exp.c
  5.     started: November 2, 1985
  6.     version:
  7.         February 17, 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.     CAUTION: about extending casts: see lint.doc.  Extension is done first,
  28.     then sign conversion.  This is built into exp.c/pe_fold1(), 
  29.     g2.c/sop_cast(), and x2.c/x_cast().  Note also that pointer addition
  30.     depends on x_cast, so that if x_cast() is made to extend in a
  31.     different way, the dependent calls may have to be modified to keep
  32.     pointer addition correct.  Pointer addition calls for a result of
  33.     x_cast() as int_type or long_type (i.e. signed), so this should not
  34.     be a substantial problem unless unsigned-to-signed extending casts
  35.     are altered, which would be a botch.  (But committees do make botches.)
  36.     Since pointer addition should never overflow, except possibly when
  37.     the (folded) scaled offset is added to the pointer, it should be clear
  38.     in all cases what needs to happen.
  39. */
  40.  
  41. /*
  42.     type is:
  43.  
  44.     ASSIGN_EXPR    for expression having outer effect
  45.     ANY_EXPR    for nonnull expression
  46.     CONST_EXPR    for primitive or composite constant
  47.     XARITH_EXPR    for expression usable as boolean
  48.     ARG_EXPR    for expression usable as argument
  49.  
  50.     The pe_list1() and pe_expr1() routines call each other without resetting
  51.     the token and node stacks.  The externally visible versions do reset
  52.     those stacks.
  53. */
  54.  
  55.  
  56. /*
  57.     Externally visible routines:
  58. */
  59. struct node *    pe_list        (register int type);
  60. int        pe_oversize    (int mclass, long value);
  61. struct node *    pe_expr        (void);
  62. struct node *    pe_expr1    (bool comma_ok);
  63. bool        pe_check    (struct node * p, int type);
  64. void        pe_massage    (register struct type_node *t1,
  65.                 register struct node *p2, int op);
  66. int        pe_number    (struct node * p);
  67. void        pe_retype    (int mclass, register struct node * p2,
  68.                 int op);
  69.  
  70. /*
  71.     Internal routines.
  72.  
  73. */
  74. static int        pe_can_reduce    (register int opr1, register int opr2);
  75. static void        pe_cl_check    (int oldclass, int newclass,
  76.                     long value, int op);
  77. static struct node *    pe_cprim    (void);
  78. static void        pe_init        (void);
  79. static bool        pe_islval    (register struct node *p, int op);
  80. static struct node *    pe_fold1    (register struct node * p);
  81. static struct node *    pe_fold2    (register struct node * p);
  82. static struct node *    pe_list1    (register int type);
  83. static struct node *    pe_npop        (void);
  84. static void        pe_npush    (register struct node * p);
  85. static struct type_node * pe_opop    (void);
  86. static void        pe_opush    (struct type_node *tp);
  87. static int        pe_prec        (int op);
  88. static struct node *    pe_prim        (void);
  89. static void        pe_reduce    (int op, struct type_node *t);
  90. static unsigned long    pe_sizeof    (void);
  91. static int        pe_sprim    (struct node * p);
  92. static int        pe_tcheck    (void);
  93. static void        pe_tpop        (void);
  94. static void        pe_tpush    (int tok);
  95. static bool        pe_type1    (register struct node * p);
  96. static bool        pe_type2    (register struct node * p);
  97. static bool        pe_type3    (register struct node * p);
  98. static bool        pe_zcheck    (struct node *p);
  99.  
  100. /*
  101.     NOTE: pe_cprim(), pe_prim() depend on the structure of the target machine to
  102.     a limited extent.  It appears that gen_pp may be too late to do
  103.     some aspects of these setups.
  104. */
  105.  
  106. /*
  107.     Define data structures used only by this file.
  108. */
  109. #define MAX_STACK 2000
  110. static byte    expr_stk [MAX_STACK];
  111.  
  112. static byte *    tok_ptr;    /* Top of operator stack.    */
  113. static struct node ** node_ptr;    /* Top of expression stack.    */
  114. static int    free_count;    /* Free elements in stacks.    */
  115. static int    tok_count;    /* # of operators in stack.    */
  116. static int    node_count;    /* # of expressions in stack.    */
  117.  
  118. /*
  119.     Certain shared items
  120. */
  121. extern struct type_node *intrn_decl;
  122. extern struct type_node *intrn_ptr;
  123.  
  124. /*
  125.     ----- INTERNAL ROUTINES -----
  126. */
  127.  
  128. /*
  129.     Stack routines.
  130. */
  131. static void
  132. pe_tpush(int tok)
  133. {
  134.     /* CAUTION: this is used rather arbitrarily, and should not
  135.        interrogate t_type or any of the other t_ globals. */
  136.  
  137.     /* compare ascending and descending pointers */
  138.     TRACEPB("pe_tpush", printf("(%d)\n", tok));
  139.  
  140.     if (tok_ptr + 4 > (void *) node_ptr) {
  141.         fatal("expression too complex");
  142.     }
  143.     *( CAST(int *) tok_ptr ) = tok;
  144.     tok_ptr += sizeof(tok);
  145.     tok_count++;
  146.  
  147.     TICKX("pe_tpush");
  148. }
  149.  
  150. /* check if there is token-stack, needed for ternary reduce */
  151. static int
  152. pe_tcheck(void)
  153. {
  154.     TICK("pe_tcheck");
  155.     return (tok_ptr >= &expr_stk[0] + sizeof(int));
  156. }
  157.  
  158. #define look_tok() (  *( (CAST(int *) (void *) tok_ptr) - 1)  )
  159. /* returns an int! */
  160.  
  161. static void
  162. pe_tpop(void)
  163. {
  164.     TICKB("pe_tpop");
  165.  
  166.     if (tok_ptr < &expr_stk[0] + sizeof(int)) {
  167.         fatal("pe_tpop: can't be done");
  168.     }
  169.     tok_ptr -= sizeof(int);
  170.     tok_count--;
  171.  
  172.     TICKX("pe_tpop");
  173. }
  174.  
  175. /* operator subtype to stack */
  176. static void
  177. pe_opush(struct type_node *tp)
  178. {
  179.     /* compare ascending and descending pointers */
  180.     TRACEPB("pe_opush", printf("(%p)\n", tp));
  181.  
  182.     if (tok_ptr + 4 > (void *) node_ptr) {
  183.         fatal("expression too complex");
  184.     }
  185.     *( CAST(void **) tok_ptr ) = tp;
  186.     tok_ptr += sizeof(struct type_node *);
  187.  
  188.     TICKX("pe_opush");
  189. }
  190.  
  191. static struct type_node *
  192. pe_opop(void)
  193. {
  194.     register struct type_node * tp;
  195.  
  196.     TICKB("pe_opop");
  197.  
  198.     if (tok_ptr < &expr_stk[0] + sizeof(tp)) {
  199.         fatal("pe_opop: can't be done");
  200.     }
  201.     tok_ptr -= sizeof(struct type_node *);
  202.     tp = *(CAST (void **) tok_ptr);
  203.  
  204.     RETURN_PTR("pe_opop", tp);
  205. }
  206.  
  207. static void
  208. pe_npush(register struct node * p)
  209. {
  210.     TRACEPB("pe_npush", printf("(%p)\n", p));
  211.  
  212.     if (p == NULL) {
  213.         t_error("pe_npush: internal: NULL node");
  214.     }
  215.     if (tok_ptr + 4 > (void *) node_ptr) {
  216.         fatal("expression too complex");
  217.     }
  218.  
  219.     *--node_ptr = p;
  220.     node_count++;
  221.  
  222.     TICKX("pe_npush");
  223. }
  224.  
  225. static struct node *
  226. pe_npop(void)
  227. {
  228.     register struct node * p;
  229.  
  230.     TICKB("pe_npop");
  231.  
  232.     if (node_count <= 0) {
  233.         fatal("pe_npop: internal: ran out of nodes");
  234.     }
  235.  
  236.     p = *node_ptr++;
  237.     node_count--;
  238.  
  239.     RETURN_PTR("pe_npop", p);
  240. }
  241.  
  242. /*
  243.     Return TRUE if a tree p could be an lvalue if the types are right
  244.     Otherwise return FALSE and give the error.
  245.     This allows pe_typex() to detect certain errors.
  246.  
  247.     Lvalue form has root as an identifier, U*, array, ., or ->
  248. */
  249. bool
  250. pe_islval(register struct node *p, int op)
  251. {
  252.     TRACEPB("pe_islval", printf("(%p, %d)\n", p, op));
  253.  
  254.     switch (p -> n_type) {
  255.     case ID_TOK:    
  256.         if (p -> n_cid == NULL) {
  257.             RETURN_BOOL("pe_islval", FALSE); /* it's a constant */
  258.         }
  259.         RETURN_BOOL("pe_islval", TRUE);
  260.  
  261.     case USTAR_TOK:
  262.     case DOT_TOK:
  263.     case ARROW_TOK:
  264.     case ARRAY_TOK:
  265.         RETURN_BOOL("pe_islval", TRUE);
  266.  
  267.     case CAST_TOK:
  268.         if (pe_islval(p -> n_arg1, p -> n_arg1 -> n_type)) {
  269.             RETURN_BOOL("pe_islval", TRUE);
  270.         }
  271.         /* FALLTHROUGH */
  272.  
  273.     default:
  274.         t_2error("operand not assignable: ", ps_tok(op));
  275.     }
  276.     RETURN_BOOL("pe_islval", FALSE);
  277. }
  278.  
  279. /*
  280.     Return TRUE if we can reduce opr1 when opr2 follows.
  281.  
  282.     Return TRUE if opr1 has higher precedence than opr2.
  283.     Else if opr1 and opr2 have the same precedence,
  284.     return TRUE if they associate left to right.
  285.  
  286.     This code reflects the table on page 49 of K & R, except that
  287.     LPAREN_TOK has the LOWEST precedence and associates R to L.
  288. */
  289. static int
  290. pe_can_reduce(register int opr1, register int opr2)
  291. {
  292.     register int prec1, prec2;
  293.  
  294.     TRACEPB("pe_can_reduce", printf("(%d, %d)\n", opr1, opr2));
  295.  
  296.     if (opr1 == LPAREN_TOK) {
  297.         /* Force the pushing of opr2. */
  298.         RETURN_INT("pe_can_reduce", FALSE);
  299.     }
  300.  
  301.     prec1 = pe_prec(opr1);
  302.     prec2 = pe_prec(opr2);
  303.  
  304.     if (prec1 > prec2) {
  305.         RETURN_INT("pe_can_reduce", TRUE);
  306.     }
  307.     else if (prec1 < prec2) {
  308.         RETURN_INT("pe_can_reduce", FALSE);
  309.     }
  310.  
  311.     /* prec1 == 3 is the ternary */
  312.     else if (prec1 == 14 || prec1 == 3 || prec1 == 2) {
  313.         /* Associate right to left. */
  314.         RETURN_INT("pe_can_reduce", FALSE);
  315.     }
  316.     else {
  317.         /* Associate left to right. */
  318.         RETURN_INT("pe_can_reduce", TRUE);
  319.     }
  320. }
  321.  
  322. /*
  323.     Return the precedence of an operator.
  324.     Parentheses are handled separately.
  325.  
  326.     This code reflects the table on page 49 of K & R.
  327.  
  328.     If an operator can be both unary and binary, the default
  329.     form (not known yet whether unary or binary) must be the 
  330.     binary form.  Consider a + b &
  331. */
  332. static int
  333. pe_prec(int op)
  334. {
  335.     TRACEP("pe_prec", printf("(%s)\n", ps_tok(op)));
  336.  
  337.     switch (op) {
  338.     case LBRACK_TOK:
  339.     case LPAREN_TOK:
  340.     case ARROW_TOK:
  341.     case DOT_TOK:        return 15;
  342.  
  343.     case NOT_TOK:        case TILDE_TOK:
  344.     case INC_TOK:        case DEC_TOK:
  345.     case PRE_INC_TOK:    case PRE_DEC_TOK:
  346.     case POST_INC_TOK:    case POST_DEC_TOK:
  347.     case UMINUS_TOK:
  348.     case USTAR_TOK:        case UAND_TOK:
  349.     case K_SIZEOF:
  350.     case CAST_TOK:
  351.                 return 14;
  352.  
  353.     case STAR_TOK:
  354.     case DIV_TOK:
  355.     case MOD_TOK:        return 13;
  356.  
  357.     case PLUS_TOK:
  358.     case MINUS_TOK:        return 12;
  359.  
  360.     case LSHIFT_TOK:
  361.     case RSHIFT_TOK:    return 11;
  362.  
  363.     case LT_TOK:
  364.     case LE_TOK:
  365.     case GT_TOK:
  366.     case GE_TOK:        return 10;
  367.  
  368.     case EQUAL_TOK:
  369.     case NE_TOK:        return 9;
  370.  
  371.     case AND_TOK:        return 8;
  372.     case XOR_TOK:        return 7;
  373.     case OR_TOK:        return 6;
  374.  
  375.     case LAND_TOK:        return 5;
  376.     case LOR_TOK:        return 4;
  377.  
  378.     case QUESTION_TOK:
  379.     case COLON_TOK:
  380.                 return 3;
  381.  
  382.     case ASSN_TOK:        case AND_ASSN_TOK:
  383.     case DIV_ASSN_TOK:    case LSHIFT_ASSN_TOK:
  384.     case MINUS_ASSN_TOK:    case MOD_ASSN_TOK:
  385.     case OR_ASSN_TOK:    case PLUS_ASSN_TOK:
  386.     case RSHIFT_ASSN_TOK:    case STAR_ASSN_TOK:
  387.     case XOR_ASSN_TOK:
  388.                 return 2;
  389.     case COMMA_TOK:
  390.                 return 1;
  391.  
  392.     default:
  393.         printf("pe_prec: bad operator: %d, %s\n",op, ps_tok(op));
  394.         fatal("pe_prec");
  395.     }
  396. }
  397.  
  398. /*
  399.     Check an expression to see if it is of the indicated type.
  400.     Call t_error() if it isn't.
  401. */
  402. bool
  403. pe_check(struct node * p, int type)
  404. {
  405.     TRACEPB("pe_check", printf("(%p, %d)\n", p, type));
  406.  
  407.     if (p == NULL) {
  408.         t_error("empty expression");
  409.         RETURN_BOOL("pe_check", FALSE);
  410.     }
  411.  
  412.     switch (type) {
  413.     case ANY_EXPR:
  414.         RETURN_BOOL("pe_check", TRUE);
  415.  
  416.     /* expression having an effect */
  417.     /* WARNING: comma expressions */
  418.     case ASSIGN_EXPR:
  419.         switch(p -> n_type) {
  420.         case PRE_INC_TOK:    case PRE_DEC_TOK:
  421.         case POST_INC_TOK:    case POST_DEC_TOK:
  422.         case ASSN_TOK:        case AND_ASSN_TOK:
  423.         case DIV_ASSN_TOK:    case LSHIFT_ASSN_TOK:
  424.         case MINUS_ASSN_TOK:    case MOD_ASSN_TOK:
  425.         case OR_ASSN_TOK:    case PLUS_ASSN_TOK:
  426.         case RSHIFT_ASSN_TOK:    case STAR_ASSN_TOK:
  427.         case XOR_ASSN_TOK:
  428.             RETURN_BOOL("pe_check", TRUE);
  429.  
  430.         default:
  431.             TRACE("pe_check", printf("p -> n_type = %d\n", p -> n_type));
  432.             if (p -> n_cltype &&
  433.                     p->n_cltype -> t_typtok == VOID_TYPE) {
  434.             }
  435.             else {
  436.                 if (p -> n_type == CALL_TOK) {
  437.                     t_help("unused function-return value");
  438.                 }
  439.                 else {
  440.                     t_warning("unused value at outer level");
  441.                 }
  442.             }
  443.         }
  444.         RETURN_BOOL("pe_check", FALSE);
  445.  
  446.     case CONST_EXPR:
  447.         switch(p -> n_type) {
  448.         case INT_TOK:
  449.         case STRING_TOK:
  450.             t_error("internal: pe_check: unprocessed const_tok");
  451.             RETURN_BOOL("pe_check", FALSE);
  452.         case ID_TOK:
  453.             if (pe_number(p)) {
  454.                 RETURN_BOOL("pe_check", TRUE);
  455.             }
  456.             else {
  457.                 RETURN_BOOL("pe_check", FALSE);
  458.             }
  459.         default:
  460.             t_error("non-constant constant expression");
  461.             RETURN_BOOL("pe_check", FALSE);
  462.         }
  463.     case XARITH_EXPR:
  464.         if (p -> n_cltype) switch (p -> n_cltype -> t_typtok) {
  465.         case INT_TYPE:
  466.         case POINTER_TYPE:
  467.             RETURN_BOOL("pe_check", TRUE);
  468.         case ARRAY_TYPE:
  469.             t_warning("array name is apt to be always true");
  470.             RETURN_BOOL("pe_check", TRUE);
  471.         case VOID_TYPE:
  472.             t_error("boolean expression is of void type");
  473.             break;
  474.         default:
  475.             t_error("boolean expression has no arithmetic value");
  476.         }
  477.         else {
  478.             t_error("internal: untyped boolean expression");
  479.         }
  480.         RETURN_BOOL("pe_check", FALSE);
  481.  
  482.     case ARG_EXPR:
  483.         if (p -> n_cltype) switch (p -> n_cltype -> t_typtok) {
  484.         case INT_TYPE:
  485.         case POINTER_TYPE:
  486.         case ARRAY_TYPE:
  487.             RETURN_BOOL("pe_check", TRUE);
  488.         case STRUCT_TYPE:
  489.         case UNION_TYPE:
  490.             t_error("argument is a structure");
  491.             break;
  492.         case VOID_TYPE:
  493.             t_error("argument is of void type");
  494.             break;
  495.         default:
  496.             t_error("argument has no arithmetic value");
  497.         }
  498.         else {
  499.             t_error("internal: untyped boolean expression");
  500.         }
  501.         RETURN_BOOL("pe_check", FALSE);
  502.  
  503.     default:
  504.         TRACEP("pe_check", printf("bad type: %d\n", type));
  505.         fatal("internal: pe_check: called with bad type");
  506.         RETURN_BOOL("pe_check", FALSE);
  507.     }
  508. }
  509.  
  510. /*
  511.     Parse a comma list of expressions.
  512.     THIS MUST NOT BE CALLED INSIDE AN EXPRESSION!!!!!!
  513.     That is, called directly or indirectly by pe_expr()
  514.     pe_list INITIALIZES expr. use ALIST1 instead.
  515. */
  516. struct node *
  517. pe_list(int type)
  518. {
  519.     TRACEPB("pe_list", printf("(%d)\n", type));
  520.  
  521.     pe_init();
  522.     RETURN_PTR("pe_list", pe_list1(type));
  523. }
  524.  
  525. /*
  526.     parse the comma list; make a cons_node only if there are two
  527.     or more arguments
  528. */
  529. static struct node *
  530. pe_list1(register int type)
  531. {
  532.     register struct node * p;
  533.     register struct node * q;
  534.     struct node * head, *prev;
  535.  
  536.     TRACEPB("pe_list1", printf("(%d)\n", type));
  537.  
  538.     head = NULL;
  539.     prev = NULL;
  540.     for (;;) {
  541.         p = pe_expr1(FALSE);
  542.         if (p == NULL) {
  543.             break;
  544.         }
  545.         (void) pe_check(p, type);
  546.         if (head == NULL) {
  547.             /* No cons node needed yet. */
  548.             head = p;
  549.         }
  550.         else {
  551.             q = new_pnode(sizeof(struct cons_node));
  552.             q -> n_type = SEPARATOR_TOK;
  553.  
  554.             if (prev == NULL) {
  555.                 /* Initial cons node.  No unlinking to do. */
  556.                 q -> n_car = head;
  557.                 q -> n_next = p;
  558.                 head = q;
  559.                 prev = q;
  560.             }
  561.             else {
  562.                 /* Change the list structure. */
  563.                 q -> n_car = prev -> n_next;
  564.                 q -> n_next = p;
  565.                 prev -> n_next = q;
  566.                 prev = q;
  567.             }
  568.         }
  569.  
  570.         /* Continue as long as comma is seen. */
  571.         if (t_type != COMMA_TOK) {
  572.             break;
  573.         }
  574.         get_token();
  575.     }
  576.     RETURN_PTR("pe_list1", head);
  577. }
  578.  
  579. /*
  580.     Parse an arbitrary C expression, commas allowed if comma is TRUE
  581.  
  582.     The code below uses an operator    precedence algorithm which
  583.     uses an operator stack and a node stack, both housed in expr_stk[].
  584.     Several auxiliary routines handle these stacks:
  585.     pe_tpush(), pe_tpop(), pe_npush() and pe_npop();
  586. */
  587. static void
  588. pe_init(void)
  589. {
  590.     byte * cp;
  591.  
  592.     TICK("pe_init");
  593.  
  594.     /* Initialize the stacks. */
  595.     free_count = MAX_STACK-8;
  596.     tok_count  = 0;
  597.     node_count = 0;
  598.     tok_ptr    = &expr_stk[0];
  599.     cp         = (void *) &expr_stk[0];
  600.     cp += (MAX_STACK-4);
  601.     node_ptr   = /* (void *) */ CAST(struct node **) cp;
  602.     return;
  603. }
  604.  
  605. struct node *
  606. pe_expr(void)
  607. {
  608.     TICKB("pe_expr");
  609.  
  610.     pe_init();
  611.     RETURN_PTR("pe_expr", pe_expr1(TRUE));
  612. }
  613.  
  614. /* pe_expr1 is visible for use by dcl.c in parsing array subscripts in casts */
  615. struct node *
  616. pe_expr1(bool comma_ok)
  617. {
  618.     /* these items are for save-and-restore */
  619.     byte *    tok_psave;
  620.     struct node ** node_psave;
  621.     int    free_csave;
  622.     int    tok_csave;
  623.     int    node_csave;
  624.  
  625.     register struct node * p;
  626.     register struct node * p2;
  627.     register int op;
  628.     register struct type_node *t;
  629.     register int ternary;
  630.     register int g_f;
  631.  
  632.     /* save the stacks */
  633.  
  634.     TRACEPB("pe_expr1", printf("(comma ok: %d)\n", comma_ok));
  635.  
  636.     tok_psave = tok_ptr;
  637.     node_psave = node_ptr;
  638.     free_csave = free_count;
  639.     tok_csave = tok_count;
  640.     node_csave = node_count;
  641.  
  642.     ternary = 0;
  643.  
  644. /*
  645.     Handle null expressions cleanly.
  646. */
  647.     switch(t_type) {
  648.     case COMMA_TOK:
  649.         if (comma_ok) {
  650.             break;
  651.         }
  652.         /* FALLTHROUGH */
  653.  
  654.     case SEMICOLON_TOK:
  655.     case RPAREN_TOK:
  656.         RETURN_PTR("pe_expr1", NULL);
  657.     }
  658.  
  659. /*
  660.     State S1:  Start of expression
  661.  
  662.     handle unary ops or '('
  663.     push them on the stack for evaluation later.
  664. */
  665. s1:
  666.     TRACEP("pe_expr1", printf("state s1, t_type %d, line %d\n",
  667.                              t_type, t_line));
  668.  
  669.     /* The sizeof operator is handled by pe_prim(). */
  670.     /* t_type is as currently provided via get_token */
  671.  
  672.     switch (t_type) {
  673.  
  674.     case TILDE_TOK:        
  675.     case NOT_TOK:        break;
  676.  
  677.     case INC_TOK:        t_type = PRE_INC_TOK;    break;
  678.     case DEC_TOK:        t_type = PRE_DEC_TOK;    break;
  679.     case AND_TOK:        t_type = UAND_TOK;    break;
  680.     case STAR_TOK:        t_type = USTAR_TOK;    break;
  681.     case PLUS_TOK:        t_type = UPLUS_TOK;    break;
  682.  
  683.     case LPAREN_TOK:
  684.         /* Possible cast, look ahead */
  685.         TRACEP("pe_expr1", printf("s1: check for cast\n"));
  686.         get_token();
  687.         t = pd_cast();
  688.         if (t != NULL) {
  689.             pe_opush(t);
  690.             pe_tpush(CAST_TOK);
  691.             need(RPAREN_TOK);
  692.         }
  693.         else {
  694.             TRACEP("pe_expr1", printf("s1: not a cast\n"));
  695.             pe_tpush(LPAREN_TOK);
  696.             comma_ok++;
  697.             TRACEP("pe_expr1", printf("comma_ok++, comma_ok == %d\n", comma_ok));
  698.         }
  699.         goto s1;
  700.  
  701.     case MINUS_TOK:
  702.         t_type = UMINUS_TOK;
  703.         TRACEP("pe_expr1", printf("s1: unary minus special handling\n"));
  704.         get_token();
  705.         /* look ahead at the next token */
  706.         switch (t_type) {
  707.         case CHAR_TOK:
  708.         case INT_TOK:
  709.         case LONG_TOK:
  710.             /* 
  711.                 tamper with t_value and go to state s2
  712.                 with the negative t_value in place. this
  713.                 saves parsing one useless unary -, which is
  714.                 OK, but what is important is that it
  715.                 allows pe_cprim to see the negative constant,
  716.                 which is probably what the programmer also
  717.                 sees, and raise warnings, e.g. about an
  718.                 apparent integer that's actually long.
  719.             */
  720.             t_value = -t_value;
  721.             goto s2;
  722.         default:
  723.             /* set things as though lookahead had never happened */
  724.             pe_tpush(UMINUS_TOK);
  725.             goto s1;
  726.         }
  727.     default:
  728.         goto s2;
  729.     }
  730.  
  731.     TRACEP("pe_expr1", printf("s1: fall-through\n"));
  732.     pe_tpush(t_type);
  733.     get_token();
  734.     goto s1;
  735.  
  736. /*
  737.     State S2:
  738.     We expect and must have a primitive (i.e., an identifier or constant)
  739.     at this point.
  740.  
  741.     Push it onto the node stack.
  742. */
  743. s2:
  744.     TRACEP("pe_expr1", printf("state s2\n"));
  745.     p = pe_prim();
  746.     TRACEP("pe_expr1", printf("state s2: prim returns node type %d\n",
  747.             p -> n_type));
  748.     /*
  749.         WARNING: we have to keep the books balanced or else an
  750.         expression will be totally botched by too many pulls
  751.         on pe_npop, given that an incomplete expression is
  752.         present in an argument parsed underneath by pe_list()
  753.     */
  754.     if (p == NULL) {
  755.         p = new_pnode(sizeof(struct loc_node));
  756.         p -> n_cltype = new_tnode();
  757.         p -> n_type = ID_TOK;
  758.     }
  759.     pe_npush(p);
  760.     
  761.  
  762. /*
  763.     State S3: After an identifier
  764.  
  765.     Take care of the post-operator, if any.
  766. */
  767. s3:    
  768.     TRACEP("pe_expr1", printf("state s3\n"));
  769.  
  770.     switch (t_type) {
  771.     case INC_TOK:
  772.         t_type = POST_INC_TOK;
  773.         g_f = 1;
  774.         break;
  775.     case DEC_TOK:
  776.         t_type = POST_DEC_TOK;
  777.         g_f = 1;
  778.         break;
  779.  
  780.     case POST_DEC_TOK:
  781.     case POST_INC_TOK:
  782.         break;
  783.  
  784.     case LPAREN_TOK:
  785.     case LBRACK_TOK:
  786.         g_f = 0;
  787.         break;
  788.  
  789.     default:
  790.         goto s4;
  791.     }
  792.  
  793.     TRACEP("pe_expr1", printf("s3: reducing post %s\n", ps_tok(t_type)));
  794.  
  795.     if (tok_count > tok_csave && pe_can_reduce(op = look_tok(), t_type)) {
  796.         /* reduce what is already on the stack */
  797.         pe_tpop();
  798.         if (op == CAST_TOK) {
  799.             t = pe_opop();
  800.         }
  801.         else {
  802.             t = NULL;
  803.         }
  804.         pe_reduce(op, t);
  805.     }
  806.     else {
  807.         pe_reduce(t_type, NULL);
  808.         if (g_f) {
  809.             get_token();
  810.         }
  811.     }
  812.     goto s3;
  813. /*
  814.     State S4:                   
  815.     End of expression, or continuation via binary operator, 
  816.     or balanced right parenthesis.
  817.  
  818.     If it is not a continuation,
  819.     the whole op stack gets used up, at which point it exits.
  820.  
  821.     If it is a continuation, the op stack gets popped only until
  822.     t_type has a higher precedence than the operator on top.
  823.  
  824.     The operator has already been obtained via get_token().
  825. */
  826. s4:
  827.     TRACEP("pe_expr1", printf("state s4\n"));
  828.  
  829.     if (tok_count <= tok_csave) {
  830.  
  831.         TRACEP("pe_expr1", printf("stack empty. t_type=%d\n",t_type));
  832.  
  833.         switch(t_type) {
  834.         case RBRACK_TOK:
  835.         case RPAREN_TOK:
  836.         case SEMICOLON_TOK:
  837.             goto s5;
  838.  
  839.         case COMMA_TOK:
  840.             if (!comma_ok) {
  841.                 goto s5;
  842.             }
  843.             pe_tpush(t_type);
  844.             get_token();
  845.             goto s1;
  846.  
  847.         case COLON_TOK: 
  848.             /* this colon always ends an expression, since there is
  849.                no operator stack, and so no ? on the stack */
  850.             TRACEP("pe_expr1", printf("terminal :\n"));
  851.             goto s5;
  852.  
  853.         case QUESTION_TOK:
  854.             /* question marks are counted in case excess :
  855.                is found while something is on stack */
  856.             TRACEP("pe_expr1", printf("ternary++\n"));
  857.             ternary++;
  858.             pe_tpush(t_type);
  859.             get_token();
  860.             goto s1;
  861.             
  862.         case LONG_TOK:
  863.         case INT_TOK:
  864.         case STRING_TOK:
  865.             t_error("extra constant ignored");
  866.             get_token();
  867.             goto s4;
  868.  
  869.         case ID_TOK:
  870.             t_2error("extra identifier ignored: ", t_symbol);
  871.             get_token();
  872.             goto s4;
  873.         }
  874.  
  875.         if (is_binop(t_type)) {
  876.             /* Valid operator.  Push it and enter S1. */
  877.             pe_tpush(t_type);
  878.             get_token();
  879.             goto s1;
  880.         }
  881.         else if (is_unop(t_type)) {
  882.             t_2error("extra unary operator ignored: ",
  883.                             ps_tok(t_type));
  884.             get_token();
  885.             goto s4;
  886.         }
  887.         else {
  888.             if (t_type == X_TOK || t_type == Z_TOK) {
  889.                 t_2error("expression runs into reserved: ",
  890.                                 t_symbol);
  891.             }
  892.             else if (ps_tok(t_type)) {
  893.                 t_2error("expression runs into: ",
  894.                              ps_tok(t_type));
  895.             }
  896.             else {
  897.                 t_error("runon expression");
  898.             }
  899.             goto s5;
  900.         }
  901.     }
  902.  
  903.     /*
  904.         The operator stack is not empty.
  905.         Compare the operator on the op stack with the current operator.
  906.         The operator on the stack may be a cast operator
  907.  
  908.         Operators are popped here and in reduce()
  909.         This is the later part of s4
  910.     */
  911.     op = look_tok();
  912.  
  913.     TRACEP("expr", printf("s4a: op = %d %s, ternary = %d\n",
  914.                 op, ps_tok(op), ternary));
  915.  
  916.     /* unknown or known reducible t_types get reduced */
  917.     /* known and nonreducible t_types get pushed at pushit: */
  918.     switch(t_type) {
  919.     case RPAREN_TOK: 
  920.         if (op == LPAREN_TOK) {
  921.             if (comma_ok > 0) {
  922.                 comma_ok--;
  923.             }
  924.             TRACEP("pe_expr1", printf("comma_ok--, comma_ok == %d\n", comma_ok));
  925.             /* cancel LPAREN & enter after-prim state */
  926.             pe_tpop();
  927.             get_token();
  928.             goto s3;
  929.         }
  930.         /* here RPAREN is a terminator and flushes the stack */
  931.         break;
  932.  
  933.     case QUESTION_TOK:
  934.         if (pe_can_reduce(op, t_type)) {
  935.             break;
  936.             /* go reduce stack and try again */
  937.         }
  938.         /* first of ternary pair */
  939.         TRACEP("pe_expr1", printf("ternary++\n"));
  940.         ternary++;
  941.         goto pushit;
  942.  
  943.     case COLON_TOK: 
  944.         /* second of ternary pair */
  945.         if (pe_can_reduce(op, t_type) || ternary == 0) {
  946.             break;
  947.         }
  948.         ternary--;
  949.         goto pushit;
  950.  
  951.     case COMMA_TOK:
  952.         if (!comma_ok || pe_can_reduce(op, t_type)) {
  953.             break;
  954.         }
  955.         goto pushit;
  956.  
  957.     default:
  958.         if (!is_binop(t_type)) {
  959.             TRACEP("pe_expr1",printf("not binop: %d\n", t_type));
  960.             break;
  961.         }
  962.         if (pe_can_reduce(op, t_type)) {
  963.             break;
  964.         }
  965.         /* FALLTHROUGH */
  966.  
  967.     pushit:
  968.         pe_tpush(t_type);
  969.         get_token();
  970.         goto s1;
  971.     }
  972.  
  973.     /* reduce the operator that's on the stack and try again */
  974.     pe_tpop();
  975.     if (op == CAST_TOK) {
  976.         t = pe_opop();
  977.         TRACEP("pe_expr1",printf("cast type %\n", t));
  978.     }
  979.     else if (op == LPAREN_TOK) {
  980.         t_error("excess or misplaced ( in expression");
  981.         goto s4;
  982.     }
  983.     else {
  984.         t = NULL;
  985.     }
  986.     pe_reduce (op,t);
  987.     goto s4;
  988.  
  989. /*
  990.     State S5: End of expression.
  991. */
  992. s5:
  993.     TRACEP("pe_expr1", printf("s5: node_count = %d , %d (local)\n",
  994.          node_count, node_count-node_csave));
  995.  
  996.     p = pe_npop(); /* the last one off the stack */
  997.     TRACE("pe_expr1_list", pr_expr(p));
  998.     TRACE("pe_expr1_list", printf("\n"));
  999.  
  1000.     if (node_count != node_csave) {
  1001.         t_error("too many operands (node stack not empty on exit)");
  1002.     }
  1003.  
  1004.     tok_ptr    = tok_psave;
  1005.     node_ptr   = node_psave;
  1006.     free_count = free_csave;
  1007.     tok_count  = tok_csave;
  1008.     node_count = node_csave;
  1009.  
  1010.     TRACE("pe_npush",
  1011.     printf("pe_expr1: node_ptr set to %p on exit\n", node_ptr));
  1012.     RETURN_PTR("pe_expr1", p);
  1013. }
  1014.  
  1015. /*
  1016.     Reduce unary, binary, or ternary operator (including '[')
  1017.     by popping operands off the node stack and repushing a result.
  1018. */
  1019. static void
  1020. pe_reduce(int op, struct type_node *t)
  1021. {
  1022.     register struct node * p, * q;
  1023.  
  1024.     TRACEPB("pe_reduce", printf("op=%d %s, t=%p\n",
  1025.         op, ps_tok(op), t));
  1026.  
  1027.     if (is_unop(op) || op == POST_INC_TOK || op == POST_DEC_TOK) {
  1028.         /* Create a new unary node. */
  1029.         p = new_pnode(sizeof(struct unop_node));
  1030.         p -> n_type = op;
  1031.         p -> n_arg1 = pe_npop();
  1032.         p -> n_cltype = t;
  1033.  
  1034.         /* Fold constant expressions. */
  1035.         TRACEP("pe_reduce", printf("new unary node %p\n", p));
  1036.         if ((q = pe_fold1(p)) == NULL) {
  1037.             (void) pe_type1(p);
  1038.             pe_npush(p);
  1039.         }
  1040.         else {
  1041.             pe_npush(q);
  1042.         }
  1043.     }
  1044.     else if (op == LBRACK_TOK) {
  1045.         get_token();
  1046.         q = new_pnode(sizeof(struct binop_node));
  1047.         q -> n_type = ARRAY_TOK;
  1048.         q -> n_arg2 = pe_expr1(TRUE);
  1049.         q -> n_arg1 = pe_npop(); /* array-id expression */
  1050.         if ((p = pe_fold2(q)) == NULL) {
  1051.             (void) pe_type2(q);
  1052.             p = q;
  1053.         }
  1054.         (void) needend(RBRACK_TOK);
  1055.         TRACEP("pe_reduce", printf("array, p = %p\n", p));
  1056.         pe_npush(p);
  1057.     }
  1058.     else if (op == LPAREN_TOK) {
  1059.         get_token();
  1060.         p = new_pnode(sizeof(struct call_node));
  1061.         p -> n_type = CALL_TOK;
  1062.         p -> n_arg2 = q = pe_list1(ARG_EXPR);
  1063.         if (q && q -> n_type != SEPARATOR_TOK) {
  1064.             call_1arg++;
  1065.         }
  1066.         p -> n_arg1 = pe_npop(); /* function-id expression */
  1067.         (void) pe_type2(p);
  1068.         (void) needend(RPAREN_TOK);
  1069.         TRACEP("pe_reduce", printf("function call, p = %p\n", p));
  1070.         pe_npush(p);
  1071.     }
  1072.     else if (is_binop(op)) {
  1073.         /* Create a binary node. */
  1074.         p = new_pnode(sizeof(struct binop_node));
  1075.         p -> n_type = op;
  1076.         TRACEP("pe_reduce",printf("new binary node %p\n", p));
  1077.  
  1078.         /* Reduce the operator on the top of the stack. */
  1079.         p -> n_arg2 = pe_npop();
  1080.         p -> n_arg1 = pe_npop();
  1081.         /* CAUTION: pe_fold2 can convert binary (-) to unary (-) */
  1082.         if ((q = pe_fold2(p)) == NULL) {
  1083.             (void) pe_type2(p); 
  1084.             TRACEP("pe_type2",
  1085.                 printf("%p->%p: ", p, p -> n_cltype);
  1086.                 pr_type(p -> n_cltype); printf("\n"));
  1087.             pe_npush(p);
  1088.         }
  1089.         else {
  1090.             pe_npush(q);
  1091.         }
  1092.     }
  1093.     else if (op == COLON_TOK) {
  1094.         TRACEP("pe_reduce",printf("colon operator\n"));
  1095.         /* Create a ternary node, maybe */
  1096.         if (!pe_tcheck()) {
  1097.             t_error("unexpected \':\'");
  1098.             (void) pe_npop();
  1099.         }
  1100.         else if ( (op = look_tok()) == QUESTION_TOK) {
  1101.             pe_tpop();
  1102.             p = new_pnode(sizeof(struct ternop_node));
  1103.             p -> n_type = QUESTION_TOK;
  1104.  
  1105.             p -> n_arg3 = pe_npop();
  1106.             p -> n_arg2 = pe_npop();
  1107.             p -> n_arg1 = pe_npop();
  1108.             if (pe_type3(p)) {
  1109.                 /* p = fold3(p) */
  1110.             }
  1111.             pe_npush(p);
  1112.         }
  1113.         else {
  1114.             /* just align the stack */
  1115.             (void) pe_npop();
  1116.             t_error("unexpected \':\'");
  1117.         }
  1118.     }
  1119.     else if (op == QUESTION_TOK) {
  1120.         TRACEP("pe_reduce",printf("bad ? operator\n"));
  1121.         /* just align the stack */
  1122.         (void) pe_npop();
  1123.         t_error("? without associated :");
  1124.     }
  1125.     else {
  1126.         /* a bad op should never be pushed in the first place! */
  1127.         printf("pe_reduce: bad operator %d\n", op);
  1128.         fatal("pe_reduce: bad operator");
  1129.     }
  1130.  
  1131.     TICKX("pe_reduce");
  1132. }
  1133.  
  1134. /*
  1135.     Check a PARSER operand to see if it is a constant of value zero
  1136.     and a scalar type
  1137. */
  1138. static bool
  1139. pe_zcheck(struct node *p)
  1140. {
  1141.     TRACEPB("pe_zcheck", printf("(%p)\n", p));
  1142.  
  1143.     if (p && p -> n_type == ID_TOK &&
  1144.             p -> n_cid == NULL && p -> n_const == 0L &&
  1145.             p -> n_reg1 == 0) {
  1146.         if (p -> n_cltype) {        
  1147.             switch(p -> n_cltype -> t_typtok) {
  1148.             case INT_TYPE:
  1149.             case POINTER_TYPE:
  1150.                 RETURN_BOOL("pe_zcheck", TRUE);
  1151.             }
  1152.         }
  1153.     }
  1154.     RETURN_BOOL("pe_zcheck", FALSE);
  1155. }
  1156.  
  1157. /*
  1158.     Set type involving a unary operator.
  1159.     A type always gets attached to p, and the routine returns
  1160.     FALSE if that type had to be made of whole cloth.
  1161.     (If it is desired to have the made-up type be VOID instead
  1162.     of INT, do it here, and don't change new_tnode!)
  1163. */
  1164. static bool
  1165. pe_type1(register struct node * p)
  1166. {
  1167.     register struct node *p1;
  1168.     register struct type_node *t, *t1;
  1169.     register int op;
  1170.  
  1171.     TRACEPB("pe_type1", printf("(%p)\n", p));
  1172.  
  1173.     p1 = p -> n_arg1;
  1174.     op = p -> n_type;
  1175.     if (p1 == NULL) {
  1176.         t_2error("pe_type1: internal: no arg of unary operator: ",
  1177.                         ps_tok(op));
  1178.         if (p -> n_cltype == NULL) {
  1179.             p -> n_cltype = new_tnode();
  1180.         }
  1181.         RETURN_BOOL("pe_type1", FALSE);
  1182.     }
  1183.  
  1184.     TRACEP("pe_type1", printf("node %p, op %d: %s\n", p, op, ps_tok(op)));
  1185.  
  1186.     t1 = p1 -> n_cltype;
  1187.     if (t1 == NULL) {
  1188.         t_2error("pe_type1: internal: untyped arg of unary operator: ",
  1189.                         ps_tok(op));
  1190.         TRACEP("pe_type1",
  1191.             printf("arg is:\n"); pr_expr(p1); printf("\n"));
  1192.  
  1193.         if (p -> n_cltype == NULL) {
  1194.             p -> n_cltype = new_tnode();
  1195.         }
  1196.         RETURN_BOOL("pe_type1", FALSE);
  1197.     }
  1198.     else if (op != CAST_TOK) {
  1199.         /* default setting */
  1200.         p -> n_cltype = t1;
  1201.     }
  1202.  
  1203.     switch (op) {
  1204.     case CAST_TOK:
  1205.         t = p -> n_cltype;
  1206.         /* t1 is the argument type */
  1207.         if (t -> t_typtok != VOID_TYPE) switch (t1 -> t_typtok) {
  1208.         case POINTER_TYPE:
  1209.             if (t -> t_tsize < t1 -> t_tsize) {
  1210.                 t_warning("pointer cast to narrower type");
  1211.             }
  1212.             break;
  1213.  
  1214.         case STRUCT_TYPE:
  1215.         case ARRAY_TYPE:
  1216.         case UNION_TYPE:
  1217.         case FUNCTION_TYPE:
  1218.             t_warning("address-of required?");
  1219.             t_error("cast from an aggregate");
  1220.             break;
  1221.         }
  1222.         /* t is the cast type */
  1223.         switch (t -> t_typtok) {
  1224.         case INT_TYPE:
  1225.             if ((t -> t_mclass & UNSIGNED_MOD) &&
  1226.                 t1 -> t_typtok == INT_TYPE &&
  1227.                 !(t1 -> t_mclass & UNSIGNED_MOD) &&
  1228.                     (t -> t_tsize > t1 -> t_tsize) ) {
  1229.                 t_warning("ambiguous cast will extend then convert");
  1230.             }
  1231.             break;
  1232.                 
  1233.         case POINTER_TYPE:
  1234.             switch (t1 -> t_typtok) {
  1235.             case POINTER_TYPE:
  1236.             case ARRAY_TYPE:
  1237.                 switch(t -> t_link -> t_typtok) {
  1238.                 case INT_TYPE:
  1239.                 case POINTER_TYPE:
  1240.                     switch(t1->t_link->t_typtok) {
  1241.                     case INT_TYPE:
  1242.                     case POINTER_TYPE:
  1243.                         if(t1 -> t_link -> t_tsize !=
  1244.                            t -> t_link -> t_tsize) {
  1245.                             t_help("coerced pointer: beware of 68000 scalar alignment");
  1246.                         }
  1247.                     }
  1248.                 }
  1249.             }
  1250.             if (t -> t_tsize != t1 -> t_tsize) {
  1251.                 t_warning("type of mismatching width cast to pointer");
  1252.             }
  1253.             break;
  1254.  
  1255.         case STRUCT_TYPE:
  1256.         case UNION_TYPE:
  1257.         case FUNCTION_TYPE:
  1258.             t_error("cast into an aggregate");
  1259.             break;
  1260.         }
  1261.         break;
  1262.  
  1263.     case UMINUS_TOK:
  1264.         if (t1 -> t_typtok == INT_TYPE &&
  1265.                 t1 -> t_mclass & UNSIGNED_MOD) {
  1266.             t_warning("negation of unsigned item");
  1267.         }
  1268.         /* FALLTHROUGH */
  1269.         
  1270.     case TILDE_TOK:
  1271.     case UPLUS_TOK:
  1272.         if (t1 -> t_typtok != INT_TYPE) {
  1273.             t_2error("arithmetic on non-integer: ",
  1274.                             ps_tok(op));
  1275.             RETURN_BOOL("pe_type1", FALSE);
  1276.         }
  1277.         break;
  1278.  
  1279.     case UAND_TOK:
  1280.         (void) pe_islval(p1, UAND_TOK);
  1281.         t = new_tnode();
  1282.         t -> t_typtok = POINTER_TYPE;
  1283.         t -> t_tsize = POINTER_SIZE;
  1284.         t -> t_link = t1;
  1285.         p -> n_cltype = t;
  1286.         break;
  1287.  
  1288.     case NOT_TOK:
  1289.         p -> n_cltype = new_tnode();
  1290.         break;
  1291.  
  1292.     case PRE_INC_TOK:
  1293.     case PRE_DEC_TOK:
  1294.     case POST_INC_TOK:
  1295.     case POST_DEC_TOK:
  1296.         if (t1 -> t_typtok != INT_TYPE
  1297.                 && t1 -> t_typtok != POINTER_TYPE) {
  1298.             t_2error("nonscalar operand: ", ps_tok(op));
  1299.             RETURN_BOOL("pe_type1", FALSE);
  1300.         }
  1301.         if (!pe_islval(p1, op)) {
  1302.             RETURN_BOOL("pe_type1", FALSE);
  1303.         }
  1304.         if (t1 -> t_typtok == POINTER_TYPE &&
  1305.                 t1 -> t_link -> t_typtok == VOID_TYPE) {
  1306.             t_2error(ps_tok(op), " on pointer to void");
  1307.         }
  1308.         break;
  1309.  
  1310.     case USTAR_TOK:
  1311.         if (t1 -> t_typtok == POINTER_TYPE ||
  1312.                 t1 -> t_typtok == ARRAY_TYPE) {
  1313.             t1 = t1 -> t_link;
  1314.             if (t1 == NULL) {
  1315.                 t_error("internal: pointer to no-type");
  1316.                 RETURN_BOOL("pe_type1", FALSE);
  1317.             }
  1318.             else {
  1319.                 p -> n_cltype = t1;
  1320.             }
  1321.         }
  1322.         else {
  1323.             t_error("indirection on non-pointer");
  1324.             RETURN_BOOL("pe_type1", FALSE);
  1325.         }
  1326.         break;
  1327.  
  1328.     default:
  1329.         printf("unknown op %d\n", op);
  1330.         fatal("pe_type1: unknown unary op");
  1331.     }
  1332.     RETURN_BOOL("pe_type1", TRUE);
  1333. }
  1334.  
  1335. /*
  1336.     Set type of an expression involving a binary operator.
  1337.     A type always gets attached to p, and the routine returns
  1338.     FALSE if that type had to be made of whole cloth.
  1339.     (If it is desired to have the made-up type be VOID instead
  1340.     of INT, do it here, and don't change new_tnode!)
  1341. */
  1342. static bool
  1343. pe_type2(register struct node * p)
  1344. {
  1345.     register struct node *p1, *p2;
  1346.     register struct type_node *t, *t1, *t2;
  1347.     int op;
  1348.  
  1349.     TRACEPB("pe_type2", printf("(%p)\n", p));
  1350.  
  1351.     p1 = p -> n_arg1;
  1352.     p2 = p -> n_arg2;
  1353.  
  1354.     t1 = p1 -> n_cltype;
  1355.     t2 = p2 -> n_cltype;
  1356.  
  1357.     op = p -> n_type;
  1358.  
  1359.     if (t1 == NULL || (t2 == NULL && op != CALL_TOK)) {
  1360.         /* second arg of call is a list which presently has no type */
  1361.         t_2error("internal: untyped operand of: ", ps_tok(op));
  1362.         p -> n_cltype = new_tnode();
  1363.         RETURN_BOOL("pe_type2", FALSE);
  1364.     }
  1365.     p -> n_cltype = t1;
  1366.         /* this is the default return */
  1367.  
  1368.  
  1369.     /* handle the various ops */
  1370.     /* assignments continue on through for a post-check as well */
  1371.     switch (op) {
  1372.     case ASSN_TOK:
  1373.         switch(t1 -> t_typtok) {
  1374.         default:
  1375.             t_error("non-assignable lvalue type: =");
  1376.             RETURN_BOOL("pe_type2", FALSE);
  1377.         case INT_TYPE:
  1378.         case POINTER_TYPE:
  1379.             ;
  1380.         }
  1381.         if (!pd_taeq(t1, t2)) {
  1382.             if (t1 -> t_typtok == POINTER_TYPE) {
  1383.                 if (pe_zcheck(p2)) {
  1384.                     /* it's ok */
  1385.                 }
  1386.                 else if (t2 -> t_typtok == POINTER_TYPE ||
  1387.                       t2 -> t_typtok == ARRAY_TYPE) {
  1388.                     t_warning("pointers to different objects: =");
  1389.  
  1390.                     TRACE("pe_type2", pr_type(t1);
  1391.                                 pr_type(t2));
  1392.                     /* but proceed despite warning */
  1393.                 }
  1394.                 else {
  1395.                     t_error("type mismatch: =");
  1396.                     RETURN_BOOL("pe_type2", FALSE);
  1397.                 }
  1398.             }
  1399.             else {
  1400.                 if (t2 -> t_typtok == INT_TYPE &&
  1401.                         m_size(t1 -> t_mclass) == m_size(t2 -> t_mclass)) {
  1402.                     t_warning("type mismatch: =");
  1403.                 }
  1404.                 else {
  1405.                     t_error("type mismatch: =");
  1406.                     TRACEP("pe_type2",
  1407.                         pr_type(t1);
  1408.                         pr_type(t2);
  1409.                     );
  1410.                     RETURN_BOOL("pe_type2", FALSE);
  1411.                 }
  1412.             }
  1413.         }
  1414.         /* fall out of switch to lvalue check */
  1415.         break;
  1416.  
  1417.     case PLUS_ASSN_TOK:
  1418.     case MINUS_ASSN_TOK:
  1419.         switch(t1 -> t_typtok) {
  1420.         case INT_TYPE:
  1421.             switch (t2 -> t_typtok) {
  1422.             case POINTER_TYPE:
  1423.             case ARRAY_TYPE:
  1424.                 t_3serr(NULL, "integer ", ps_tok(op), " pointer");
  1425.                 RETURN_BOOL("pe_type2", FALSE);
  1426.             default:
  1427.                 t_2error("non-assignable type: ", ps_tok(op));
  1428.                 RETURN_BOOL("pe_type2", FALSE);
  1429.             case INT_TYPE:
  1430.                 if (!pd_teq(t1, t2)) {
  1431.                     t_2error("type mismatch: ", ps_tok(op));
  1432.                     RETURN_BOOL("pe_type2", FALSE);
  1433.                 }
  1434.                 break;
  1435.             }
  1436.             break;
  1437.  
  1438.         case POINTER_TYPE:
  1439.             if (t1 -> t_link -> t_typtok == VOID_TYPE) {
  1440.                 t_2error(ps_tok(op), " into pointer to void");
  1441.             }
  1442.             switch (t2 -> t_typtok) {
  1443.             case POINTER_TYPE:
  1444.             case ARRAY_TYPE:
  1445.                 t_3serr(NULL, "pointer ", ps_tok(op), " pointer");
  1446.                 RETURN_BOOL("pe_type2", FALSE);
  1447.             default:
  1448.                 t_2error("non-assignable type: ", ps_tok(op));
  1449.                 RETURN_BOOL("pe_type2", FALSE);
  1450.             case INT_TYPE:
  1451.                 break;
  1452.             }
  1453.             break;
  1454.  
  1455.         default:
  1456.             t_2error("non-assignable lvalue type: ", ps_tok(op));
  1457.             RETURN_BOOL("pe_type2", FALSE);
  1458.         }
  1459.         /* go do assignment check */
  1460.         break;
  1461.  
  1462.     case LSHIFT_ASSN_TOK:
  1463.     case RSHIFT_ASSN_TOK:
  1464.         if (t1 -> t_typtok != INT_TYPE || t2 -> t_typtok != INT_TYPE) {
  1465.             t_2error("non-numeric assignment: ", ps_tok(op));
  1466.             RETURN_BOOL("pe_type2", FALSE);
  1467.         }
  1468.         break;
  1469.  
  1470.     case AND_ASSN_TOK:
  1471.     case DIV_ASSN_TOK:
  1472.     case MOD_ASSN_TOK:
  1473.     case OR_ASSN_TOK:
  1474.     case STAR_ASSN_TOK:
  1475.     case XOR_ASSN_TOK:
  1476.         if (t1 -> t_typtok != INT_TYPE || t2 -> t_typtok != INT_TYPE) {
  1477.             t_2error("non-numeric assignment: ", ps_tok(op));
  1478.             RETURN_BOOL("pe_type2", FALSE);
  1479.         }
  1480.         else if (!pd_teq(t1, t2)) {
  1481.             t_2error("type mismatch: ", ps_tok(op));
  1482.             RETURN_BOOL("pe_type2", FALSE);
  1483.         }
  1484.         break;    /* go do assignment check */
  1485.  
  1486.     /* 6 relational operators and two boolean operators. */
  1487.     case EQUAL_TOK:
  1488.     case NE_TOK:
  1489.         if (t1 -> t_typtok == INT_TYPE) {
  1490.             p -> n_cltype = new_tnode();
  1491.             if (pd_teq(t1, t2)) {
  1492.                 RETURN_BOOL("pe_type2", TRUE);
  1493.             }
  1494.             if (t2 -> t_typtok == INT_TYPE &&
  1495.                     m_size(t1 -> t_mclass) == m_size(t2 -> t_mclass)) {
  1496.                 t_warning("type mismatch: =");
  1497.                 RETURN_BOOL("pe_type2", TRUE);
  1498.             }
  1499.             else {
  1500.                 t_2error("type mismatch: ", ps_tok(op));
  1501.                 RETURN_BOOL("pe_type2", FALSE);
  1502.             }
  1503.         }
  1504.         /* FALLTHROUGH */
  1505.     case GE_TOK:
  1506.     case GT_TOK:
  1507.     case LE_TOK:
  1508.     case LT_TOK:
  1509.         p -> n_cltype = new_tnode();
  1510.         switch(t1 -> t_typtok) {
  1511.         case INT_TYPE:
  1512.             if (pd_teq(t1, t2)) {
  1513.                 RETURN_BOOL("pe_type2", TRUE);
  1514.             }
  1515.             else {
  1516.                 t_2error("type mismatch: ", ps_tok(op));
  1517.                 RETURN_BOOL("pe_type2", FALSE);
  1518.             }
  1519.  
  1520.         case ARRAY_TYPE:
  1521.         case POINTER_TYPE:
  1522.             switch (t2 -> t_typtok) {
  1523.             case ARRAY_TYPE:
  1524.             case POINTER_TYPE:
  1525.                 if (!pd_taeq(t1, t2)) {
  1526.                     t_2warning("pointers to different objects: ", ps_tok(op));
  1527.                 }
  1528.                 RETURN_BOOL("pe_type2", TRUE);
  1529.  
  1530.             case INT_TYPE:
  1531.                 t_2error("type mismatch: ", ps_tok(op));
  1532.                 RETURN_BOOL("pe_type2", FALSE);
  1533.             }
  1534.         }
  1535.         t_2error("comparison with nonscalar: ", ps_tok(op));
  1536.         RETURN_BOOL("pe_type2", FALSE);
  1537.  
  1538.     case LAND_TOK:
  1539.     case LOR_TOK:
  1540.         p -> n_cltype = new_tnode();        
  1541.         switch(t1 -> t_typtok) {
  1542.         case INT_TYPE:
  1543.         case POINTER_TYPE:
  1544.         case ARRAY_TYPE:
  1545.             switch(t2 -> t_typtok) {
  1546.             case INT_TYPE:
  1547.             case POINTER_TYPE:
  1548.             case ARRAY_TYPE:
  1549.                             RETURN_BOOL("pe_type2", TRUE);
  1550.             }
  1551.         }
  1552.         t_2error("operand must be scalar: ", ps_tok(op));
  1553.         RETURN_BOOL("pe_type2", FALSE);
  1554.  
  1555.     case COMMA_TOK:
  1556.         p -> n_cltype = t2;
  1557.         mark_noneed(p1);
  1558.         RETURN_BOOL("pe_type2", TRUE);
  1559.  
  1560.     /* 2 addition operators. */
  1561.     case PLUS_TOK:
  1562.         switch(t1 -> t_typtok) {
  1563.         case INT_TYPE:
  1564.             switch(t2 -> t_typtok) {
  1565.             case INT_TYPE:
  1566.                 if (!pd_teq(t1, t2)) {
  1567.                     t_error("type mismatch: +");
  1568.                     RETURN_BOOL("pe_type2", FALSE);
  1569.                 }
  1570.                 break;
  1571.  
  1572.             case POINTER_TYPE:
  1573.                 if (t2 -> t_link -> t_typtok == VOID_TYPE) {
  1574.                     t_error("addition to pointer to void");
  1575.                 }
  1576.             case ARRAY_TYPE:
  1577.                 p -> n_cltype = t2;
  1578.                 break;
  1579.             default:
  1580.                 t_error("integer + nonscalar");
  1581.                 RETURN_BOOL("pe_type2", FALSE);
  1582.             }
  1583.             break;
  1584.     
  1585.         case POINTER_TYPE:
  1586.             if (t1 -> t_link -> t_typtok == VOID_TYPE) {
  1587.                 t_error("addition to pointer to void");
  1588.             }
  1589.  
  1590.         case ARRAY_TYPE:
  1591.             switch (t2 -> t_typtok) {
  1592.             case INT_TYPE:
  1593.                 break;
  1594.  
  1595.             case POINTER_TYPE:
  1596.             case ARRAY_TYPE:
  1597.                 t_error("pointer + pointer");
  1598.                 RETURN_BOOL("pe_type2", FALSE);
  1599.             default:
  1600.                 t_error("pointer + non-scalar");
  1601.                 RETURN_BOOL("pe_type2", FALSE);
  1602.             }
  1603.             break;
  1604.  
  1605.         default:
  1606.             t_error("non-scalar + something");
  1607.             RETURN_BOOL("pe_type2", FALSE);
  1608.         }
  1609.         RETURN_BOOL("pe_type2", TRUE);
  1610.  
  1611.     case MINUS_TOK:
  1612.         switch (t1 -> t_typtok) {
  1613.         case INT_TYPE:
  1614.             switch (t2 -> t_typtok) {
  1615.             case INT_TYPE:
  1616.                 if (!pd_teq(t1, t2)) {
  1617.                     t_error("type mismatch: -");
  1618.                     RETURN_BOOL("pe_type2", FALSE);
  1619.                 }
  1620.                 break;
  1621.  
  1622.             case POINTER_TYPE:
  1623.                 t_error("integer - pointer");
  1624.                 RETURN_BOOL("pe_type2", FALSE);
  1625.  
  1626.             default:
  1627.                 t_error("integer - nonscalar");
  1628.                 RETURN_BOOL("pe_type2", FALSE);
  1629.             }
  1630.             break;
  1631.  
  1632.         case POINTER_TYPE:
  1633.             if (t1 -> t_link -> t_typtok == VOID_TYPE) {
  1634.                 t_error("subtraction from pointer to void");
  1635.             }
  1636.  
  1637.         case ARRAY_TYPE:
  1638.             switch (t2 -> t_typtok) {
  1639.             case INT_TYPE:
  1640.                 break;
  1641.  
  1642.             case POINTER_TYPE:
  1643.             case ARRAY_TYPE:
  1644.                 /* pointer - pointer shall be long */
  1645.                 /* cast it if you want it truncated !!! */
  1646.                 p -> n_cltype = new_tnode();
  1647.                 p -> n_cltype -> t_mclass |= LONG_MOD;
  1648.                 break;
  1649.  
  1650.             default:
  1651.                 t_error("pointer - non-scalar");
  1652.                 RETURN_BOOL("pe_type2", FALSE);
  1653.             }
  1654.             break;
  1655.  
  1656.         default:
  1657.             t_error("non-scalar - something");
  1658.             RETURN_BOOL("pe_type2", FALSE);
  1659.         }
  1660.         RETURN_BOOL("pe_type2", TRUE);
  1661.  
  1662.     /* 8 miscellaneous arithmetic operators. */
  1663.     case AND_TOK:
  1664.     case OR_TOK:
  1665.     case XOR_TOK:
  1666.     case MOD_TOK:
  1667.     case STAR_TOK:
  1668.     case DIV_TOK:
  1669.         if (!pd_teq(t1, t2)) {
  1670.             t_2error("type mismatch: ", ps_tok(op));
  1671.             RETURN_BOOL("pe_type2", FALSE);
  1672.         }
  1673.         /* FALLTHROUGH */
  1674.  
  1675.     case LSHIFT_TOK:
  1676.     case RSHIFT_TOK:
  1677.         if (t1 -> t_typtok != INT_TYPE || t2 -> t_typtok != INT_TYPE) {
  1678.             t_2error("non-numeric operand: ", ps_tok(op));
  1679.             RETURN_BOOL("pe_type2", FALSE);
  1680.         }
  1681.         RETURN_BOOL("pe_type2", TRUE);
  1682.  
  1683.     case CALL_TOK:
  1684.         /* walk down function-returning link to get result type */
  1685.         if (t1 -> t_typtok != FUNCTION_TYPE) {
  1686.             t_error("function identifier isn't");
  1687.             RETURN_BOOL("pe_type2", FALSE);
  1688.         }
  1689.         t = t1 -> t_link;
  1690.         goto exit_check;
  1691.  
  1692.     case ARRAY_TOK:
  1693.         /* walk down the array-of link to get result type */
  1694.         if (t1 -> t_typtok != POINTER_TYPE
  1695.                      && t1 -> t_typtok != ARRAY_TYPE) {
  1696.             t_error("subscript applied to non-array");
  1697.             RETURN_BOOL("pe_type2", FALSE);
  1698.         }
  1699.         if (t2 -> t_typtok != INT_TYPE) {
  1700.             t_error("array subscript not int");
  1701.         }
  1702.         t = t1 -> t_link;
  1703.         goto exit_check;
  1704.  
  1705.     case DOT_TOK:
  1706.         if (t1 -> t_typtok == STRUCT_TYPE) {
  1707.             if (t2 -> t_typtok != SELEMENT_TYPE) {
  1708.                 t_error("struct . non-structelement");
  1709.                 RETURN_BOOL("pe_type2", FALSE);
  1710.             }
  1711.         }
  1712.         else if (t1 -> t_typtok == UNION_TYPE) {
  1713.             if (t2 -> t_typtok != UELEMENT_TYPE) {
  1714.                 t_error("union . non-unionelement");
  1715.                 RETURN_BOOL("pe_type2", FALSE);
  1716.             }
  1717.         }
  1718.         else {
  1719.             t_error("non-struct/union . something");
  1720.             RETURN_BOOL("pe_type2", FALSE);
  1721.         }
  1722.         t = t2 -> t_link;
  1723.         goto exit_check;
  1724.  
  1725.     case ARROW_TOK:
  1726.         if (t1 -> t_typtok == ARRAY_TYPE) {
  1727.             t_help("array -> something is bad form");
  1728.         }
  1729.         else if (t1 -> t_typtok != POINTER_TYPE) {
  1730.             t_error("non-pointer -> something");
  1731.             RETURN_BOOL("pe_type2", FALSE);
  1732.         }
  1733.         t = t1 -> t_link;
  1734.         if (t == NULL) {
  1735.             t_error("internal: pointer to undefined");
  1736.             RETURN_BOOL("pe_type2", FALSE);
  1737.         }
  1738.         else if (t -> t_typtok == STRUCT_TYPE) {
  1739.             if (t2 -> t_typtok != SELEMENT_TYPE) {
  1740.                 t_error("struct -> non-structelement");
  1741.                 RETURN_BOOL("pe_type2", FALSE);
  1742.             }
  1743.         }
  1744.         else if (t1 -> t_typtok == UNION_TYPE) {
  1745.             if (t2 -> t_typtok != UELEMENT_TYPE) {
  1746.                 t_error("union -> non-unionelement");
  1747.                 RETURN_BOOL("pe_type2", FALSE);
  1748.  
  1749.             }
  1750.         }
  1751.         else {
  1752.             t_warning("pointer on -> is not struct/union pointer");
  1753.         }
  1754.         t = t2 -> t_link;
  1755.  
  1756.     exit_check:
  1757.         if (t) {
  1758.             p -> n_cltype = t;
  1759.         }
  1760.         else {
  1761.             t_2error("internal: linked-NULL-type of operand of: ",
  1762.                                 ps_tok(op));
  1763.             RETURN_BOOL("pe_type2", FALSE);
  1764.         }
  1765.         RETURN_BOOL("pe_type2", TRUE);
  1766.  
  1767.     default:
  1768.         printf("unknown op %d\n", op);
  1769.         fatal("pe_type2: unknown binop");
  1770.     }
  1771.     /* assignments fall out of the switch! */
  1772.  
  1773.     /* check assignments */
  1774.     if (!pe_islval(p1, op)) {
  1775.         RETURN_BOOL("pe_type2", TRUE);
  1776.     }
  1777.     else if (t1 -> t_mclass & CONST_MOD) {
  1778.         t_2error(ps_tok(op), " into lvalue of const type");
  1779.         RETURN_BOOL("pe_type2", FALSE);    /* ekr */
  1780.     }
  1781.     else if (t1 -> t_typtok == POINTER_TYPE &&
  1782.         t2 -> t_typtok == POINTER_TYPE &&
  1783.         t1 -> t_link -> t_mclass & CONST_MOD &&
  1784.         !(t2 -> t_link -> t_mclass & CONST_MOD)) {
  1785.         t_2warning(ps_tok(op),
  1786.             " of pointer to non-const into pointer to const");
  1787.         RETURN_BOOL("pe_type2", FALSE);    /* ekr */
  1788.     }
  1789.  
  1790.     TICKX("pe_type2");
  1791. }
  1792.  
  1793. /*
  1794.     Set type of an expression involving a ternary operator.
  1795.     A type always gets attached to p, and the routine returns
  1796.     FALSE if that type had to be made of whole cloth.
  1797.     (If it is desired to have the made-up type be VOID instead
  1798.     of INT, do it here, and don't change new_tnode!)
  1799. */
  1800. static bool
  1801. pe_type3(register struct node * p)
  1802. {
  1803.     register struct node *p1, *p2, *p3;
  1804.     register struct type_node *t1, *t2, *t3;
  1805.  
  1806.     TRACEPB("pe_type3", printf("(%p)\n", p));
  1807.  
  1808.     p1 = p -> n_arg1;
  1809.     p2 = p -> n_arg2;
  1810.     p3 = p -> n_arg3;
  1811.  
  1812.     t1 = p1 -> n_cltype;
  1813.     t2 = p2 -> n_cltype;
  1814.     t3 = p3 -> n_cltype;
  1815.  
  1816.     p -> n_cltype = t2;
  1817.  
  1818.     if (p1 == NULL || p3 == NULL) {
  1819.         RETURN_BOOL("pe_type3", FALSE);
  1820.     }
  1821.  
  1822.     if (p -> n_type == QUESTION_TOK) {
  1823.         if (!pd_t1eq(t2, t3)) {
  1824.             if (t2 -> t_typtok == POINTER_TYPE &&
  1825.                     t3 -> t_typtok == POINTER_TYPE) {
  1826.                 t_warning("?: selects pointers to different types");
  1827.                 t_help("result of ?: is pointer to void");
  1828.                 t2 = new_tnode();
  1829.                 t2 -> t_typtok = VOID_TYPE;
  1830.                 t2 -> t_tsize = 0;
  1831.                 t3 = new_tnode();
  1832.                 t3 -> t_typtok = POINTER_TYPE;
  1833.                 t3 -> t_tsize = POINTER_SIZE;
  1834.                 t3 -> t_link = t2;
  1835.                 p -> n_cltype = t3;
  1836.             }
  1837.             else {
  1838.                 t_error("?: selects items of different types");
  1839.             }
  1840.             RETURN_BOOL("pe_type3", FALSE); /* disallow reduce */
  1841.         }
  1842.         if (t1) {
  1843.             switch(t1 -> t_typtok) {
  1844.             default:
  1845.                 t_error("switch in ?: is of unusable type");
  1846.                 RETURN_BOOL("pe_type3", FALSE);
  1847.             case INT_TYPE:
  1848.             case POINTER_TYPE:
  1849.                 ;
  1850.             }
  1851.         }
  1852.         else {
  1853.             t_error("internal: untyped switch in ?:");
  1854.         }
  1855.     }
  1856.     else {
  1857.         printf("unknown op %d\n", p -> n_type);
  1858.         fatal("pe_type3: unknown ternary op");
  1859.     }
  1860.     RETURN_BOOL("pe_type3", TRUE);
  1861. }
  1862.  
  1863. /*
  1864.     Fold expressions involving a unary operator.
  1865. */
  1866. static struct node *
  1867. pe_fold1(register struct node * p)
  1868. {
  1869.     register struct node *p1;
  1870.     register struct type_node *t, *t1;
  1871.     register long value, val1;
  1872.     register int op;
  1873.  
  1874.     TICK("pe_fold1");
  1875.  
  1876.     p1 = p -> n_arg1;
  1877.     if ((op = p -> n_type) == CAST_TOK) {
  1878.         if (!pe_sprim(p1) ||
  1879.             (t = p -> n_cltype) == NULL ||
  1880.             (t1 = p1 -> n_cltype) == NULL) {
  1881.             return NULL;
  1882.         }
  1883.         /* do according to cast type itself */
  1884.         switch (t -> t_typtok) {
  1885.         case INT_TYPE:
  1886.             switch (t1 -> t_typtok) {
  1887.             case POINTER_TYPE:
  1888.             case ARRAY_TYPE:
  1889.                 t1 -> t_typtok = INT_TYPE;
  1890.                 t1 -> t_mclass = UNSIGNED_MOD & LONG_MOD;
  1891.                 t1 -> t_tdim = 0;
  1892.                 t1 -> t_tsize = 4;
  1893.                 
  1894.                 /* FALL_THROUGH */
  1895.             case INT_TYPE:
  1896.                 pe_retype(t -> t_mclass, p1, op);
  1897.                 break;
  1898.  
  1899.             default:
  1900.                 t_error("cast on nonscalar constant: shouldn't happen");
  1901.             }
  1902.             break;
  1903.  
  1904.         case POINTER_TYPE:
  1905.         case ARRAY_TYPE:
  1906.             /* constant pointer is manifest; no warning */
  1907.             p1 -> n_cltype = t;
  1908.             break;
  1909.  
  1910.         default:
  1911.             t_error("cast into non-scalar");
  1912.         }
  1913.         t1 -> t_mclass |= CONST_MOD;
  1914.         return p1;
  1915.     }    
  1916.     else {
  1917.         if (!pe_number(p1)) {
  1918.             return NULL;
  1919.         }
  1920.         switch(op) {
  1921.         case NOT_TOK:
  1922.             p1 -> n_const = (long) !p1 -> n_const;
  1923.             p1 -> n_cltype -> t_mclass &= ~ARITH_MODS;
  1924.             return p1;
  1925.  
  1926.         case UMINUS_TOK:
  1927.             if (p1 -> n_cltype -> t_mclass & UNSIGNED_MOD) {
  1928.                 t_warning("negation of unsigned constant; result unsigned");
  1929.             }
  1930.             p1 -> n_const = - p1 -> n_const;
  1931.             /* FALLTHROUGH */
  1932.  
  1933.         case UPLUS_TOK:
  1934.             return p1;
  1935.  
  1936.         case TILDE_TOK:
  1937.             p1 -> n_const = ~p1 -> n_const;
  1938.             return p1;
  1939.         }
  1940.     }    
  1941.     return NULL;
  1942. }
  1943.  
  1944. /*
  1945.     Fold an expression involving a binary operator.
  1946.     Only arithmetic and relational operators may be folded.
  1947.     The problem of assignment into a constant is handled by pe_type2().
  1948. */
  1949. static struct node *
  1950. pe_fold2(register struct node * p)
  1951. {
  1952.     union {
  1953.         long sval;
  1954.         unsigned long uval;
  1955.     } value, val1, val2;
  1956.     register int op, m1, m2;
  1957.     register struct node *p1, *p2;
  1958.     struct type_node *t1, *t2;
  1959.  
  1960.     TICK("pe_fold2");
  1961.  
  1962.     /* WARNING: it also might attempt to fold the subtraction
  1963.         of two addresses */
  1964.  
  1965.     TRACEP("pe_fold2", printf("op=%d, %s\n",
  1966.                     p -> n_type, ps_tok(p -> n_type)));
  1967.  
  1968.     op = p -> n_type;
  1969.     p1 = p -> n_arg1;
  1970.     p2 = p -> n_arg2;
  1971.  
  1972.     t1 = p1 -> n_cltype;
  1973.     t2 = p2 -> n_cltype;
  1974.  
  1975.     if (t1 == NULL || t2 == NULL) {
  1976.         fatal("pe_fold2: untyped operand");
  1977.     }
  1978.     if (op == PLUS_TOK) {
  1979.         if (pe_number(p1)) {
  1980.             /*
  1981.                 NOTE: for the following multiplication, it
  1982.                 is unnecessary to distinguish between signed
  1983.                 and unsigned operands, since they all lead to
  1984.                 the same bit-pattern, which is added in the
  1985.                 same way to the pointer.  That is, all effects
  1986.                 of operand signs lie outside the low 32 bits
  1987.                 and are therefore never extant.  See note on
  1988.                 signed vs unsigned multiplication.
  1989.             */
  1990.             if (t2 -> t_typtok != INT_TYPE && pe_sprim(p2)) {
  1991.                 TRACEP("pe_fold2", printf("fold pointer\n"));
  1992.                 p2 -> n_const +=
  1993.                     p1->n_const * (long) t2 -> t_link -> t_tsize;
  1994.                 return p2;
  1995.             }
  1996.         }
  1997.         else if (pe_number(p2)) {
  1998.             if (t1 -> t_typtok != INT_TYPE && pe_sprim(p1)) {
  1999.                 TRACEP("pe_fold2", printf("fold pointer\n"));
  2000.                 p1 -> n_const +=
  2001.                     p2->n_const * (long) t1 -> t_link -> t_tsize;
  2002.                 return p1;
  2003.             }
  2004.         }
  2005.     }
  2006.  
  2007.     /* massage constant types and short out certain constants */
  2008.     if (!pe_number(p1)) {
  2009.         if (pe_number(p2)) {
  2010.             switch(op) {
  2011.             case PLUS_TOK:
  2012.             case PLUS_ASSN_TOK:
  2013.             case MINUS_TOK:
  2014.             case MINUS_ASSN_TOK:
  2015.                 if (p2 -> n_const == 0) {
  2016.                     return p1;
  2017.                 }
  2018.                 break;
  2019.             case STAR_TOK:
  2020.             case STAR_ASSN_TOK:
  2021.             case DIV_TOK:
  2022.             case DIV_ASSN_TOK:
  2023.                 if (p2 -> n_const == 1) {
  2024.                     return p1;
  2025.                 }
  2026.                 break;
  2027.             case MOD_TOK:
  2028.                 if (p2 -> n_const == 1) {
  2029.                     p2 -> n_const = 0;
  2030.                     return p2;
  2031.                 }
  2032.                 break;
  2033.             case LSHIFT_TOK:
  2034.             case LSHIFT_ASSN_TOK:
  2035.             case RSHIFT_TOK:
  2036.             case RSHIFT_ASSN_TOK:    
  2037.                 if (p2 -> n_const == 0) {
  2038.                     return p1;
  2039.                 }
  2040.                 break;
  2041.             }
  2042.             pe_massage(t1, p2, op);
  2043.         }
  2044.         return NULL;
  2045.     }
  2046.     else if (!pe_number(p2)) {
  2047.         switch(op) {
  2048.         case PLUS_TOK:
  2049.             if (p1 -> n_const == 0) {
  2050.                 return p2;
  2051.             }
  2052.             break;
  2053.         case MINUS_TOK:
  2054.             /* CAUTION: assumption about unop_node and binop_node
  2055.                 similarity */
  2056.             if (p1 -> n_const == 0) {
  2057.                 p -> n_type = UMINUS_TOK;
  2058.                 p -> n_arg1 = p2;
  2059.                 (void) pe_type1(p);
  2060.                 return p;
  2061.             }
  2062.             break;
  2063.         case STAR_TOK:
  2064.             if (p1 -> n_const == 1) {
  2065.                 return p2;
  2066.             }
  2067.             break;
  2068.         case LSHIFT_TOK:
  2069.         case RSHIFT_TOK:
  2070.             if (p1 -> n_const == 0) {
  2071.                 return p1;
  2072.             }
  2073.             break;
  2074.         }
  2075.         if (!is_assnop(op)) {
  2076.             pe_massage(t2, p1, op);
  2077.         }
  2078.         return NULL;
  2079.     }
  2080.             
  2081.     TRACEP("pe_fold2", printf("folding two constants\n"));
  2082.     if (op == COMMA_TOK) {
  2083.         t_warning("constant , constant");
  2084.         return NULL;
  2085.     }
  2086.     /* 
  2087.         when folding two constants, use the K&R rules.
  2088.         we choose to do this with constants because of a
  2089.         variety of practical problems that arise otherwise
  2090.  
  2091.         note that using a constant expression as a function
  2092.         argument is a very dangerous business, expecially if
  2093.         macros are involved, and it may be well to cast such
  2094.         things explicitly; such casts raise warnings in C-Star
  2095.         if the cast type is too narrow to hold the object
  2096.     */
  2097.     if ((m1 = t1 -> t_mclass) != (m2 = t2 -> t_mclass)) {
  2098.         if (m1 & LONG_MOD && !(m2 & LONG_MOD)) {
  2099.             pe_retype(m1 | (m2 & UNSIGNED_MOD), p2, op);
  2100.             m2 = t2 -> t_mclass;
  2101.         }
  2102.         else if (m2 & LONG_MOD && !(m1 & LONG_MOD)) {
  2103.             pe_retype(m2 | (m1 & UNSIGNED_MOD), p1, op);
  2104.             m1 = t1 -> t_mclass;
  2105.         }
  2106.         else if (m2 & CHAR_MOD && !(m1 & CHAR_MOD)) {
  2107.             pe_retype(m1 | (m2 & UNSIGNED_MOD), p2, op);
  2108.             m2 = t2 -> t_mclass;
  2109.         }
  2110.         else if (m1 & CHAR_MOD && !(m2 & CHAR_MOD)) {
  2111.             pe_retype(m2 | (m1 & UNSIGNED_MOD), p1, op);
  2112.             m1 = t1 -> t_mclass;
  2113.         }
  2114.         /* now they are both the same length */
  2115.         if (m1 & UNSIGNED_MOD && !(m2 & UNSIGNED_MOD)) {
  2116.             pe_retype(m1, p2, op);
  2117.             m2 = m1;
  2118.         }
  2119.         else if (m2 & UNSIGNED_MOD && !(m1 & UNSIGNED_MOD)) {
  2120.             pe_retype(m2, p1, op);
  2121.             m1 = m2;
  2122.         }
  2123.     }
  2124.     /* now they are standardly signed versus unsigned */
  2125.         
  2126.         
  2127.     
  2128.     val1.sval = p1 -> n_const;
  2129.     val2.sval = p2 -> n_const;
  2130.  
  2131.     if (m1 & UNSIGNED_MOD) {
  2132.     switch (op) {
  2133.     case GE_TOK:     value.sval = (long)(val1.uval >= val2.uval);    break;
  2134.     case GT_TOK:     value.sval = (long)(val1.uval >  val2.uval);    break;
  2135.     case LE_TOK:     value.sval = (long)(val1.uval <= val2.uval);    break;
  2136.     case LT_TOK:     value.sval = (long)(val1.uval <  val2.uval);    break;
  2137.  
  2138.     case STAR_TOK:     value.uval = val1.uval * val2.uval;    break;
  2139.     case DIV_TOK:    if (val2.uval == 0) {
  2140.                 value.uval = 0;
  2141.                 t_error("division by zero: /");
  2142.             }
  2143.             else {
  2144.                 value.uval = val1.uval / val2.uval;
  2145.             }
  2146.             break;
  2147.  
  2148.     case MOD_TOK:    if (val2.uval == 0) {
  2149.                 t_error("division by zero: %");
  2150.                 value.uval = 0;
  2151.             }
  2152.             else {
  2153.                 value.uval = val1.uval % val2.uval;
  2154.             }
  2155.             break;
  2156.     default:
  2157.         goto sign_ed;
  2158.     } /* end switch */
  2159.     goto around;
  2160.     } /* end if clause */
  2161. sign_ed:
  2162.     switch (op) {
  2163.     /* 6 relational operators. */
  2164.     case GE_TOK:     value.sval = (long)(val1.sval >= val2.sval);    break;
  2165.     case GT_TOK:     value.sval = (long)(val1.sval >  val2.sval);    break;
  2166.     case LE_TOK:     value.sval = (long)(val1.sval <= val2.sval);    break;
  2167.     case LT_TOK:     value.sval = (long)(val1.sval <  val2.sval);    break;
  2168.     case EQUAL_TOK:     value.sval = (long)(val1.sval == val2.sval);    break;
  2169.     case NE_TOK:     value.sval = (long)(val1.sval != val2.sval);    break;
  2170.  
  2171.     /* 10 arithmetic operators. */
  2172.     case LSHIFT_TOK: value.sval = val1.sval << val2.sval;    break;
  2173.     case RSHIFT_TOK: value.sval = val1.sval >> val2.sval;    break;
  2174.     case AND_TOK:     value.sval = val1.sval & val2.sval;    break;
  2175.     case OR_TOK:     value.sval = val1.sval | val2.sval;    break;
  2176.     case XOR_TOK:     value.sval = val1.sval ^ val2.sval;    break;
  2177.     case PLUS_TOK:     value.sval = val1.sval + val2.sval;    break;
  2178.     case MINUS_TOK:     value.sval = val1.sval - val2.sval;    break;
  2179.  
  2180.     case STAR_TOK:     value.sval = val1.sval * val2.sval;    break;
  2181.     case DIV_TOK:    if (val2.sval == 0) {
  2182.                 value.sval = 0;
  2183.                 t_error("division by zero: /");
  2184.             }
  2185.             else {
  2186.                 value.sval = val1.sval / val2.sval;
  2187.             }
  2188.             break;
  2189.  
  2190.     case MOD_TOK:    if (val2.sval == 0) {
  2191.                 t_error("division by zero: %");
  2192.                 value.sval = 0;
  2193.             }
  2194.             else {
  2195.                 value.sval = val1.sval % val2.sval;
  2196.             }
  2197.             break;
  2198.     default:
  2199.         return NULL;
  2200.     }
  2201. around:
  2202.  
  2203.     /* Return pointer to updated constant node. */
  2204.     p1 -> n_const = value.sval;
  2205.  
  2206.     /* Fiddle with the result width */
  2207.     switch (op) {
  2208.     case GE_TOK:
  2209.     case GT_TOK:
  2210.     case LE_TOK:
  2211.     case LT_TOK:
  2212.     case EQUAL_TOK:
  2213.     case NE_TOK:
  2214.         t1 -> t_mclass &= ~ARITH_MODS;
  2215.         break;
  2216.  
  2217.     case AND_TOK:
  2218.     case OR_TOK:
  2219.     case XOR_TOK:
  2220.     case PLUS_TOK:
  2221.     case MINUS_TOK:
  2222.     case STAR_TOK:
  2223.     case DIV_TOK:
  2224.     case MOD_TOK:
  2225.         if (pe_oversize(m1, value.sval)) {
  2226.             if (m1 & CHAR_MOD) {
  2227.                 m1 &= ~SIZE_MODS;
  2228.                 t1 -> t_tsize = INT_SIZE;
  2229.                 t_2warning("constant result is int: ",
  2230.                                 ps_tok(p -> n_type));
  2231.             }
  2232.             else {
  2233.                 m1 &= ~SIZE_MODS;
  2234.                 m1 |= LONG_MOD;
  2235.                 t1 -> t_tsize = LONG_SIZE;
  2236.                 t_2warning("constant result is long: ",
  2237.                                 ps_tok(p -> n_type));
  2238.             }
  2239.         }
  2240.         t1 -> t_mclass = m1;
  2241.         break;
  2242.     }
  2243.     return p1;
  2244. }
  2245.  
  2246. /*
  2247.     t1 is a type and p2 is a manifest constant.
  2248.     attach t1 to p2 in certain cases.
  2249. */
  2250. void
  2251. pe_massage(register struct type_node *t1, register struct node *p2, int op)
  2252. {
  2253.     TRACEPB("pe_massage", printf("(%p, %p, %d)\n", t1, p2, op));
  2254.     TRACE("pe_massage",
  2255.         pr_type(t1);
  2256.         printf("<< %s >>\n",
  2257.         ps_tok(op));
  2258.         pr_type(p2 -> n_cltype);
  2259.         printf("\n"));
  2260.  
  2261.     switch(t1 -> t_typtok) {
  2262.     case POINTER_TYPE:
  2263.  
  2264.         TRACEP("pe_massage", printf("pointer <> %ld\n",
  2265.                 p2 -> n_const));
  2266.         switch(op) {
  2267.         case ASSN_TOK:
  2268.         case EQUAL_TOK:
  2269.         case NE_TOK:
  2270.             /* in the case of constant zero, force a match */
  2271.             if (p2 -> n_const == 0) {
  2272.                 TRACEP("pe_massage", printf("  substitute\n"));
  2273.                 p2 -> n_cltype = t1;
  2274.             }
  2275.         }
  2276.         break;
  2277.  
  2278.     case INT_TYPE:
  2279.         switch(op) {
  2280.         /*
  2281.             shift-operators have no length constraints
  2282.             and so they need not be massaged
  2283.         */
  2284.         case GE_TOK:
  2285.         case GT_TOK:
  2286.         case LE_TOK:
  2287.         case LT_TOK:
  2288.         case EQUAL_TOK:
  2289.         case NE_TOK:
  2290.  
  2291.         case ASSN_TOK:
  2292.         case PLUS_ASSN_TOK:
  2293.         case MINUS_ASSN_TOK:
  2294.         case AND_ASSN_TOK:
  2295.         case OR_ASSN_TOK:
  2296.         case XOR_ASSN_TOK:
  2297.         case STAR_ASSN_TOK:
  2298.         case DIV_ASSN_TOK:
  2299.         case MOD_ASSN_TOK:
  2300.         
  2301.         case AND_TOK:
  2302.         case OR_TOK:
  2303.         case XOR_TOK:
  2304.         case PLUS_TOK:
  2305.         case MINUS_TOK:
  2306.  
  2307.         case STAR_TOK:
  2308.         case DIV_TOK:
  2309.         case MOD_TOK:
  2310.             pe_retype(t1 -> t_mclass, p2, op);
  2311.             break;
  2312.         }
  2313.         break;
  2314.     }
  2315.  
  2316.     TICKX("pe_massage");
  2317. }
  2318.  
  2319. /*
  2320.     copy int mclass into int type of CONSTANT p2.
  2321.     do not do this to declared items; their typenodes are NOT unique
  2322.     raise various warnings.
  2323. */
  2324. void
  2325. pe_retype(int mclass, register struct node *p2, int op)
  2326. {
  2327.     register struct type_node *t2;
  2328.  
  2329.     TRACEPB("pe_retype", printf("(%d, %p, %d)\n", mclass, p2, op));
  2330.     TRACEP("pe_retype",
  2331.         printf("across %s\n", ps_tok(op));
  2332.         if(ps_tok(op) == NULL) {
  2333.             printf("op=%d\n", op);
  2334.         });
  2335.  
  2336.     t2 = p2 -> n_cltype;
  2337.     pe_cl_check(t2 -> t_mclass, mclass, p2 -> n_const, op);
  2338.     t2 -> t_mclass &= ~ARITH_MODS;
  2339.     t2 -> t_mclass |= mclass & ARITH_MODS;
  2340.     t2 -> t_tsize = m_size(mclass);
  2341.  
  2342.     TICKX("pe_retype");
  2343. }
  2344.  
  2345. /*
  2346.     generate warnings pursuant to copying or changing a constant from one
  2347.     mclass into another
  2348. */
  2349. static void
  2350. pe_cl_check(int oldclass, int newclass, long value, int op)
  2351. {
  2352.     register int o;
  2353.  
  2354.     TRACEPB("pe_cl_check", printf("(%d, %d, %ld, %d)\n", oldclass, newclass, value, op));
  2355.  
  2356.     if ( (newclass & UNSIGNED_MOD) &&
  2357.                 !(oldclass & UNSIGNED_MOD) && value < 0) {
  2358.         t_2warning("negative constant converted to unsigned: ", ps_tok(op));
  2359.     }
  2360.     if (o = pe_oversize(newclass, value)) {
  2361.         if (o == 1) {
  2362.             if ( (newclass & CHAR_MOD) && (oldclass & CHAR_MOD) ) {
  2363.             }
  2364.             else {
  2365.                 t_2warning("positive constant becomes negative: ", ps_tok(op));
  2366.             }
  2367.         }
  2368.         else {
  2369.             t_2error("oversize constant: ", ps_tok(op));
  2370.         }
  2371.     }
  2372.  
  2373.     TICKX("pe_cl_check");
  2374. }
  2375.  
  2376. /*
  2377.     Return nonzero if an integer constant doesn't fit its mclass
  2378. */
  2379. int
  2380. pe_oversize(int mclass, long value)
  2381. {
  2382.     register long m;
  2383.  
  2384.     TRACEPB("pe_oversize", printf("(%d, %ld)\n", mclass, value));
  2385.  
  2386.     m = 0xFFFF0000L;
  2387.     if (mclass & LONG_MOD) {
  2388.         m = 0;
  2389.     }
  2390.     else if (mclass & CHAR_MOD) {
  2391.         m = 0xFFFFFF00L;
  2392.     }
  2393.     if ((value & m) != 0 && (~value & m) != 0 ) {
  2394.         /* constant won't fit, period */
  2395.         RETURN_INT("pe_oversize", 2);
  2396.     }
  2397.     if (!(mclass & UNSIGNED_MOD)) {
  2398.         /* RIGHT shift with negative-sign insertion */
  2399.         m >>= 1;
  2400.         m |= 0x80000000L;
  2401.         if ((value & m) != 0 && (~value & m) != 0 ) {
  2402.             /* unsigned overflows to negative */
  2403.             RETURN_INT("pe_oversize", 1);
  2404.         }
  2405.     }
  2406.     RETURN_INT("pe_oversize", 0);
  2407. }
  2408.  
  2409. /*
  2410.     Return the size of a manifest numeric constant; or else 0 if
  2411.     it's not.
  2412. */
  2413. int
  2414. pe_number(struct node * p)
  2415. {
  2416.     register struct type_node * t;
  2417.  
  2418.     TRACEPB("pe_number", printf("(%p)\n", p));
  2419.  
  2420.     if (p == NULL || p -> n_type != ID_TOK) {
  2421.         RETURN_INT("pe_number", 0);
  2422.     }
  2423.     if (p -> n_mode || p -> n_cid || p -> n_reg1) {
  2424.         RETURN_INT("pe_number", 0);
  2425.     }
  2426.     if (t = p -> n_cltype) {
  2427.         if (t -> t_typtok == INT_TYPE) {
  2428.             RETURN_INT("pe_number", (int) t -> t_tsize);
  2429.         }
  2430.     }
  2431.     RETURN_INT("pe_number", 0);
  2432. }
  2433.  
  2434. /*
  2435.     Return the size of a manifest numeric constant; or else 0 if
  2436.     it's not.
  2437. */
  2438. static int
  2439. pe_sprim(struct node * p)
  2440. {
  2441.     register struct type_node * t;
  2442.  
  2443.     TRACEPB("pe_sprim", printf("(%p)\n", p));
  2444.  
  2445.     if (p == NULL || p -> n_type != ID_TOK) {
  2446.         RETURN_INT("pe_sprim", 0);
  2447.     }
  2448.     if (p -> n_mode || p -> n_cid || p -> n_reg1) {
  2449.         RETURN_INT("pe_sprim", 0);
  2450.     }
  2451.     if (t = p -> n_cltype) {
  2452.         switch(t -> t_typtok) {
  2453.         case INT_TYPE:
  2454.         case POINTER_TYPE:
  2455.         case ARRAY_TYPE:
  2456.             RETURN_INT("pe_sprim", (int) t -> t_tsize);
  2457.         }
  2458.     }
  2459.     RETURN_INT("pe_sprim", 0);
  2460. }
  2461.  
  2462. /*
  2463.     Parse a (syntactical) primitive and return a pointer.
  2464.  
  2465.     Return a pointer to a suitable node.
  2466.  
  2467.     Items treated as primitives are:
  2468.         identifier
  2469.         constant (including sizeof)
  2470.         Dn, An
  2471. */
  2472. static struct node *
  2473. pe_prim(void)
  2474. {
  2475.     register struct node *p;
  2476.     register struct st_node *id;
  2477.     register struct type_node *t, *t1;
  2478.  
  2479.     TRACEPB("pe_prim", printf("called on t_type %d\n",t_type));
  2480.  
  2481.     switch (t_type) {
  2482.  
  2483.     case INT_TOK:
  2484.     case LONG_TOK:
  2485.     case CHAR_TOK:
  2486.     case K_SIZEOF:
  2487.     case STRING_TOK:
  2488.         p = pe_cprim();
  2489.         break;
  2490.  
  2491.     case CC_TOK:
  2492.     case ID_TOK:
  2493.  
  2494.         TRACEP("pe_prim", printf("id, subtype %d\n", t_subtype));
  2495.  
  2496.         p = new_pnode(sizeof(struct loc_node));
  2497.         p -> n_reg1 = real_reg(t_subtype);
  2498.         id = ast_lookup(t_symbol);
  2499.         if (id == NULL) {
  2500.             t = new_tnode();
  2501.             id = rst_enter(t_symbol, t, NULL_CLASS);
  2502.             get_token();
  2503.             if (t_type == LPAREN_TOK && t_subtype == 0) {
  2504.                 /* assume it's a function name */
  2505.                 /* implicit declaration */
  2506.                 t1 = new_tnode();
  2507.                 t1 -> t_typtok = FUNCTION_TYPE;
  2508.                 t1 -> t_tsize = 0;
  2509.                 t1 -> t_link = t;
  2510.                 id -> st_type = t1;
  2511.                 id -> st_sclass = CODE_CLASS;
  2512.             }
  2513.             else if (t_subtype == 0) {
  2514.                 t_2error("undefined variable: ", id -> st_name);
  2515.             }
  2516.             else {
  2517.                 t_2error("undefined register: ", id -> st_name);
  2518.             }
  2519.         }
  2520.         else {
  2521.             get_token();
  2522.         }
  2523.         p -> n_cltype = id -> st_type;
  2524.         if (p -> n_reg1 == 0) {
  2525.             p -> n_cid = id; /* points to symbol table entry */
  2526.         }
  2527.         break;
  2528.  
  2529.     default:
  2530.         need(NULL_TOK);
  2531.         p = NULL;
  2532.     }
  2533.     RETURN_PTR("pe_prim", p);
  2534. }
  2535.  
  2536. /*
  2537.     Parse a primitive constant.
  2538.     This must EITHER
  2539.         return something
  2540.     OR
  2541.         flag t_error
  2542. */
  2543. static struct node *
  2544. pe_cprim(void)
  2545. {
  2546.     register struct node * p;
  2547.     register struct type_node *t, *t1;    
  2548.     register struct st_node *id;
  2549.     register unsigned long len;
  2550.  
  2551.     TICKB("pe_cprim");
  2552.  
  2553.     t = new_tnode();
  2554.     t -> t_mclass |= CONST_MOD;
  2555.  
  2556.     p = new_pnode(sizeof(struct loc_node));
  2557.     p -> n_type = ID_TOK;
  2558.     p -> n_cltype = t;
  2559.  
  2560.     TRACE("pe_cprim", printf("loc_node = %p\n", p));
  2561.  
  2562.     switch(t_type) {
  2563.     case INT_TOK:
  2564.         TRACEP("pe_cprim",
  2565.             printf("short integer %ld 0x%lx\n",
  2566.                 t_value, t_value));
  2567.  
  2568.         p -> n_const = t_value;
  2569.         if (p -> n_const > INT_MAX || p -> n_const < - INT_MAX - 1) {
  2570.             /*
  2571.                 this warning is especially important in function
  2572.                 calls if ints don't default to long size,
  2573.                 which they don't unless some changes are made
  2574.             */
  2575.             t_help("constant taken as long");
  2576.             t -> t_mclass |= LONG_MOD;
  2577.             t -> t_tsize = LONG_SIZE;
  2578.         }
  2579.         get_token();
  2580.         break;
  2581.  
  2582.     case LONG_TOK:
  2583.         TRACEP("pe_cprim",
  2584.             printf("long integer %ld 0x%lx\n",
  2585.                 t_value, t_value));
  2586.  
  2587.         p -> n_const = t_value;
  2588.         t -> t_mclass |= LONG_MOD;
  2589.         t -> t_tsize = LONG_SIZE;
  2590.         get_token();
  2591.         break;
  2592.  
  2593.     case CHAR_TOK:
  2594.         TRACEP("pe_cprim",
  2595.             printf("char (byte) %ld 0x%lx\n",
  2596.                 t_value, t_value));
  2597.  
  2598.         p -> n_const = t_value;
  2599.         t -> t_typtok = INT_TYPE;
  2600.         t -> t_mclass |= (CHAR_MOD | UNSIGNED_MOD);
  2601.         t -> t_tsize = 1;
  2602.         get_token();
  2603.         break;
  2604.  
  2605.     case K_SIZEOF:
  2606.         p -> n_const = (long) pe_sizeof();
  2607.         if (p -> n_const > INT_MAX) {
  2608.             t_help("result of sizeof is long");
  2609.             t -> t_mclass |= LONG_MOD;
  2610.             t -> t_tsize = LONG_SIZE;
  2611.         }
  2612.         break;
  2613.  
  2614.     case STRING_TOK:
  2615.         /*
  2616.             NOTE:    ANSI says such a string shouldn't be
  2617.                 CONST.  We may need to provide such
  2618.                 an option eventually.
  2619.         */
  2620.         t -> t_typtok = INT_TYPE;
  2621.         t -> t_mclass |= CHAR_MOD | CONST_MOD;
  2622.         t -> t_tsize = 1;
  2623.         
  2624.         t1 = new_tnode();
  2625.         t1 -> t_typtok = ARRAY_TYPE;
  2626.  
  2627.         t1 -> t_link = t;
  2628.         t1 -> t_mclass |= CONST_MOD;
  2629.  
  2630.         p -> n_cltype = t1;
  2631.  
  2632.         /*
  2633.             now make up an internal label. treat the string
  2634.             as a static global in order to get the aliasing right
  2635.         */
  2636.         p -> n_cid = id = rst_enter(str_name(), t1, STATICG_CLASS);
  2637.         id -> st_alias = id -> st_name;
  2638.  
  2639.         id -> st_iniz = new_iblock(1L);
  2640.         len = (unsigned long) str_val(t_symbol);
  2641.         id -> st_iniz -> idim = t1 -> t_tdim = t1 -> t_tsize = len;
  2642.         id -> st_iniz -> idata[0] . ipt =
  2643.             chr_salloc(t_symbol, (int) len);
  2644.         id -> st_iniz -> itype = ISTRA_DEC;
  2645.  
  2646.         t = new_tnode();
  2647.         t -> t_typtok = DELEMENT_TYPE;
  2648.         t -> t_parent = p -> n_cid;
  2649.         t -> t_tsize = t1 -> t_tsize;
  2650.         t -> t_link = t1;
  2651.  
  2652.         if (intrn_decl) {
  2653.             intrn_ptr -> t_list = t;
  2654.         }
  2655.         else {
  2656.             intrn_decl = t;
  2657.         }
  2658.         intrn_ptr = t;
  2659.  
  2660.         get_token();
  2661.         break;
  2662.  
  2663.     default:
  2664.         t_2error("internal: pe_cprim: called with bad type at: ",
  2665.             t_symbol);
  2666.     }
  2667.     RETURN_PTR("pe_cprim", p);
  2668. }
  2669.  
  2670. /*
  2671.     Return the RESULT of a sizeof expression; a number, not a node.
  2672. */
  2673. static unsigned long
  2674. pe_sizeof(void)
  2675. {
  2676.     register struct node * p;
  2677.     register struct type_node *t;
  2678.     register unsigned long size;
  2679.  
  2680.     TICKB("pe_sizeof");
  2681.  
  2682.     get_token(); /* eat the K_SIZEOF */
  2683.     need(LPAREN_TOK);
  2684.     if ((t = pd_cast()) != NULL) {
  2685.         size = t -> t_tsize;
  2686.         if (size == 0) {
  2687.             t_error("sizeof returns zero");
  2688.         }
  2689.     }
  2690.     else {
  2691.         p = pe_expr1(TRUE);
  2692.         if (p == NULL) {
  2693.             t_error("sizeof has no argument");
  2694.             size = 0;
  2695.         }
  2696.         else if ( (t = p -> n_cltype) == NULL) {
  2697.             printf("pe_sizeof: internal: no type");
  2698.             size = 0;
  2699.         }
  2700.         else {
  2701.             size = t -> t_tsize;
  2702.             if (size == 0) {
  2703.                 t_error("sizeof returns zero");
  2704.             }
  2705.         }
  2706.     }
  2707.     need(RPAREN_TOK);
  2708.     RETURN_ULONG("pe_sizeof", size);
  2709. }
  2710.