home *** CD-ROM | disk | FTP | other *** search
/ Dream 48 / Amiga_Dream_48.iso / Atari / c / cpp.zoo / src / if_expr.c < prev    next >
C/C++ Source or Header  |  1993-06-03  |  7KB  |  449 lines

  1.  
  2. #include <stdlib.h>
  3. #include <setjmp.h>
  4. #include <ctype.h>
  5. #include "global.h"
  6. #include "ztype.h"
  7.  
  8. typedef struct {
  9.   long l;
  10.   char uns;
  11. } Long;
  12.  
  13. static jmp_buf punt;
  14.  
  15. static char char_const(s)
  16.   char *s;
  17. {
  18.   char val = 0;
  19.  
  20.   for (; *s != '\''; s++)
  21.     switch (*s) {
  22.     case '\\':
  23.       switch (*++s) {
  24.       case 'n':
  25.     val = '\n';
  26.     break;
  27.       case 't':
  28.     val = '\t';
  29.     break;
  30.       case 'v':
  31.     val = '\v';
  32.     break;
  33.       case 'b':
  34.     val = '\b';
  35.     break;
  36.       case 'r':
  37.     val = '\r';
  38.     break;
  39.       case 'f':
  40.     val = '\f';
  41.     break;
  42.       case 'a':
  43.     val = '\a';
  44.     break;
  45.       case '0':
  46.       case '1':
  47.       case '2':
  48.       case '3':
  49.       case '4':
  50.       case '5':
  51.       case '6':
  52.       case '7':
  53.     val = (*s++) - '0';
  54.     if (is_octal(*s))
  55.       val = val << 3 + ((*s++) - '0');
  56.     if (is_octal(*s))
  57.       val = val << 3 + ((*s++) - '0');
  58.     break;
  59.       case 'x':
  60.     val = 0;
  61.     while (isxdigit(*s))
  62.       val = val << 4 + (
  63.                  isdigit(*s) ? (*s++ - '0') :
  64.                  islower(*s) ? (*s++ - 'a') :
  65.                  (*s++ - 'A')
  66.           );
  67.     break;
  68.       default:
  69.     val = *s;
  70.       }
  71.       break;
  72.     default:
  73.       val = *s;
  74.     }
  75.   return val;
  76. }
  77.  
  78. static char match(tok)
  79.   int tok;
  80. {
  81.   TokenP T = exp_token();
  82.   char c = T->subtype;
  83.  
  84.   if (T->type == tok) {
  85.     free_token(T);
  86.     return c;
  87.   }
  88.   if (tok == UNARY_OP && T->type == ADD_OP) {
  89.     free_token(T);
  90.     return c;
  91.   }
  92.   push_tlist(T);
  93.   return '\0';
  94. }
  95.  
  96. static void fmatch(tok)
  97.   int tok;
  98. {
  99.   if (!match(tok))
  100.     longjmp(punt, 1);
  101. }
  102.  
  103. static Long l_or_expr __PROTO((void));
  104.  
  105. static Long primary_expr()
  106. {
  107.   Long L /* ={0L,'\0'} */ ;
  108.   TokenP T;
  109.  
  110.   L.l = 0;
  111.   L.uns = '\0';
  112.   T = exp_token();
  113.   switch (T->type) {
  114.   case ID:
  115.     free_token(T);
  116.     return L;
  117.   case NUMBER:
  118.     L.l = T->val;
  119.     L.uns == !!(T->flags & UNS_VAL);
  120.     free_token(T);
  121.     return L;
  122.   case CHAR_CON:
  123.     L.l = char_const(T->txt + 1);
  124.     free_token(T);
  125.     return L;
  126.   case LPAREN:
  127.     L = l_or_expr();
  128.     fmatch(RPAREN);
  129.     free_token(T);
  130.     return L;
  131.   default:
  132.     free_token(T);
  133.     longjmp(punt, 1);
  134.   }
  135. }
  136.  
  137. static Long unary_expr()
  138. {
  139.   Long L;
  140.   char op;
  141.  
  142.   if (!(op = match(UNARY_OP)))
  143.     return primary_expr();
  144.   switch (op) {
  145.   case '!':
  146.     L = unary_expr();
  147.     L.uns = 0;
  148.     L.l = !L.l;
  149.     return L;
  150.   case '~':
  151.     L = unary_expr();
  152.     L.l = ~L.l;
  153.     return L;
  154.   case '+':
  155.     return unary_expr();
  156.   case '-':
  157.     L = unary_expr();
  158.     L.l = -L.l;
  159.     return L;
  160.   default:
  161.     bugchk("'%c' is UNARY_OP in #if expr", op);
  162.     longjmp(punt, 2);
  163.   }
  164. }
  165.  
  166. static Long mul_expr()
  167. {
  168.   Long L1, L;
  169.   char op;
  170.  
  171.   L1 = unary_expr();
  172.   while (op = match(MUL_OP)) {
  173.     L = unary_expr();
  174.     if (L.uns)
  175.       L1.uns = 1;
  176.     switch (op) {
  177.     case '*':
  178.       L1.l *= L.l;
  179.       break;
  180.     case '%':
  181.       L1.l %= L.l;
  182.       break;
  183.     case '/':
  184.       if (L.l == 0) {
  185.     error("divide by zero in #if expr");
  186.     longjmp(punt, 2);
  187.       }
  188.       L1.l /= L.l;
  189.       break;
  190.     default:
  191.       bugchk("'%c' is MUL_OP in #if expr", op);
  192.       longjmp(punt, 2);
  193.     }
  194.   }
  195.   return L1;
  196. }
  197.  
  198. static Long add_expr()
  199. {
  200.   Long L1, L;
  201.   char op;
  202.  
  203.   L1 = mul_expr();
  204.   while (op = match(ADD_OP)) {
  205.     L = mul_expr();
  206.     if (L.uns)
  207.       L1.uns = 1;
  208.     switch (op) {
  209.     case '+':
  210.       L1.l += L.l;
  211.       break;
  212.     case '-':
  213.       L1.l -= L.l;
  214.       break;
  215.     default:
  216.       bugchk("'%c' is ADD_OP in #if expr", op);
  217.       longjmp(punt, 2);
  218.     }
  219.   }
  220.   return L1;
  221. }
  222.  
  223. static Long shift_expr()
  224. {
  225.   Long L1, L;
  226.   char op;
  227.  
  228.   L1 = add_expr();
  229.   while (op = match(SHIFT_OP)) {
  230.     L = add_expr();
  231.     if (L.uns)
  232.       L1.uns = 1;
  233.     switch (op) {
  234.     case '<':
  235.       L1.l <<= L.l;
  236.       break;
  237.     case '>':
  238.       L1.l >>= L.l;
  239.       break;
  240.     default:
  241.       bugchk("'%c' is SHIFT_OP in #if expr", op);
  242.       longjmp(punt, 2);
  243.     }
  244.   }
  245.   return L1;
  246. }
  247.  
  248. #define compare(L1,op,L2) \
  249.  ((L1.uns || L2.uns) ? (unsigned long)L1.l op (unsigned long)L2.l : \
  250.              L1.l op L2.l)
  251.  
  252. static Long rel_expr()
  253. {
  254.   Long L1, L;
  255.   char op;
  256.  
  257.   L1 = shift_expr();
  258.   while (op = match(REL_OP)) {
  259.     L = shift_expr();
  260.     switch (op) {
  261.     case '<':
  262.       L1.l = compare(L1, <, L);
  263.       L1.uns = 0;
  264.       break;
  265.     case '>':
  266.       L1.l = compare(L1, >, L);
  267.       L1.uns = 0;
  268.       break;
  269.     case '(':
  270.       L1.l = compare(L1, <=, L);
  271.       L1.uns = 0;
  272.       break;
  273.     case ')':
  274.       L1.l = compare(L1, >=, L);
  275.       L1.uns = 0;
  276.       break;
  277.     default:
  278.       bugchk("'%c' is REL_OP in #if expr", op);
  279.       longjmp(punt, 2);
  280.     }
  281.   }
  282.   return L1;
  283. }
  284.  
  285. static Long eq_expr()
  286. {
  287.   Long L1, L;
  288.   char op;
  289.  
  290.   L1 = rel_expr();
  291.   while (op = match(EQ_OP)) {
  292.     L = rel_expr();
  293.     switch (op) {
  294.     case '=':
  295.       L1.l = compare(L1, ==, L);
  296.       L1.uns = 0;
  297.       break;
  298.     case '!':
  299.       L1.l = compare(L1, !=, L);
  300.       L1.uns = 0;
  301.       break;
  302.     default:
  303.       bugchk("'%c' is EQ_OP in #if expr", op);
  304.       longjmp(punt, 2);
  305.     }
  306.   }
  307.   return L1;
  308. }
  309.  
  310. static Long b_and_expr()
  311. {
  312.   Long L1, L;
  313.   char op;
  314.  
  315.   L1 = eq_expr();
  316.   while (op = match(B_AND_OP)) {
  317.     L = eq_expr();
  318.     if (L.uns)
  319.       L1.uns = 1;
  320.     switch (op) {
  321.     case '&':
  322.       L1.l &= L.l;
  323.       break;
  324.     default:
  325.       bugchk("'%c' is B_AND_OP in #if expr", op);
  326.       longjmp(punt, 2);
  327.     }
  328.   }
  329.   return L1;
  330. }
  331.  
  332. static Long b_xor_expr()
  333. {
  334.   Long L1, L;
  335.   char op;
  336.  
  337.   L1 = b_and_expr();
  338.   while (op = match(B_XOR_OP)) {
  339.     L = b_and_expr();
  340.     if (L.uns)
  341.       L1.uns = 1;
  342.     switch (op) {
  343.     case '^':
  344.       L1.l ^= L.l;
  345.       break;
  346.     default:
  347.       bugchk("'%c' is B_XOR_OP in #if expr", op);
  348.       longjmp(punt, 2);
  349.     }
  350.   }
  351.   return L1;
  352. }
  353.  
  354. static Long b_or_expr()
  355. {
  356.   Long L1, L;
  357.   char op;
  358.  
  359.   L1 = b_xor_expr();
  360.   while (op = match(B_OR_OP)) {
  361.     L = b_xor_expr();
  362.     if (L.uns)
  363.       L1.uns = 1;
  364.     switch (op) {
  365.     case '|':
  366.       L1.l |= L.l;
  367.       break;
  368.     default:
  369.       bugchk("'%c' is B_OR_OP in #if expr", op);
  370.       longjmp(punt, 2);
  371.     }
  372.   }
  373.   return L1;
  374. }
  375.  
  376. static Long l_and_expr()
  377. {
  378.   Long L1, L;
  379.   char op;
  380.  
  381.   L1 = b_or_expr();
  382.   while (op = match(L_AND_OP)) {
  383.     L = b_or_expr();
  384.     switch (op) {
  385.     case '&':
  386.       L1.l = L1.l && L.l;
  387.       L1.uns = 0;
  388.       break;
  389.     default:
  390.       bugchk("'%c' is L_AND_OP in #if expr", op);
  391.       longjmp(punt, 2);
  392.     }
  393.   }
  394.   return L1;
  395. }
  396.  
  397. static Long l_or_expr()
  398. {
  399.   Long L1, L;
  400.   char op;
  401.  
  402.   L1 = l_and_expr();
  403.   while (op = match(L_OR_OP)) {
  404.     L = l_and_expr();
  405.     switch (op) {
  406.     case '|':
  407.       L1.l = L1.l || L.l;
  408.       L1.uns = 0;
  409.       break;
  410.     default:
  411.       bugchk("'%c' is L_OR_OP in #if expr", op);
  412.       longjmp(punt, 2);
  413.     }
  414.   }
  415.   return L1;
  416. }
  417.  
  418. static Long expr()
  419. {
  420.   Long L;
  421.  
  422.   L = l_or_expr();
  423.   if (!match(EOL))
  424.     longjmp(punt, 1);
  425.   return L;
  426. }
  427.  
  428. int if_expr()
  429. {
  430.   Long L;
  431.   int r;
  432.  
  433.   change_mode(IF_EXPR, 0);
  434.   _tokenize_line();
  435.   switch (setjmp(punt)) {
  436.   case 0:
  437.     L = expr();
  438.     r = !!L.l;
  439.     break;
  440.   case 1:
  441.     error("syntax error in #if expr");
  442.     /* and fall through */
  443.   default:
  444.     r = 0;
  445.   }
  446.   change_mode(0, IF_EXPR);
  447.   return r;
  448. }
  449.