home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / c / condor40.zip / CONDOR / src / util_lib / expr.c < prev    next >
C/C++ Source or Header  |  1989-05-15  |  28KB  |  1,599 lines

  1. /* 
  2. ** Copyright 1986, 1987, 1988, 1989 University of Wisconsin
  3. ** 
  4. ** Permission to use, copy, modify, and distribute this software and its
  5. ** documentation for any purpose and without fee is hereby granted,
  6. ** provided that the above copyright notice appear in all copies and that
  7. ** both that copyright notice and this permission notice appear in
  8. ** supporting documentation, and that the name of the University of
  9. ** Wisconsin not be used in advertising or publicity pertaining to
  10. ** distribution of the software without specific, written prior
  11. ** permission.  The University of Wisconsin makes no representations about
  12. ** the suitability of this software for any purpose.  It is provided "as
  13. ** is" without express or implied warranty.
  14. ** 
  15. ** THE UNIVERSITY OF WISCONSIN DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. ** THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. ** FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN  BE LIABLE FOR
  18. ** ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. ** WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ** ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  21. ** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22. ** 
  23. ** Authors:  Allan Bricker and Michael J. Litzkow,
  24. **              University of Wisconsin, Computer Sciences Dept.
  25. ** 
  26. */ 
  27.  
  28.  
  29. #include <stdio.h>
  30. #include <ctype.h>
  31. #include <varargs.h>
  32. #include "except.h"
  33. #include "debug.h"
  34. #include "expr.h"
  35. #include "clib.h"
  36.  
  37. static char *_FileName_ = __FILE__;        /* Used by EXCEPT (see except.h)     */
  38.  
  39. #define SCAN_ERROR  \
  40.     _LineNo = __LINE__; \
  41.     _FileName = __FILE__; \
  42.     scan_error
  43.     
  44.  
  45. #define EVALUATION_ERROR  \
  46.     _LineNo = __LINE__; \
  47.     _FileName = __FILE__; \
  48.     evaluation_error
  49.     
  50.  
  51. #define ALPHA(ch) (isalpha(ch)||ch=='_')
  52. #define WHITE(ch) (isspace(ch))
  53. #define QUOTE(ch) (ch=='"')
  54. #define DIGIT(ch) (isdigit(ch))
  55. #define PUNCT(ch) (ch=='<'||ch=='='||ch=='>'||ch=='('||ch==')'||ch=='|'||ch=='&'||ch=='!'||ch=='+'||ch=='-'||ch=='*'||ch=='/')
  56. #define MATCH 0
  57. #define MAX_RECURSION    50
  58.  
  59. extern FILE    *DebugFP;
  60.  
  61. int        Terse;
  62. int        Silent;
  63. int        _LineNo;
  64. char    *_FileName;
  65. int        HadError;
  66. int        Depth;
  67.  
  68. char    *In, *Line;
  69.  
  70. char    *strdup(), *malloc(), *op_name();
  71. ELEM    *get_number(), *get_int(), *get_float(), *get_string(), *get_name(),
  72.         *get_punct(), *pop(), *elem_dup(), *integer_compare(),
  73.         *float_compare(), *string_compare(), *eval(), *integer_arithmetic(),
  74.         *float_arithmetic(), *unstack_elem(), *create_elem();
  75. EXPR    *create_expr(), *scan(), *search_expr();
  76.  
  77. EXPR *
  78. scan( line )
  79. char    *line;
  80. {
  81.     ELEM    *elem, *tmp, *get_elem();
  82.     STACK    operand_stack, *op_stack = &operand_stack;
  83.     EXPR    *expr;
  84.  
  85.     HadError = 0;
  86.  
  87.     expr = create_expr();
  88.     init_stack( op_stack );
  89.     In = Line = line;
  90.  
  91.     for(;;) {
  92.  
  93.         if( HadError ) {
  94.             return NULL;
  95.         }
  96.  
  97.         elem = get_elem();
  98.  
  99.         if( HadError ) {
  100.             free_elem( elem );
  101.             return NULL;
  102.         }
  103.  
  104.         if( elem->type == ERROR ) {
  105.             return NULL;
  106.         }
  107.  
  108.         switch( elem->type ) {
  109.             case ENDMARKER:
  110.                 for( tmp = pop(op_stack); tmp; tmp = pop(op_stack) ) {
  111.                     add_elem( tmp, expr );
  112.                 }
  113.                 add_elem( elem, expr );
  114.                 return expr;
  115.  
  116.             case FLOAT:
  117.             case INT:
  118.             case STRING:
  119.             case BOOL:
  120.             case NAME:
  121.                 add_elem( elem, expr );
  122.                 break;
  123.  
  124.             case RPAREN:
  125.                 free_elem( elem );
  126.                 for(;;) {
  127.                     tmp = pop( op_stack );
  128.                     if( tmp == NULL ) { 
  129.                         break;
  130.                     }
  131.                     if( tmp->type == LPAREN ) {
  132.                         free_elem( tmp );
  133.                         break;
  134.                     }
  135.                     add_elem( tmp, expr );
  136.                 }
  137.                 break;
  138.             default:
  139.                 for(tmp=pop(op_stack); tmp; tmp = pop(op_stack) ) {
  140.                     if( expr_prio(tmp,IN_STACK) >= expr_prio(elem,IN_COMING) ) {
  141.                         add_elem( tmp, expr );
  142.                     } else {
  143.                         break;
  144.                     }
  145.                 }
  146.                 if( tmp ) {
  147.                     push( tmp, op_stack );
  148.                 }
  149.                 push( elem, op_stack );
  150.                 break;
  151.         }
  152.     }
  153. }
  154.         
  155.  
  156. /*
  157. ** Create and initialize an empty expression, and return a pointer to it.
  158. */
  159. EXPR *
  160. create_expr()
  161. {
  162.     EXPR    *answer;
  163.  
  164.     answer = (EXPR *)malloc( sizeof(EXPR) );
  165.     answer->len = 0;
  166.     answer->max_len = EXPR_INCR;
  167.     answer->data = (ELEM **)malloc(
  168.                     (unsigned)(answer->max_len * sizeof(ELEM *)) );
  169.     return answer;
  170. }
  171.  
  172. /*
  173. ** Add an element to an expression.
  174. */
  175. add_elem( elem, expr )
  176. ELEM    *elem;
  177. EXPR    *expr;
  178. {
  179.     if( expr->len == expr->max_len ) {
  180.         expr->max_len += EXPR_INCR;
  181.         expr->data =
  182.             (ELEM **)realloc( (char *)expr->data,
  183.             (unsigned)(expr->max_len * sizeof(ELEM *)) );
  184.     }
  185.     expr->data[expr->len++] = elem;
  186. }
  187.  
  188. /*
  189. ** Free an expression including all the elements in it.
  190. */
  191. free_expr( expr )
  192. EXPR    *expr;
  193. {
  194.     int        i;
  195.  
  196.     for( i=0; i<expr->len; i++ ) {
  197.         free_elem( expr->data[i] );
  198.     }
  199.     free( (char *)expr->data );
  200.     free( (char *)expr );
  201. }
  202.  
  203. init_stack( stack )
  204. STACK    *stack;
  205. {
  206.     stack->top = -1;
  207. }
  208.  
  209. push( elem, stack )
  210. ELEM    *elem;
  211. STACK    *stack;
  212. {
  213.     stack->data[ ++stack->top ] = elem;
  214. }
  215.  
  216. ELEM *
  217. pop( stack )
  218. STACK    *stack;
  219. {
  220.     if( stack->top < 0 ) {
  221.         return NULL;
  222.     }
  223.     return stack->data[ stack->top-- ];
  224. }
  225.  
  226. empty_stack( stack )
  227. STACK    *stack;
  228. {
  229.     return stack->top == -1;
  230. }
  231.  
  232. ELEM    *
  233. get_elem()
  234. {
  235.     ELEM    *answer;
  236.  
  237.     answer = create_elem();
  238.  
  239.     while( WHITE(*In) ) {
  240.         In++;
  241.     }
  242.  
  243.     if( !*In ) {
  244.         answer->type = ENDMARKER;
  245.         return answer;
  246.     }
  247.  
  248.     if( DIGIT(*In) || *In == '-' || *In == '.' ) {
  249.         return get_number( answer );
  250.     }
  251.         
  252.     if( QUOTE(*In) ) {
  253.         return get_string( answer );
  254.     }
  255.  
  256.     if( ALPHA(*In) ) {
  257.         return get_name( answer );
  258.     }
  259.  
  260.     if( PUNCT(*In) ) {
  261.         return get_punct( answer );
  262.     }
  263.  
  264.     SCAN_ERROR( "Unrecognized character" );
  265.     return answer;
  266. }
  267.  
  268. ELEM    *
  269. get_punct( elem )
  270. ELEM    *elem;
  271. {
  272.  
  273.     if( *In == '(' ) {
  274.         elem->type = LPAREN;
  275.         In++;
  276.         return elem;
  277.     }
  278.  
  279.     if( *In == ')' ) {
  280.         elem->type = RPAREN;
  281.         In++;
  282.         return elem;
  283.     }
  284.  
  285.     if( *In == '+' ) {
  286.         elem->type = PLUS;
  287.         In++;
  288.         return elem;
  289.     }
  290.  
  291.     if( *In == '-' ) {
  292.         elem->type = MINUS;
  293.         In++;
  294.         return elem;
  295.     }
  296.  
  297.     if( *In == '*' ) {
  298.         elem->type = MUL;
  299.         In++;
  300.         return elem;
  301.     }
  302.  
  303.     if( *In == '/' ) {
  304.         elem->type = DIV;
  305.         In++;
  306.         return elem;
  307.     }
  308.  
  309.     if( *In == '<' ) {
  310.         In++;
  311.         if( *In && *In == '=' ) {
  312.             In++;
  313.             elem->type = LE;
  314.         } else {
  315.             elem->type = LT;
  316.         }
  317.         return elem;
  318.     }
  319.  
  320.     if( *In == '>' ) {
  321.         In++;
  322.         if( *In && *In == '=' ) {
  323.             In++;
  324.             elem->type = GE;
  325.         } else {
  326.             elem->type = GT;
  327.         }
  328.         return elem;
  329.     }
  330.  
  331.     if( *In == '=' ) {
  332.         In++;
  333.         if( *In && *In == '=' ) {
  334.             In++;
  335.             elem->type = EQ;
  336.         } else {
  337.             elem->type = GETS;
  338.         }
  339.         return elem;
  340.     }
  341.  
  342.     if( *In == '!' ) {
  343.         In++;
  344.         if( *In && *In == '=' ) {
  345.             In++;
  346.             elem->type = NE;
  347.         } else {
  348.             elem->type = NOT;
  349.         }
  350.         return elem;
  351.     }
  352.  
  353.     if( *In == '|' ) {
  354.         In++;
  355.         if( *In && *In == '|' ) {
  356.             elem->type = OR;
  357.         } else {
  358.             SCAN_ERROR( "Unrecognized punctuation" );
  359.             return NULL;
  360.         }
  361.         In++;
  362.         return elem;
  363.     }
  364.  
  365.     if( *In == '&' ) {
  366.         In++;
  367.         if( *In && *In == '&' ) {
  368.             elem->type = AND;
  369.         } else {
  370.             SCAN_ERROR( "Unrecognized punctuation" );
  371.             return NULL;
  372.         }
  373.         In++;
  374.         return elem;
  375.     }
  376.     SCAN_ERROR( "Unrecognized punctuation" );
  377.     return NULL;
  378. }
  379.  
  380. ELEM *
  381. get_number( elem )
  382. ELEM    *elem;
  383. {
  384.     char    *ptr;
  385.     char    next = *(In + 1);
  386.  
  387.     if( *In == '-' && !DIGIT(next) && next != '.' ) {
  388.         return get_punct( elem );        /* Binary MINUS */
  389.     }
  390.  
  391.     for( ptr=In; *ptr; ptr++ ) {
  392.         if( *ptr == '.' ) {
  393.             return get_float( elem );
  394.         }
  395.         if( *ptr != '-' && !DIGIT(*ptr) ) {
  396.             return get_int( elem );
  397.         }
  398.     }
  399.     return get_int( elem );
  400. }
  401.  
  402. ELEM    *
  403. get_float( elem )
  404. ELEM    *elem;
  405. {
  406.     char    *ptr;
  407.     char    tmp;
  408.     double    atof();
  409.  
  410.     ptr = In;
  411.     if( *ptr == '-' )
  412.         ptr++;
  413.     for( ; DIGIT(*ptr) || *ptr == '.'; ptr++)
  414.         ;
  415.     tmp = *ptr;
  416.     *ptr = '\0';
  417.     elem->type = FLOAT;
  418.     elem->f_val = (float)atof(In);
  419.     *ptr = tmp;
  420.     In = ptr;
  421.     return elem;
  422. }
  423.  
  424. ELEM    *
  425. get_int( elem )
  426. ELEM    *elem;
  427. {
  428.     char    *ptr;
  429.     char    tmp;
  430.  
  431.     ptr = In;
  432.     if( *ptr == '-' )
  433.         ptr++;
  434.     for( ; DIGIT(*ptr); ptr++)
  435.         ;
  436.     tmp = *ptr;
  437.     *ptr = '\0';
  438.     elem->type = INT;
  439.     elem->i_val = atoi( In );
  440.     *ptr = tmp;
  441.     In = ptr;
  442.     return elem;
  443. }
  444.  
  445.  
  446. ELEM    *
  447. get_string( elem )
  448. ELEM    *elem;
  449. {
  450.     char    *ptr;
  451.  
  452.     In++;
  453.     for( ptr=In; *ptr && *ptr != '"'; ptr++ )
  454.         ;
  455.  
  456.     if( *ptr != '"' ) {
  457.         SCAN_ERROR( "Quote not closed" );
  458.         return elem;
  459.     }
  460.  
  461.     *ptr = '\0';
  462.     elem->type = STRING;
  463.     elem->s_val = strdup( In );
  464.     In = ptr + 1;
  465.     *ptr = '"';
  466.     return elem;
  467. }
  468.  
  469.  
  470. ELEM    *
  471. get_name( elem )
  472. ELEM    *elem;
  473. {
  474.     char    *ptr, tmp;
  475.  
  476.     for( ptr=In; ALPHA(*ptr); ptr++ )
  477.         ;
  478.     tmp = *ptr;
  479.     *ptr = '\0';
  480.     elem->type = NAME;
  481.     elem->s_val = strdup( In );
  482.     *ptr = tmp;
  483.     In = ptr;
  484.  
  485.     if( strcmp(elem->s_val,"T") == MATCH ) {
  486.         free( elem->s_val );
  487.         elem->type = BOOL;
  488.         elem->b_val = 1;
  489.     } else if( strcmp(elem->s_val,"F") == MATCH ) {
  490.         free( elem->s_val );
  491.         elem->type = BOOL;
  492.         elem->b_val = 0;
  493.     }
  494.     return elem;
  495. }
  496.  
  497. display_elem( elem, log_fp )
  498. ELEM    *elem;
  499. FILE    *log_fp;
  500. {
  501.     if( Terse ) {
  502.         display_elem_short( elem, log_fp );
  503.     } else {
  504.         display_elem_long( elem );
  505.     }
  506. }
  507.  
  508. display_elem_long( elem )
  509. ELEM    *elem;
  510. {
  511.     int        type = elem->type;
  512.     char    *op = op_name( type );
  513.  
  514.     switch( type ) {
  515.         case LT:
  516.         case LE:
  517.         case EQ:
  518.         case GT:
  519.         case GE:
  520.         case NE:
  521.         case AND:
  522.         case OR:
  523.         case NOT:
  524.         case PLUS:
  525.         case MINUS:
  526.         case MUL:
  527.         case DIV:
  528.         case GETS:
  529.         case LPAREN:
  530.         case ENDMARKER:
  531.         case ERROR:
  532.             dprintf( D_EXPR, "TYPE: %s\n", op );
  533.             break;
  534.         case NAME:
  535.             dprintf( D_EXPR, "TYPE: %s    VALUE: \"%s\"\n", op, elem->s_val);
  536.             break;
  537.         case STRING:
  538.             dprintf( D_EXPR, "TYPE: %s    VALUE: \"%s\"\n", op, elem->s_val);
  539.             break;
  540.         case FLOAT:
  541.             dprintf( D_EXPR, "TYPE: %s    VALUE: %f\n", op, elem->f_val );
  542.             break;
  543.         case INT:
  544.             dprintf( D_EXPR, "TYPE: %s    VALUE: %d\n", op, elem->i_val );
  545.             break;
  546.         case BOOL:
  547.             dprintf( D_EXPR, "TYPE: %s    VALUE: %s\n", op,
  548.                                             elem->b_val ? "TRUE" : "FALSE" );
  549.             break;
  550.         default:
  551.             EXCEPT( "Found element of unknown type (%d)", type );
  552.             break;
  553.     }
  554. }
  555.  
  556. display_elem_short( elem, log_fp )
  557. ELEM    *elem;
  558. FILE    *log_fp;
  559. {
  560.     int        type = elem->type;
  561.  
  562.     switch( type ) {
  563.         case LT:
  564.             (void)fputc( '<', log_fp );
  565.             break;
  566.         case LE:
  567.             (void)fputc( '<', log_fp );
  568.             (void)fputc( '=', log_fp );
  569.             break;
  570.         case EQ:
  571.             (void)fputc( '=', log_fp );
  572.             (void)fputc( '=', log_fp );
  573.             break;
  574.         case GT:
  575.             (void)fputc( '>', log_fp );
  576.             break;
  577.         case GE:
  578.             (void)fputc( '>', log_fp );
  579.             (void)fputc( '=', log_fp );
  580.             break;
  581.         case NE:
  582.             (void)fputc( '!', log_fp );
  583.             (void)fputc( '=', log_fp );
  584.             break;
  585.         case AND:
  586.             (void)fputc( '&', log_fp );
  587.             (void)fputc( '&', log_fp );
  588.             break;
  589.         case OR:
  590.             (void)fputc( '|', log_fp );
  591.             (void)fputc( '|', log_fp );
  592.             break;
  593.         case NOT:
  594.             (void)fputc( '!', log_fp );
  595.             break;
  596.         case PLUS:
  597.             (void)fputc( '+', log_fp );
  598.             break;
  599.         case MINUS:
  600.             (void)fputc( '-', log_fp );
  601.             break;
  602.         case MUL:
  603.             (void)fputc( '*', log_fp );
  604.             break;
  605.         case DIV:
  606.             (void)fputc( '/', log_fp );
  607.             break;
  608.         case GETS:
  609.             (void)fputc( '=', log_fp );
  610.             break;
  611.         case LPAREN:
  612.             (void)fputc( '(', log_fp );
  613.             break;
  614.         case RPAREN:
  615.             (void)fputc( ')', log_fp );
  616.             break;
  617.         case ENDMARKER:
  618.             (void)fputc( ';', log_fp );
  619.             break;
  620.         case ERROR:
  621.             fprintf( log_fp, "(ERROR)" );
  622.             break;
  623.         case NAME:
  624.             fprintf( log_fp,  "%s", elem->s_val );
  625.             break;
  626.         case STRING:
  627.             fprintf( log_fp,  "%s", elem->s_val );
  628.             break;
  629.         case FLOAT:
  630.             fprintf( log_fp,  "%f", elem->f_val );
  631.             break;
  632.         case INT:
  633.             fprintf( log_fp,  "%d", elem->i_val );
  634.             break;
  635.         case BOOL:
  636.             fprintf( log_fp,  "%c", elem->b_val ? 'T' : 'F' );
  637.             break;
  638.         default:
  639.             debug_unlock();
  640.             EXCEPT( "Found element of unknown type (%d)", type );
  641.             break;
  642.     }
  643. }
  644.  
  645.  
  646. struct prio {
  647.     int        type;
  648.     int        isp;
  649.     int        icp;
  650. } PrioTab[] = {
  651.     GETS,    1,    1,
  652.     LT,        5,    5,
  653.     LE,        5,    5,
  654.     EQ,        4,    4,
  655.     GE,        5,    5,
  656.     GT,        5,    5,
  657.     NE,        4,    4,
  658.     AND,    3,    3,
  659.     OR,        2,    2,
  660.     PLUS,    6,    6,
  661.     MINUS,    6,    6,
  662.     DIV,    7,    7,
  663.     MUL,    7,    7,
  664.     NOT,    8,    8,
  665.     LPAREN,    0,    9,
  666.     ENDMARKER,    0,    0,
  667. };
  668.  
  669. expr_prio( elem, which )
  670. ELEM    *elem;
  671. int        which;
  672. {
  673.     struct prio    *p;
  674.  
  675.     for( p=PrioTab; p->type != ENDMARKER; p++ ) {
  676.         if( p->type == elem->type ) {
  677.             if( which == IN_STACK ) {
  678.                 return p->isp;
  679.             } else {
  680.                 return p->icp;
  681.             }
  682.         }
  683.     }
  684.     EXCEPT( "Can't find priority for elem type %d\n", elem->type );
  685.     /* NOTREACHED */
  686. }
  687.  
  688. display_expr( expr )
  689. EXPR    *expr;
  690. {
  691.     int        i;
  692.     FILE    *log_fp, *debug_lock();
  693.  
  694.     if( Terse ) {
  695.         log_fp = debug_lock();
  696.         for( i=0; i<expr->len; i++ ) {
  697.             display_elem( expr->data[i], log_fp );
  698.             if( i+1 < expr->len ) {
  699.                 (void)fputc( ' ', log_fp );
  700.             }
  701.         }
  702.         (void)fputc( '\n', log_fp );
  703.         debug_unlock();
  704.     } else {
  705.         dprintf( D_EXPR, "\nPostfix Expression\n" );
  706.         for( i=0; i<expr->len; i++ ) {
  707.             display_elem( expr->data[i], (FILE *) NULL );
  708.         }
  709.     }
  710. }
  711.  
  712. ELEM    *
  713. eval( name, cont1, cont2 )
  714. char    *name;
  715. CONTEXT    *cont1;
  716. CONTEXT    *cont2;
  717. {
  718.     STACK    op_stack, *operand_stack = &op_stack;
  719.     ELEM    *elem, *tmp, *result;
  720.     int        i;
  721.     EXPR    *expr;
  722.  
  723.         /* Built in function */
  724.     if( strcmp("CurrentTime",name) == MATCH ) {
  725.         result = create_elem();
  726.         result->type = INT;
  727.         result->i_val = time( (time_t *)0 );
  728.         return result;
  729.     }
  730.  
  731.     expr = search_expr( name, cont1, cont2 );
  732.     if( !expr ) {
  733.         EVALUATION_ERROR( "Can't find variable \"%s\"", name );
  734.         return NULL;
  735.     }
  736.  
  737.     HadError = 0;
  738.     init_stack( operand_stack );
  739.  
  740.     for( i=1; i<expr->len; i++ ) {
  741.  
  742.         if( HadError ) {
  743.             return NULL;
  744.         }
  745.  
  746.         elem = elem_dup( expr->data[i] );
  747.         switch( elem->type ) {
  748.             case NAME:
  749.  
  750.                 if( Depth++ > MAX_RECURSION ) {
  751.                     EVALUATION_ERROR(
  752.                         "Expression too complicated -- possible loop" );
  753.                     tmp = NULL;
  754.                 } else {
  755.                     tmp = eval( elem->s_val, cont1, cont2 );
  756.                 }
  757.                 Depth--;
  758.  
  759.                 free_elem( elem );
  760.                 if( !tmp ) {
  761.                     return NULL;
  762.                 }
  763.                 push( tmp, operand_stack );
  764.                 break;
  765.             case STRING:
  766.             case FLOAT:
  767.             case INT:
  768.             case BOOL:
  769.                 push( elem, operand_stack );
  770.                 break;
  771.             case LT:
  772.             case LE:
  773.             case GT:
  774.             case GE:
  775.             case NE:
  776.             case EQ:
  777.             case AND:
  778.             case OR:
  779.             case NOT:
  780.             case PLUS:
  781.             case MINUS:
  782.             case MUL:
  783.             case DIV:
  784.                 do_op( elem, operand_stack );
  785.                 free_elem( elem );
  786.                 break;
  787.             case GETS:    /* Ignore for now */
  788.                 free_elem( elem );
  789.                 break;
  790.             case ENDMARKER:
  791.                 free_elem( elem );
  792.                 result = pop( operand_stack );
  793.  
  794.                 if( !result || !empty_stack(operand_stack) ) {
  795.                     EVALUATION_ERROR(
  796.                                 "Number of operands doesn't match operators");
  797.                     return NULL;
  798.                 }
  799.                 return result;
  800.             default:
  801.                 EXCEPT( "Found elem type %d in postfix expr\n", elem->type );
  802.                 break;
  803.         }
  804.     }
  805.     EXCEPT( "Internal evaluation error" );
  806.     /* NOTREACHED */
  807. }
  808.  
  809. do_op( elem, stack )
  810. ELEM    *elem;
  811. STACK    *stack;
  812. {
  813.     switch( elem->type ) {
  814.             case LT:
  815.             case LE:
  816.             case GT:
  817.             case GE:
  818.             case EQ:
  819.             case NE:
  820.                 do_comparison_op( elem->type, stack );
  821.                 break;
  822.             case AND:
  823.             case OR:
  824.             case NOT:
  825.                 do_logical_op( elem->type, stack );
  826.                 break;
  827.             case PLUS:
  828.             case MINUS:
  829.             case MUL:
  830.             case DIV:
  831.                 do_arithmetic_op( elem->type, stack );
  832.                 break;
  833.             default:
  834.                 EXCEPT( "Unexpected element type (%d)", elem->type );
  835.         }
  836. }
  837.  
  838. do_logical_op( op, stack )
  839. int        op;
  840. STACK    *stack;
  841. {
  842.     ELEM    *elem_1, *elem_2;
  843.     ELEM    *answer;
  844.  
  845.     answer = create_elem();
  846.     answer->type = BOOL;
  847.  
  848.         /* Get and check right operand */
  849.     elem_2 = unstack_elem( op, stack );
  850.     if( !elem_2 ) {
  851.         free_elem( answer );
  852.         return;
  853.     }
  854.     if( elem_2->type != BOOL ) {
  855.         EVALUATION_ERROR( "boolean value expected" );
  856.         free_elem( elem_2 );
  857.         free_elem( answer );
  858.         return;
  859.     }
  860.  
  861.         /* NOT only takes one operand, so do it here */
  862.     if( op == NOT ) {
  863.         answer->b_val = !elem_2->b_val;
  864.         push( answer, stack );
  865.         free_elem( elem_2 );
  866.         return;
  867.     }
  868.  
  869.         /* Get and check left operand */
  870.     elem_1 = unstack_elem( op, stack );
  871.     if( !elem_1 ) {
  872.         free_elem( elem_2 );
  873.         free_elem( answer );
  874.         return;
  875.     }
  876.     if( elem_1->type != BOOL ) {
  877.         EVALUATION_ERROR( "boolean value expected" );
  878.         free_elem( elem_2 );
  879.         free_elem( elem_1 );
  880.         free_elem( answer );
  881.         return;
  882.     }
  883.  
  884.     switch( op ) {
  885.         case AND:
  886.             answer->b_val = elem_1->b_val && elem_2->b_val;
  887.             break;
  888.         case OR:
  889.             answer->b_val = elem_1->b_val || elem_2->b_val;
  890.             break;
  891.         default:
  892.             SCAN_ERROR( "unexpected operator" );
  893.             return;
  894.     }
  895.     push( answer, stack );
  896.     free_elem( elem_1 );
  897.     free_elem( elem_2 );
  898. }
  899.  
  900. do_comparison_op( op, stack )
  901. int        op;
  902. STACK    *stack;
  903. {
  904.     ELEM    *elem_1, *elem_2;
  905.  
  906.         /* Get and check right operand */
  907.     elem_2 = unstack_elem( op, stack );
  908.     if( !elem_2 ) {
  909.         return;
  910.     }
  911.  
  912.         /* Get and check left operand */
  913.     elem_1 = unstack_elem( op, stack );
  914.     if( !elem_1 ) {
  915.         free_elem( elem_2 );
  916.         return;
  917.     }
  918.  
  919.     if( elem_1->type == INT && elem_2->type == INT ) {
  920.         push( integer_compare(op,elem_1->i_val,elem_2->i_val), stack );
  921.     } else if( elem_1->type == FLOAT && elem_2->type == INT ) {
  922.         push( float_compare(op,elem_1->f_val,(float)elem_2->i_val), stack );
  923.     } else if( elem_1->type == INT && elem_2->type == FLOAT ) {
  924.         push( float_compare(op,(float)elem_1->i_val,elem_2->f_val), stack );
  925.     } else if( elem_1->type == FLOAT && elem_2->type == FLOAT) {
  926.         push( float_compare(op,elem_1->f_val,elem_2->f_val), stack );
  927.     } else if( elem_1->type == STRING && elem_2->type == STRING ) {
  928.         push( string_compare(op,elem_1->s_val,elem_2->s_val), stack );
  929.     } else {
  930.         EVALUATION_ERROR( "Comparison of incompatible types %d and %d",
  931.                                             elem_1->type, elem_2->type );
  932.     }
  933.     free_elem( elem_1 );
  934.     free_elem( elem_2 );
  935. }
  936.  
  937. ELEM    *
  938. integer_compare( op, v1, v2 )
  939. int        op;
  940. int        v1;
  941. int        v2;
  942. {
  943.     ELEM    *answer;
  944.  
  945.     answer = create_elem();
  946.     answer->type = BOOL;
  947.  
  948.     switch( op ) {
  949.         case LT:
  950.             answer->b_val = v1 < v2;
  951.             break;
  952.         case LE:
  953.             answer->b_val = v1 <= v2;
  954.             break;
  955.         case EQ:
  956.             answer->b_val = v1 == v2;
  957.             break;
  958.         case GE:
  959.             answer->b_val = v1 >= v2;
  960.             break;
  961.         case GT:
  962.             answer->b_val = v1 > v2;
  963.             break;
  964.         case NE:
  965.             answer->b_val = v1 != v2;
  966.             break;
  967.         default:
  968.             EXCEPT( "Unexpecteded operator %d\n", op );
  969.     }
  970.     return answer;
  971. }
  972.  
  973. ELEM    *
  974. float_compare( op, f1, f2 )
  975. int        op;
  976. float    f1;
  977. float    f2;
  978. {
  979.     ELEM    *answer;
  980.  
  981.     answer = create_elem();
  982.     answer->type = BOOL;
  983.  
  984.     switch( op ) {
  985.         case LT:
  986.             answer->b_val = f1 < f2;
  987.             break;
  988.         case LE:
  989.             answer->b_val = f1 <= f2;
  990.             break;
  991.         case EQ:
  992.             answer->b_val = f1 == f2;
  993.             break;
  994.         case GE:
  995.             answer->b_val = f1 >= f2;
  996.             break;
  997.         case GT:
  998.             answer->b_val = f1 > f2;
  999.             break;
  1000.         case NE:
  1001.             answer->b_val = f1 != f2;
  1002.             break;
  1003.         default:
  1004.             EXCEPT( "Unexpecteded operator %d\n", op );
  1005.     }
  1006.     return answer;
  1007. }
  1008.  
  1009. ELEM    *
  1010. string_compare( op, s1, s2 )
  1011. int        op;
  1012. char    *s1;
  1013. char    *s2;
  1014. {
  1015.     ELEM    *answer;
  1016.  
  1017.     answer = create_elem();
  1018.     answer->type = BOOL;
  1019.  
  1020.     switch( op ) {
  1021.         case LT:
  1022.             answer->b_val = strcmp(s1,s2) < 0;
  1023.             break;
  1024.         case LE:
  1025.             answer->b_val = strcmp(s1,s2) <= 0;
  1026.             break;
  1027.         case EQ:
  1028.             answer->b_val = strcmp(s1,s2) == 0;
  1029.             break;
  1030.         case GE:
  1031.             answer->b_val = strcmp(s1,s2) >= 0;
  1032.             break;
  1033.         case GT:
  1034.             answer->b_val = strcmp(s1,s2) > 0;
  1035.             break;
  1036.         case NE:
  1037.             answer->b_val = strcmp(s1,s2) != 0;
  1038.             break;
  1039.         default:
  1040.             EXCEPT( "Unexpecteded operator %d\n", op );
  1041.     }
  1042.     return answer;
  1043. }
  1044.  
  1045. ELEM    *
  1046. elem_dup( elem )
  1047. ELEM    *elem;
  1048. {
  1049.     ELEM    *answer;
  1050.  
  1051.     answer = create_elem();
  1052.  
  1053.     switch( elem->type ) {
  1054.         case NAME:
  1055.         case STRING:
  1056.             answer->type = elem->type;
  1057.             answer->s_val = strdup( elem->s_val );
  1058.             break;
  1059.         default:
  1060.             bcopy( (char *)elem, (char *)answer, sizeof(ELEM) );
  1061.             break;
  1062.     }
  1063.     return answer;
  1064. }
  1065.  
  1066. do_arithmetic_op( op, stack )
  1067. int        op;
  1068. STACK    *stack;
  1069. {
  1070.     ELEM    *elem_1, *elem_2;
  1071.  
  1072.     elem_2 = unstack_elem( op, stack );
  1073.     elem_1 = unstack_elem( op, stack );
  1074.  
  1075.         /* Kludge to allow boolean (viewed as 1 or 0),
  1076.         to be added to ints or floats -- grot */
  1077.     if( elem_1->type == BOOL ) {
  1078.         elem_1->type = INT;
  1079.     }
  1080.     if( elem_2->type == BOOL ) {
  1081.         elem_2->type = INT;
  1082.     }
  1083.  
  1084.     if( elem_1->type == INT && elem_2->type == INT ) {
  1085.         push( integer_arithmetic(op,elem_1->i_val,elem_2->i_val), stack );
  1086.     } else if( elem_1->type == FLOAT && elem_2->type == INT ) {
  1087.         push( float_arithmetic(op,elem_1->f_val,(float)elem_2->i_val), stack );
  1088.     } else if( elem_1->type == INT && elem_2->type == FLOAT ) {
  1089.         push( float_arithmetic(op,(float)elem_1->i_val,elem_2->f_val), stack );
  1090.     } else if( elem_1->type == FLOAT && elem_2->type == FLOAT) {
  1091.         push( float_arithmetic(op,elem_1->f_val,elem_2->f_val), stack );
  1092.     } else {
  1093.         EXCEPT( "Arithmetic on operand types %d and %d\n",
  1094.                                             elem_1->type, elem_2->type );
  1095.     }
  1096.     free_elem( elem_1 );
  1097.     free_elem( elem_2 );
  1098. }
  1099.  
  1100. scan_error( str )
  1101. char    *str;
  1102. {
  1103.     int        count;
  1104.     int        i;
  1105.     char    buf[ BUFSIZ ];
  1106.  
  1107.     if( Silent ) {
  1108.         return;
  1109.     }
  1110.  
  1111.     dprintf( D_EXPR, "\n%s", Line );
  1112.     count = In - Line;
  1113.     for( i=0; i<count; i++ ) {
  1114.         buf[i] = ' ';
  1115.     }
  1116.     buf[i++] = '^';
  1117.     buf[i] = '\0';
  1118.     dprintf( D_EXPR, buf );
  1119.     dprintf( D_EXPR, "Syntax error: " );
  1120.     dprintf( D_EXPR | D_NOHEADER, "%s\n", str );
  1121.     dprintf( D_EXPR, "Discovered at line %d in file %s\n",
  1122.                                                     _LineNo, _FileName );
  1123.     HadError++;
  1124. }
  1125.  
  1126. ELEM    *
  1127. integer_arithmetic( op, v1, v2 )
  1128. int        op;
  1129. int        v1;
  1130. int        v2;
  1131. {
  1132.     ELEM    *answer;
  1133.  
  1134.     answer = create_elem();
  1135.     answer->type = INT;
  1136.  
  1137.     switch( op ) {
  1138.         case PLUS:
  1139.             answer->i_val = v1 + v2;
  1140.             break;
  1141.         case MINUS:
  1142.             answer->i_val = v1 - v2;
  1143.             break;
  1144.         case DIV:
  1145.             answer->i_val = v1 / v2;
  1146.             break;
  1147.         case MUL:
  1148.             answer->i_val = v1 * v2;
  1149.             break;
  1150.         default:
  1151.             EXCEPT( "Unexpecteded operator %d\n", op );
  1152.     }
  1153.     return answer;
  1154. }
  1155.  
  1156. ELEM    *
  1157. float_arithmetic( op, v1, v2 )
  1158. int        op;
  1159. float    v1;
  1160. float    v2;
  1161. {
  1162.     ELEM    *answer;
  1163.  
  1164.     answer = create_elem();
  1165.     answer->type = FLOAT;
  1166.  
  1167.     switch( op ) {
  1168.         case PLUS:
  1169.             answer->f_val = v1 + v2;
  1170.             break;
  1171.         case MINUS:
  1172.             answer->f_val = v1 - v2;
  1173.             break;
  1174.         case DIV:
  1175.             answer->f_val = v1 / v2;
  1176.             break;
  1177.         case MUL:
  1178.             answer->f_val = v1 * v2;
  1179.             break;
  1180.         default:
  1181.             EXCEPT( "Unexpecteded operator %d\n", op );
  1182.     }
  1183.     return answer;
  1184. }
  1185.  
  1186. struct {
  1187.     int        op;
  1188.     char    *name;
  1189. } OpName[] = {
  1190.     LT,            "LT",
  1191.     LE,            "LE",
  1192.     EQ,            "EQ",
  1193.     GT,            "GT",
  1194.     GE,            "GE",
  1195.     NE,            "NE",
  1196.     AND,        "AND",
  1197.     OR,            "OR",
  1198.     NOT,        "NOT",
  1199.     PLUS,        "PLUS",
  1200.     MINUS,        "MINUS",
  1201.     MUL,        "MUL",
  1202.     DIV,        "DIV",
  1203.     GETS,        "GETS",
  1204.     LPAREN,        "LPAREN",
  1205.     RPAREN,        "RPAREN",
  1206.     NAME,        "NAME",
  1207.     STRING,        "STRING",
  1208.     FLOAT,        "FLOAT",
  1209.     INT,        "INT",
  1210.     BOOL,        "BOOL",
  1211.     ERROR,        "ERROR",
  1212.     ENDMARKER,    "ENDMARKER",
  1213.     0,            0,
  1214. };
  1215.  
  1216. char *
  1217. op_name( op )
  1218. int        op;
  1219. {
  1220.     int        i;
  1221.  
  1222.     for( i=0; OpName[i].op; i++ ) {
  1223.         if( OpName[i].op == op ) {
  1224.             return OpName[i].name;
  1225.         }
  1226.     }
  1227.     EXCEPT( "Can't find op name for elem type (%d)\n", op );
  1228.     /* NOTREACHED */
  1229. }
  1230.  
  1231.  
  1232. free_elem( elem )
  1233. ELEM    *elem;
  1234. {
  1235.     if( elem->type == STRING || elem->type == NAME ) {
  1236.         free( elem->s_val );
  1237.     }
  1238.     free( (char *)elem );
  1239. }
  1240.  
  1241. /*
  1242. ** Take an element off the stack, and if it's a name, look up its value.
  1243. */
  1244. ELEM *
  1245. unstack_elem( op, stack )
  1246. int        op;
  1247. STACK    *stack;
  1248. {
  1249.     ELEM    *answer;
  1250.  
  1251.     answer = pop( stack );
  1252.  
  1253.     if( !answer ) {
  1254.         EVALUATION_ERROR( "Missing operand for %s", op_name(op) );
  1255.         return NULL;
  1256.     }
  1257.  
  1258.     return answer;
  1259. }
  1260.  
  1261.  
  1262. ELEM    *
  1263. create_elem()
  1264. {
  1265.     ELEM    *answer;
  1266.  
  1267.     answer = (ELEM *)malloc( sizeof(ELEM) );
  1268.     answer->type = ERROR;
  1269.     answer->i_val = 0;
  1270.     return answer;
  1271. }
  1272.  
  1273. store_stmt( expr, context )
  1274. EXPR    *expr;
  1275. CONTEXT    *context;
  1276. {
  1277.     int        i;
  1278.     char    *name;
  1279.  
  1280.     if( expr->data[0]->type != NAME ) {
  1281.         EXCEPT( "First element in statement not a NAME" );
  1282.     }
  1283.     name = expr->data[0]->s_val;
  1284.  
  1285.     for( i=0; i<context->len; i++ ) {
  1286.         if( strcmp(name,context->data[i]->data[0]->s_val) == MATCH ) {
  1287.             free_expr( context->data[i] );
  1288.             context->data[i] = expr;
  1289.             return;
  1290.         }
  1291.     }
  1292.     add_stmt( expr, context );
  1293. }
  1294.  
  1295. CONTEXT *
  1296. create_context()
  1297. {
  1298.     CONTEXT    *answer;
  1299.  
  1300.     answer = (CONTEXT *)malloc( sizeof(CONTEXT) );
  1301.     answer->len = 0;
  1302.     answer->max_len = EXPR_INCR;
  1303.     answer->data = (EXPR **)malloc(
  1304.                             (unsigned)(answer->max_len * sizeof(EXPR *)) );
  1305.     return answer;
  1306. }
  1307.  
  1308. free_context( context )
  1309. CONTEXT    *context;
  1310. {
  1311.     int        i;
  1312.  
  1313.     for( i=0; i<context->len; i++ ) {
  1314.         free_expr( context->data[i] );
  1315.     }
  1316.     free( (char *)context->data );
  1317.     free( (char *)context );
  1318. }
  1319.  
  1320. add_stmt( expr, context )
  1321. EXPR    *expr;
  1322. CONTEXT    *context;
  1323. {
  1324.     if( context->len == context->max_len ) {
  1325.         context->max_len += EXPR_INCR;
  1326.         context->data = (EXPR **)realloc( (char *)context->data,
  1327.                             (unsigned)(context->max_len * sizeof(EXPR *)) );
  1328.     }
  1329.     context->data[context->len++] = expr;
  1330. }
  1331.  
  1332. display_context( context )
  1333. CONTEXT    *context;
  1334. {
  1335.     int        i;
  1336.  
  1337.     for( i=0; i<context->len; i++ ) {
  1338.         dprintf( D_EXPR, "Stmt %2d:", i );
  1339.         if( !Terse ) {
  1340.             dprintf( D_EXPR, "\n" );
  1341.         }
  1342.         display_expr( context->data[i] );
  1343.     }
  1344. }
  1345.  
  1346. EXPR *
  1347. search_expr( name, cont1, cont2 )
  1348. char    *name;
  1349. CONTEXT    *cont1;
  1350. CONTEXT    *cont2;
  1351. {
  1352.     int        i;
  1353.  
  1354.     if( cont1 ) {
  1355.         for( i=0; i<cont1->len; i++ ) {
  1356.             if( strcmp(name,cont1->data[i]->data[0]->s_val) == MATCH ) {
  1357.                 return cont1->data[i];
  1358.             }
  1359.         }
  1360.     }
  1361.  
  1362.     if( cont2 ) {
  1363.         for( i=0; i<cont2->len; i++ ) {
  1364.             if( strcmp(name,cont2->data[i]->data[0]->s_val) == MATCH ) {
  1365.                 return cont2->data[i];
  1366.             }
  1367.         }
  1368.     }
  1369.     return NULL;
  1370. }
  1371.  
  1372. EXPR    *
  1373. build_expr( name, val )
  1374. char    *name;
  1375. ELEM    *val;
  1376. {
  1377.     EXPR    *answer;
  1378.     ELEM    *elem;
  1379.  
  1380.     answer = create_expr();
  1381.  
  1382.     elem = create_elem();
  1383.     elem->type = NAME;
  1384.     elem->s_val = strdup( name );
  1385.     add_elem( elem, answer );
  1386.  
  1387.     add_elem( elem_dup(val), answer );
  1388.  
  1389.     elem = create_elem();
  1390.     elem->type = GETS;
  1391.     add_elem( elem, answer );
  1392.  
  1393.     elem = create_elem();
  1394.     elem->type = ENDMARKER;
  1395.     add_elem( elem, answer );
  1396.  
  1397.     return answer;
  1398. }
  1399.  
  1400. evaluate_bool( name, answer, context1, context2 )
  1401. char    *name;
  1402. int        *answer;
  1403. CONTEXT    *context1;
  1404. CONTEXT    *context2;
  1405. {
  1406.     ELEM    *elem;
  1407.  
  1408.     elem = eval( name, context1, context2 );
  1409.  
  1410.     if( !elem ) {
  1411.         if( !Silent ) {
  1412.             dprintf( D_EXPR, "Expression \"%s\" can't evaluate\n", name );
  1413.         }
  1414.         return -1;
  1415.     }
  1416.  
  1417.     if( elem->type != BOOL ) {
  1418.         free_elem( elem );
  1419.         dprintf( D_EXPR,
  1420.             "Expression \"%s\" expected type boolean, but was %s",
  1421.                                             name, op_name(elem->type) );
  1422.         return -1;
  1423.     }
  1424.     *answer = elem->b_val;
  1425.     free_elem( elem );
  1426.     dprintf( D_EXPR, "evaluate_bool(\"%s\") returns %s\n",
  1427.                                         name, *answer ? "TRUE" : "FALSE" );
  1428.     return 0;
  1429. }
  1430.  
  1431. evaluate_float( name, answer, context1, context2 )
  1432. char    *name;
  1433. float    *answer;
  1434. CONTEXT    *context1;
  1435. CONTEXT    *context2;
  1436. {
  1437.     ELEM    *elem;
  1438.  
  1439.     elem = eval( name, context1, context2 );
  1440.  
  1441.     if( !elem ) {
  1442.         if( !Silent ) {
  1443.             dprintf( D_EXPR, "Expression \"%s\" can't evaluate\n", name );
  1444.         }
  1445.         return -1;
  1446.     }
  1447.  
  1448.     if( elem->type != INT && elem->type != FLOAT ) {
  1449.         free_elem( elem );
  1450.         dprintf( D_EXPR,
  1451.             "Expression \"%s\" expected type float, but was %s",
  1452.                                             name, op_name(elem->type) );
  1453.         return -1;
  1454.     }
  1455.     if( elem->type == FLOAT ) {
  1456.         *answer = elem->f_val;
  1457.     } else {
  1458.         *answer = (float)elem->i_val;
  1459.     }
  1460.     free_elem( elem );
  1461.     dprintf( D_EXPR, "evaluate_float(\"%s\") returns %f\n",
  1462.                                         name, *answer );
  1463.     return 0;
  1464. }
  1465.  
  1466. evaluate_int( name, answer, context1, context2 )
  1467. char    *name;
  1468. int        *answer;
  1469. CONTEXT    *context1;
  1470. CONTEXT    *context2;
  1471. {
  1472.     ELEM    *elem;
  1473.  
  1474.     elem = eval( name, context1, context2 );
  1475.  
  1476.     if( !elem ) {
  1477.         if( !Silent ) {
  1478.             dprintf( D_EXPR, "Expression \"%s\" can't evaluate\n", name );
  1479.         }
  1480.         return -1;
  1481.     }
  1482.  
  1483.     if( elem->type != INT ) {
  1484.         free_elem( elem );
  1485.         dprintf( D_EXPR,
  1486.             "Expression \"%s\" expected type int, but was %s",
  1487.                                             name, op_name(elem->type) );
  1488.         return -1;
  1489.     }
  1490.     *answer = elem->i_val;
  1491.     free_elem( elem );
  1492.     dprintf( D_EXPR, "evaluate_int(\"%s\") returns %d\n",
  1493.                                         name, *answer );
  1494.     return 0;
  1495. }
  1496.  
  1497. evaluate_string( name, answer, context1, context2 )
  1498. char    *name;
  1499. char    **answer;
  1500. CONTEXT    *context1;
  1501. CONTEXT    *context2;
  1502. {
  1503.     ELEM    *elem;
  1504.  
  1505.     elem = eval( name, context1, context2 );
  1506.  
  1507.     if( !elem ) {
  1508.         if( !Silent ) {
  1509.             dprintf( D_EXPR, "Expression \"%s\" can't evaluate\n", name );
  1510.         }
  1511.         return -1;
  1512.     }
  1513.  
  1514.     if( elem->type != STRING ) {
  1515.         free_elem( elem );
  1516.         dprintf( D_EXPR,
  1517.             "Expression \"%s\" expected type string, but was %s",
  1518.                                             name, op_name(elem->type) );
  1519.         return -1;
  1520.     }
  1521.     *answer = strdup( elem->s_val );
  1522.     free_elem( elem );
  1523.     dprintf( D_EXPR, "evaluate_string(\"%s\") returns \"%s\"\n",
  1524.                                         name, *answer );
  1525.     return 0;
  1526. }
  1527.  
  1528. #ifdef LINT
  1529. /* VARARGS */
  1530. evaluation_error(foo)
  1531. char    *foo;
  1532. { printf( foo ); }
  1533. #else LINT
  1534. /* VARARGS */
  1535. evaluation_error(va_alist)
  1536. va_dcl
  1537. {
  1538.     va_list pvar;
  1539.     char *fmt;
  1540.     char    buf[ BUFSIZ ];
  1541.  
  1542.     if( Silent ) {
  1543.         return;
  1544.     }
  1545.  
  1546.     va_start(pvar);
  1547.  
  1548.     fmt = va_arg(pvar, char *);
  1549.  
  1550.  
  1551. #if vax || i386 || bobcat || ibm032
  1552.     {
  1553.         FILE _strbuf;
  1554.         int *argaddr = &va_arg(pvar, int);
  1555.  
  1556.         _strbuf._flag = _IOWRT+_IOSTRG;
  1557.         _strbuf._ptr  = buf;
  1558.         _strbuf._cnt  = BUFSIZ;
  1559.         _doprnt( fmt, argaddr, &_strbuf );
  1560.         putc('\0', &_strbuf);
  1561.     }
  1562. #else vax || i386 || bobcat || ibm032
  1563.     vsprintf( buf, fmt, pvar );
  1564. #endif vax || i386 || bobcat || ibm032
  1565.  
  1566.     dprintf( D_EXPR, "Evaluation error: %s\n", buf );
  1567.     HadError++;
  1568. }
  1569. #endif LINT
  1570.  
  1571. #ifdef notdef
  1572. read_exprs( name, context )
  1573. char    *name;
  1574. CONTEXT    *context;
  1575. {
  1576.     FILE    *fp;
  1577.     char    line[1024];
  1578.     EXPR    *expr, *scan();
  1579.  
  1580.     if( (fp=fopen(name,"r")) == NULL ) {
  1581.         EXCEPT( "fopen(\"%s\",\"r\")", name );
  1582.     }
  1583.  
  1584.     while( fgets(line,sizeof(line),fp) ) {
  1585.         if( blankline(line) ) {
  1586.             continue;
  1587.         }
  1588.         
  1589.         if( (expr=scan(line)) == NULL ) {
  1590.             EXCEPT( "Syntax Error in \"%s\"", name );
  1591.         }
  1592.  
  1593.         store_stmt( expr, context );
  1594.  
  1595.     }
  1596.     (void)fclose( fp );
  1597. }
  1598. #endif notdef
  1599.