home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / t / toaster.zip / Compat / lex.c < prev    next >
C/C++ Source or Header  |  1991-12-31  |  34KB  |  1,689 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <string.h>
  4.  
  5. #include "instrs.h"
  6. #include "lint.h"
  7. #include "lang.h"
  8. #include "string.h"
  9. #include "config.h"
  10. #include "interpret.h"
  11. #include "exec.h"
  12. #include "lex.h"
  13.  
  14. #if defined(__GNUC__) && !defined(lint)
  15. #define INLINE inline
  16. #else
  17. #define INLINE
  18. #endif
  19.  
  20. #define NELEM(a) (sizeof (a) / sizeof (a)[0])
  21. #define isalunum(c) (isalnum(c) || (c) == '_')
  22.  
  23. int current_line;
  24. int total_lines;    /* Used to compute average compiled lines/s */
  25. char *current_file;
  26. int pragma_strict_types;    /* Force usage of strict types. */
  27. int pragma_save_types;        /* Save argument types after compilation */
  28. struct lpc_predef_s *lpc_predefs=NULL;
  29. extern char *argument_name;
  30. extern char *xalloc();
  31. static int number PROT((int)), ident PROT((char *)), string PROT((char *));
  32. static int islocal PROT((char *));
  33. static void handle_define PROT((char *));
  34. static void free_defines PROT((void)), add_define PROT((char *, int, char *));
  35. static int expand_define PROT((void));
  36. static void add_input PROT((char *));
  37. static void myungetc PROT((int));
  38. static int lookup_resword PROT((char *));
  39. static int cond_get_exp PROT((int));
  40. static int exgetc();
  41. static FILE *yyin;
  42. static int lex_fatal;
  43. static char **inc_list;
  44. static int inc_list_size;
  45.  
  46. #define EXPANDMAX 25000
  47. static int nexpands;
  48.  
  49. extern char *local_names[];
  50. extern int current_number_of_locals;
  51.  
  52. extern char *string_copy();
  53.  
  54. #ifndef tolower
  55. extern int tolower PROT((int));
  56. #endif
  57.  
  58. void yyerror(), error(), free();
  59.  
  60. #define MAXLINE 1024
  61. static char yytext[MAXLINE];
  62. static int slast, lastchar;
  63.  
  64. struct defn {
  65.     struct defn *next;
  66.     char *name;
  67.     int undef;
  68.     char *exps;
  69.     int nargs;
  70. };
  71. struct defn *lookup_define();
  72.  
  73. static struct ifstate {
  74.     struct ifstate *next;
  75.     int state;
  76. } *iftop = 0;
  77. #define EXPECT_ELSE 1
  78. #define EXPECT_ENDIF 2
  79.  
  80. static struct incstate {
  81.     FILE *yyin;
  82.     char *file;
  83.     struct incstate *next;
  84.     int line, slast, lastchar;
  85.     char pragma_strict_types;
  86. } *inctop = 0;
  87.  
  88. #define DEFMAX 10000
  89. static char defbuf[DEFMAX];
  90. static int nbuf;
  91. static char *outp;
  92.  
  93. void merge(name, dest)
  94.     char *name, *dest;
  95. {
  96.     char *from;
  97.  
  98.     strcpy(dest, current_file);
  99.     if (from = strrchr(dest, '/'))   /* strip filename */
  100.     *from = 0;
  101.     else
  102.     /* current_file was the file_name */
  103.     /* include from the root directory */
  104.     *dest = 0;
  105.  
  106.     from = name;
  107.     while (*from == '/') {
  108.     from++;
  109.     *dest=0;    /* absolute path */
  110.     }
  111.  
  112.     while(*from) {
  113.     if(!strncmp(from, "../", 3)) {
  114.         char *tmp;
  115.         
  116.         if(*dest == 0) /* including from above mudlib is NOT allowed */
  117.         break;
  118.         tmp = strrchr(dest, '/');
  119.         if(tmp == NULL) /* 1 component in dest */
  120.         *dest = 0;
  121.         else
  122.         *tmp = 0;
  123.         from +=3;   /* skip "../" */
  124.     }
  125.     else if(!strncmp(from, "./", 2)) {
  126.         from += 2;
  127.     }
  128.     else { /* append first component to dest */
  129.         char *q;
  130.         
  131.         if(*dest)
  132.         strcat(dest, "/");    /* only if dest is not empty !! */
  133.         q = strchr(from, '/');
  134.         
  135.         if(q) { /* from has 2 or more components */
  136.         while(*from=='/') /* find the start */
  137.             from++;
  138.         strncat(dest, from, q - from);
  139.         for(from = q+1;*from=='/';from++)
  140.             ;
  141.         }
  142.         else {
  143.         /* this was the last component */
  144.         strcat(dest, from);
  145.         break;
  146.         }
  147.     }
  148.     }
  149. }
  150.  
  151. static INLINE int
  152. mygetc()
  153. {
  154.     int c;
  155.  
  156.     if (nbuf) {
  157.     nbuf--;
  158.     c = *outp++;
  159.     } else {
  160.     c = getc(yyin);
  161.     }
  162.     lastchar = slast;
  163.     slast = c;
  164. /*fprintf(stderr, "c='%c'", c);*/
  165.     return c;
  166. }
  167.  
  168. static INLINE int
  169. gobble(c)
  170. int c;
  171. {
  172.     int d;
  173.     d = mygetc();
  174.     if (c == d)
  175.     return 1;
  176.     *--outp = d;
  177.     nbuf++;
  178.     return 0;
  179. }
  180.  
  181. static void
  182. lexerror(s)
  183. char *s;
  184. {
  185.     yyerror(s);
  186.     lex_fatal++;
  187. }
  188.  
  189. static int
  190. skip_to(token, atoken)
  191. char *token, *atoken;
  192. {
  193.     char b[20], *p;
  194.     int c;
  195.     int nest;
  196.  
  197.     for(nest = 0;;) {
  198.     c = mygetc();
  199.     if (c == '#') {
  200.         do {
  201.         c = mygetc();
  202.         } while(isspace(c));
  203.         for(p = b; c != '\n' && c != EOF; ) {
  204.         if (p < b+sizeof b-1)
  205.             *p++ = c;
  206.         c = mygetc();
  207.         }
  208.         *p++ = 0;
  209.         for(p = b; *p && !isspace(*p); p++)
  210.         ;
  211.         *p = 0;
  212. /*fprintf(stderr, "skip checks %s\n", b);*/
  213.         if (strcmp(b, "if") == 0 || strcmp(b, "ifdef") == 0 ||
  214.         strcmp(b, "ifndef") == 0) {
  215.         nest++;
  216.         } else if (nest > 0) {
  217.         if (strcmp(b, "endif") == 0)
  218.             nest--;
  219.         } else {
  220.         if (strcmp(b, token) == 0)
  221.             return 1;
  222.         else if (atoken && strcmp(b, atoken) == 0)
  223.             return 0;
  224.         }
  225.     } else {
  226. /*fprintf(stderr, "skipping (%d) %c", c, c);*/
  227.             while (c != '\n' && c != EOF) {
  228.         c = mygetc();
  229. /*fprintf(stderr, "%c", c);*/
  230.         } 
  231.         if (c == EOF) {
  232.         lexerror("Unexpected end of file while skipping");
  233.         return 1;
  234.         }
  235.     }
  236.     if (inctop == 0)
  237.         store_line_number_info();
  238.     current_line++;
  239.     total_lines++;
  240.     }
  241. }
  242.  
  243. static void
  244. handle_cond(c)
  245. int c;
  246. {
  247.     struct ifstate *p;
  248.  
  249. /*fprintf(stderr, "cond %d\n", c);*/
  250.     if (c || skip_to("else", "endif")) {
  251.     p = (struct ifstate *)xalloc(sizeof(struct ifstate));
  252.     p->next = iftop;
  253.     iftop = p;
  254.     p->state = c ? EXPECT_ELSE : EXPECT_ENDIF;
  255.     }
  256.     if (!c) {
  257.     if (inctop == 0)
  258.         store_line_number_info();
  259.     current_line++;
  260.     total_lines++;
  261.     }
  262. }
  263.  
  264. static FILE *
  265. inc_open(buf, name)
  266. char *buf, *name;
  267. {
  268.     FILE *f;
  269.     int i;
  270.     char *p;
  271.  
  272.     merge(name, buf);
  273.     if ((f = fopen(buf, "r")) != NULL)
  274.     return f;
  275.     for (i=0; i<inc_list_size; ++i)
  276.     {
  277.        sprintf(buf, "%s/%s", inc_list[i], name);
  278.        if ((f = fopen(buf, "r")) != NULL) 
  279.           return f;
  280.     }
  281.     return NULL;
  282. }
  283.  
  284. static void
  285. handle_include(name)
  286. char *name;
  287. {
  288.     char *p;
  289.     char buf[1024];
  290.     FILE *f;
  291.     struct incstate *is;
  292.     int delim;
  293.  
  294. /*fprintf(stderr, "handle include '%s'\n", name);*/
  295.     if (nbuf) {
  296.     lexerror("Internal preprocessor error");
  297.     return;
  298.     }
  299.     if (*name != '"' && *name != '<') {
  300.     struct defn *d;
  301.     if ((d = lookup_define(name)) && d->nargs == -1) {
  302.         char *q;
  303.         q = d->exps;
  304.         while(isspace(*q))
  305.         q++;
  306.         handle_include(q);
  307.     } else {
  308.         yyerror("Missing leading \" or < in #include");
  309.     }
  310.     return;
  311.     }
  312.     delim = *name++ == '"' ? '"' : '>';
  313.     for(p = name; *p && *p != delim; p++)
  314.     ;
  315.     if (!*p) {
  316.     yyerror("Missing trailing \" or > in #include");
  317.     return;
  318.     }
  319.     if (strlen(name) > sizeof(buf) - 100) {
  320.     yyerror("Include name too long.");
  321.     return;
  322.     }
  323.     *p = 0;
  324.     if ((f = inc_open(buf, name)) != NULL) {
  325.     is = (struct incstate *)xalloc(sizeof(struct incstate));
  326.     is->yyin = yyin;
  327.     is->line = current_line;
  328.     is->file = current_file;
  329.     is->slast = slast;
  330.     is->lastchar = lastchar;
  331.     is->next = inctop;
  332.         is->pragma_strict_types= pragma_strict_types;
  333.         pragma_strict_types = 0;
  334.     inctop = is;
  335.     current_line = 1;
  336.     current_file = xalloc(strlen(buf)+1);
  337.     strcpy(current_file, buf);
  338.     slast = lastchar = '\n';
  339.     yyin = f;
  340. /*fprintf(stderr, "pushed to %s\n", buf);*/
  341.     } else {
  342.     sprintf(buf, "Cannot #include %s\n", name);
  343.     yyerror(buf);
  344.     }
  345. }
  346.  
  347. static void
  348. skip_comment()
  349. {
  350.     int c;
  351.  
  352.     for(;;) {
  353.     while((c = mygetc()) != '*') {
  354.         if (c == EOF) {
  355.             lexerror("End of file in a comment");
  356.         return;
  357.         }
  358.         if (c == '\n') {
  359.         if (inctop == 0)
  360.             store_line_number_info();
  361.         nexpands=0;
  362.         current_line++;
  363.         }
  364.     }
  365.     do {
  366.         if ((c = mygetc()) == '/')
  367.         return;
  368.         if (c == '\n') {
  369.         if (inctop == 0)
  370.             store_line_number_info();
  371.         nexpands=0;
  372.         current_line++;
  373.         }
  374.     } while(c == '*');
  375.     }
  376. }
  377.  
  378. #define TRY(c, t) if (gobble(c)) return t
  379.  
  380. static void
  381. deltrail(sp)
  382. char *sp;
  383. {
  384.     char *p;
  385.     p = sp;
  386.     if (!*p) {
  387.     lexerror("Illegal # command");
  388.     } else {
  389.     while(*p && !isspace(*p))
  390.         p++;
  391.     *p = 0;
  392.     }
  393. }
  394.  
  395. #define SAVEC \
  396.     if (yyp < yytext+MAXLINE-5)\
  397.        *yyp++ = c;\
  398.     else {\
  399.        lexerror("Line too long");\
  400.        break;\
  401.     }
  402.  
  403. static void handle_pragma(str)
  404.     char *str;
  405. {
  406.     if (strcmp(str, "strict_types") == 0) {
  407.     pragma_strict_types = 1;
  408.     } else if (strcmp(str, "save_types") == 0) {
  409.     pragma_save_types = 1;
  410.     }
  411. }
  412.  
  413. static int
  414. yylex1()
  415. {
  416.   register char *yyp;
  417.   register int c;
  418.  
  419.   for(;;) {
  420.     if (lex_fatal) {
  421.     return -1;
  422.     }
  423.     switch(c = mygetc()) {
  424.     case EOF:
  425.     if (inctop) {
  426.         struct incstate *p;
  427.         p = inctop;
  428.         fclose(yyin);
  429. /*fprintf(stderr, "popping to %s\n", p->file);*/
  430.         free(current_file);
  431.         nexpands=0;
  432.         current_file = p->file;
  433.         current_line = p->line + 1;
  434.         pragma_strict_types = p->pragma_strict_types;
  435.         yyin = p->yyin;
  436.         slast = p->slast;
  437.         lastchar = p->lastchar;
  438.         inctop = p->next;
  439.         if (inctop == 0)
  440.         store_line_number_info();
  441.         free((char *)p);
  442.         break;
  443.     }
  444.     if (iftop) {
  445.         struct ifstate *p = iftop;
  446.         yyerror(p->state == EXPECT_ENDIF ? "Missing #endif" : "Missing #else");
  447.         while(iftop) {
  448.         p = iftop;
  449.         iftop = p->next;
  450.         free((char *)p);
  451.         }
  452.     }
  453.     return -1;
  454.     case '\n':
  455.     {
  456.         if (inctop == 0)
  457.         store_line_number_info();
  458.         nexpands=0;
  459.         current_line++;
  460.         total_lines++;
  461.     }
  462.     case ' ':
  463.     case '\t':
  464.     case '\f':
  465.     case '\v':
  466.     break;
  467.     case '+':
  468.     TRY('+', F_INC);
  469.     TRY('=', F_ADD_EQ);
  470.     return c;
  471.     case '-':
  472.     TRY('>', F_ARROW);
  473.     TRY('-', F_DEC);
  474.     TRY('=', F_SUB_EQ);
  475.     return c;
  476.     case '&':
  477.     TRY('&', F_LAND);
  478.     TRY('=', F_AND_EQ);
  479.     return c;
  480.     case '|':
  481.     TRY('|', F_LOR);
  482.     TRY('=', F_OR_EQ);
  483.     return c;
  484.     case '^':
  485.     TRY('=', F_XOR_EQ);
  486.     return c;
  487.     case '<':
  488.     if (gobble('<')) {
  489.         TRY('=', F_LSH_EQ);
  490.         return F_LSH;
  491.     }
  492.     TRY('=', F_LE);
  493.     return c;
  494.     case '>':
  495.     if (gobble('>')) {
  496.         TRY('=', F_RSH_EQ);
  497.         return F_RSH;
  498.     }
  499.     TRY('=', F_GE);
  500.     return c;
  501.     case '*':
  502.     TRY('=', F_MULT_EQ);
  503.     return c;
  504.     case '%':
  505.     TRY('=', F_MOD_EQ);
  506.     return c;
  507.     case '/':
  508.     if (gobble('*')) {
  509.         skip_comment();
  510.         break;
  511.         }
  512.     TRY('=', F_DIV_EQ);
  513.     return c;
  514.     case '=':
  515.     TRY('=', F_EQ);
  516.     return c;
  517.     case ';':
  518.     case '(':
  519.     case ')':
  520.     case ',':
  521.     case '{':
  522.     case '}':
  523.     case '~':
  524.     case '[':
  525.     case ']':
  526.     case '?':
  527.     return c;
  528.     case '!':
  529.     TRY('=', F_NE);
  530.     return F_NOT;
  531.     case ':':
  532.     TRY(':', F_COLON_COLON);
  533.     return ':';
  534.     case '.':
  535.     TRY('.',F_RANGE);
  536.     goto badlex;
  537.     case '#':
  538.     if (lastchar == '\n') {
  539.         char *sp = 0;
  540.         int quote;
  541.  
  542.         yyp = yytext;
  543.         do {
  544.         c = mygetc();
  545.         } while (isspace(c));
  546.         for(quote = 0;;) {
  547.  
  548.         if (c == '"')
  549.             quote ^= 1;
  550.         while(!quote && c == '/') { /*gc - handle comments cpp-like! 1.6.91 @@@*/
  551.             if(gobble('*')) { 
  552.             skip_comment();
  553.             c=mygetc();
  554.             } else 
  555.             break;
  556.         }
  557.  
  558.         if (!sp && isspace(c))
  559.             sp = yyp;
  560.         if (c == '\n' || c == EOF)
  561.             break;
  562.         SAVEC;
  563.         c = mygetc();
  564.         }
  565.         if (sp) {
  566.         *sp++ = 0;
  567.         while(isspace(*sp))
  568.             sp++;
  569.         } else {
  570.         sp = yyp;
  571.         }
  572.         *yyp = 0;
  573.         if (strcmp("define", yytext) == 0) {
  574.         handle_define(sp);
  575.         } else if (strcmp("if", yytext) == 0) {
  576. #if 0
  577.         short int nega=0; /*@@@ allow #if !VAR gc 1.6.91*/
  578.         if (*sp=='!'){ sp++; nega=1;}
  579.         if (isdigit(*sp)) {
  580.             char *p;
  581.             long l;
  582.             l = strtol(sp, &p, 10);
  583.             while(isspace(*p))
  584.             p++;
  585.             if (*p)
  586.             yyerror("Condition too complex in #if");
  587.             else
  588.             handle_cond(nega?!(int)l:(int)l);
  589.         } else if (isalunum(*sp)) {
  590.             char *p = sp;
  591.             while(isalunum(*p))
  592.             p++;
  593.             if (*p) {
  594.             *p++ = 0;
  595.             while(isspace(*p))
  596.                 p++;
  597.             }
  598.             if (*p)
  599.             yyerror("Condition too complex in #if");
  600.             else {
  601.             struct defn *d;
  602.             d = lookup_define(sp);
  603.             if (d) {
  604.                 handle_cond(nega?!atoi(d->exps):atoi(d->exps));/* a hack! */
  605.             } else {
  606.                 handle_cond(nega?1:0); /* cpp-like gc*/
  607.             }
  608.             }
  609.         } else
  610.             yyerror("Condition too complex in #if");
  611. #else
  612.         int cond;
  613.  
  614.         myungetc(0);
  615.         add_input(sp);
  616.         cond=cond_get_exp(0);
  617.         if (mygetc()) {
  618.             yyerror("Condition too complex in #if");
  619.             while ( mygetc() ) ;
  620.         } else
  621.             handle_cond(cond);
  622. #endif
  623.         } else if (strcmp("ifdef", yytext) == 0) {
  624.         deltrail(sp);
  625.         handle_cond(lookup_define(sp) != 0);
  626.         } else if (strcmp("ifndef", yytext) == 0) {
  627.         deltrail(sp);
  628.         handle_cond(lookup_define(sp) == 0);
  629.         } else if (strcmp("else", yytext) == 0) {
  630.         if (iftop && iftop->state == EXPECT_ELSE) {
  631.             struct ifstate *p = iftop;
  632.  
  633. /*fprintf(stderr, "found else\n");*/
  634.             iftop = p->next;
  635.             free((char *)p);
  636.             skip_to("endif", (char *)0);
  637.             current_line++;
  638.             total_lines++;
  639.         } else {
  640.             yyerror("Unexpected #else");
  641.         }
  642.         } else if (strcmp("endif", yytext) == 0) {
  643.         if (iftop && (iftop->state == EXPECT_ENDIF ||
  644.                   iftop->state == EXPECT_ELSE)) {
  645.             struct ifstate *p = iftop;
  646.  
  647. /*fprintf(stderr, "found endif\n");*/
  648.             iftop = p->next;
  649.             free((char *)p);
  650.         } else {
  651.             yyerror("Unexpected #endif");
  652.         }
  653.         } else if (strcmp("undef", yytext) == 0) {
  654.         struct defn *d;
  655.  
  656.         deltrail(sp);
  657.         if (d = lookup_define(sp))
  658.             d->undef++;
  659.         } else if (strcmp("echo", yytext) == 0) {
  660.         fprintf(stderr, "%s\n", sp);
  661.         } else if (strcmp("include", yytext) == 0) {
  662. /*fprintf(stderr, "including %s\n", sp);        */
  663.                 handle_include(sp);
  664.         } else if (strcmp("pragma", yytext) == 0) {
  665.         handle_pragma(sp);
  666.         } else {
  667.         yyerror("Unrecognised # directive");
  668.         }
  669.         myungetc('\n');
  670.         break;
  671.     } else
  672.         goto badlex;
  673.     case '\'':
  674.     yylval.number = mygetc();
  675.     if (yylval.number == '\\')
  676.         yylval.number = mygetc();
  677.     if (!gobble('\''))
  678.         yyerror("Illegal character constant");
  679.     return F_NUMBER;
  680.     case '"':
  681.     yyp = yytext;
  682.     *yyp++ = c;
  683.     for(;;) {
  684.         c = mygetc();
  685.         if (c == EOF) {
  686.          lexerror("End of file in string");
  687.         return string("\"\"");
  688.         } else if (c == '\n') {
  689.          lexerror("Newline in string");
  690.         return string("\"\"");
  691.         }
  692.         SAVEC;
  693.         if (c == '"')
  694.         break;
  695.         if (c == '\\') {
  696.         c = mygetc();
  697.         if ( c == '\n' ) {
  698.             yyp--;
  699.             if (inctop == 0)
  700.                 store_line_number_info();
  701.             current_line++;
  702.             total_lines++;
  703.         } else if ( c == EOF ) {
  704.             myungetc(c); /* some operating systems give EOF only once */
  705.         } else *yyp++ = c;
  706.         }
  707.     }
  708.     *yyp = 0;
  709.     return string(yytext);
  710.  
  711.     case '0':
  712.     c = mygetc();
  713.     if ( c == 'X' || c == 'x' ) {
  714.         yyp=yytext;
  715.         for(;;) {
  716.         c = mygetc();
  717.         SAVEC;
  718.         if (!isxdigit(c))
  719.             break;
  720.         }
  721.         myungetc(c);
  722.         return number( (int)strtol(yytext,(char**)NULL,0x10) );
  723.     }
  724.     myungetc(c);
  725.     c = '0';
  726.     /* fall through */
  727.              case '1':case '2':case '3':case '4':
  728.     case '5':case '6':case '7':case '8':case '9':
  729.     yyp = yytext;
  730.     *yyp++ = c;
  731.     for(;;) {
  732.         c = mygetc();
  733.         if (!isdigit(c))
  734.         break;
  735.         SAVEC;
  736.     }
  737.     myungetc(c);
  738.     *yyp = 0;
  739.     return number(atoi(yytext));
  740.     default:
  741.     if (isalpha(c) || c == '_') {
  742.         int r;
  743.  
  744.         yyp = yytext;
  745.         *yyp++ = c;
  746.         for(;;) {
  747.         c = mygetc();
  748.         if (!isalunum(c))
  749.             break;
  750.         SAVEC;
  751.         }
  752.         *yyp = 0;
  753.  
  754.         myungetc(c);
  755.         if (!expand_define()) {
  756.         r = lookup_resword(yytext);
  757.         if (r >= 0) {
  758.             return r;
  759.         } else
  760.             return ident(yytext);
  761.         }
  762.         break;
  763.         }
  764.     goto badlex;
  765.     }
  766.   }
  767.  badlex:
  768.   { char buff[100]; sprintf(buff, "Illegal character (hex %02x) '%c'", c, c);
  769.     yyerror(buff); return ' '; }
  770. }
  771.  
  772. int
  773. yylex()
  774. {
  775.     int r;
  776.  
  777.     yytext[0] = 0;
  778.     r = yylex1();
  779. /*    fprintf(stderr, "lex=%d(%s) ", r, yytext);*/
  780.     return r;
  781. }
  782.  
  783. extern YYSTYPE yylval;
  784.  
  785. static int islocal(str)
  786.     char *str;
  787. {
  788.     int i;
  789.  
  790.     for (i=current_number_of_locals-1; i>=0; i--) {
  791.     if (strcmp(local_names[i], str) == 0)
  792.             return i;
  793.     }
  794.     return -1;
  795. }
  796.  
  797. static int ident(str)
  798.     char *str;
  799. {
  800.     int i;
  801.    
  802.     i = islocal(str);
  803.     if (i >= 0) {
  804.         yylval.number = i;
  805.         return F_LOCAL_NAME;
  806.     }
  807.     yylval.string = string_copy(str);
  808.     return F_IDENTIFIER;
  809. }
  810.  
  811. static int string(str)
  812.     char *str;
  813. {
  814.     char *p;
  815.  
  816.     if (!*str) {
  817.     str = "\"\"";
  818.     }
  819.     p = xalloc(strlen(str));
  820.     yylval.string = p;
  821.     for (str++; str[0] && str[1] ; str++, p++) {
  822.     if (str[0] == '\\') {
  823.         if (str[1] == 'n') {
  824.         *p = '\n';
  825.         } else if (str[1] == 't') {
  826.         *p = '\t';
  827.         } else if (str[1] == 'r') {
  828.         *p = '\r';
  829.         } else if (str[1] == 'b') {
  830.         *p = '\b';
  831.         } else
  832.         *p = str[1];
  833.         str++;
  834.     } else
  835.         *p = *str;
  836.     }
  837.     *p = '\0';
  838.     return F_STRING;
  839. }
  840.  
  841. static int number(i)
  842.     int i;
  843. {
  844.     yylval.number = i;
  845.     return F_NUMBER;
  846. }
  847.  
  848. void end_new_file()
  849. {
  850.     while (inctop) {
  851.     struct incstate *p;
  852.     p = inctop;
  853.     fclose(yyin);
  854.     free(current_file);
  855.     current_file = p->file;
  856.     yyin = p->yyin;
  857.     inctop = p->next;
  858.     free((char *)p);
  859.     }
  860.     while(iftop) {
  861.     struct ifstate *p;
  862.  
  863.     p = iftop;
  864.     iftop = p->next;
  865.     free((char *)p);
  866.     }
  867. }
  868.  
  869. void start_new_file(f)
  870.     FILE *f;
  871. {
  872.     struct lpc_predef_s *tmpf; 
  873.     char max_buff[50];
  874.  
  875.     free_defines();
  876.     add_define("LPC3", -1, "");
  877. #ifdef COMPAT_MODE
  878.     add_define("COMPAT_FLAG", -1, "");
  879. #endif
  880.     sprintf(max_buff, "%d", MAX_PLAYERS);
  881.     add_define("MAX_PLAYERS", -1, max_buff);
  882. #ifdef MAX_MORTALS
  883.     sprintf(max_buff, "%d", MAX_MORTALS);
  884.     add_define("MAX_MORTALS", -1, max_buff);
  885. #endif
  886.     for (tmpf=lpc_predefs; tmpf; tmpf=tmpf->next) {
  887.         char namebuf[NSIZE];
  888.         char mtext[MLEN];
  889.  
  890.     *mtext='\0';
  891.     sscanf(tmpf->flag,"%[^=]=%[ -~=]",namebuf,mtext);
  892.     if ( strlen(namebuf) >= NSIZE ) fatal("NSIZE exceeded");
  893.     if ( strlen(mtext) >= MLEN ) fatal("MLEN exceeded");
  894.     add_define(namebuf,-1,mtext);
  895.     }
  896.     yyin = f;
  897.     slast = '\n';
  898.     lastchar = '\n';
  899.     current_line = 1;
  900.     lex_fatal = 0;
  901.     nbuf = 0;
  902.     outp = defbuf+DEFMAX;
  903.     pragma_strict_types = 0;        /* I would prefer !o_flag   /Lars */
  904.     nexpands = 0;
  905. }
  906.  
  907. /*
  908.  * The number of arguments stated below, are used by the compiler.
  909.  * If min == max, then no information has to be coded about the
  910.  * actual number of arguments. Otherwise, the actual number of arguments
  911.  * will be stored in the byte after the instruction.
  912.  * A maximum value of -1 means unlimited maximum value.
  913.  *
  914.  * If an argument has type 0 (T_INVALID) specified, then no checks will
  915.  * be done at run time.
  916.  */
  917. static struct keyword {
  918.     char *word;
  919.     short  token;
  920.     short min_args;    /* Minimum number of arguments. */
  921.     short max_args;    /* Maximum number of arguments. */
  922.     short ret_type;    /* The return type used by the compiler. */
  923.     char arg_type1;    /* Type of argument 1 */
  924.     char arg_type2;    /* Type of argument 2 */
  925.     int arg_index;
  926.     short Default; 
  927. } predefs[] = 
  928. #include "efun_defs.c"
  929.  
  930. static struct keyword reswords[] = {
  931. { "array",              F_MIXED, },
  932. { "break",        F_BREAK, },
  933. { "case",        F_CASE, },
  934. { "catch",        F_CATCH, },
  935. { "continue",        F_CONTINUE, },
  936. { "default",        F_DEFAULT, },
  937. { "do",            F_DO, },
  938. { "else",        F_ELSE, },
  939. { "for",        F_FOR, },
  940. { "if",            F_IF, },
  941. { "inherit",        F_INHERIT, },
  942. { "int",        F_INT, },
  943. { "mixed",        F_MIXED, },
  944. { "nomask",        F_NO_MASK, },
  945. { "object",        F_OBJECT, },
  946. { "parse_command",    F_PARSE_COMMAND, },
  947. { "private",        F_PRIVATE, },
  948. { "protected",        F_PROTECTED, },
  949. { "public",        F_PUBLIC, },
  950. { "return",        F_RETURN, },
  951. { "sscanf",        F_SSCANF, },
  952. { "static",        F_STATIC, },
  953. { "status",        F_STATUS, },
  954. { "string",        F_STRING_DECL, },
  955. { "switch",             F_SWITCH, }, 
  956. { "varargs",          F_VARARGS, },
  957. { "void",        F_VOID, },
  958. { "while",        F_WHILE, },
  959. };
  960.  
  961. struct instr instrs[256];
  962.  
  963. static void add_instr_name(name, n)
  964.     char *name;
  965.     int n;
  966. {
  967.     instrs[n - F_OFFSET].name = name;
  968. }
  969.  
  970. void init_num_args()
  971. {
  972.     int i, n;
  973.  
  974.     for(i=0; i<NELEM(predefs); i++) {
  975.     n = predefs[i].token - F_OFFSET;
  976.     if (n < 0 || n > NELEM(instrs))
  977.         fatal("Token %s has illegal value %d.\n", predefs[i].word, n);
  978.     instrs[n].min_arg = predefs[i].min_args;
  979.     instrs[n].max_arg = predefs[i].max_args;
  980.     instrs[n].name = predefs[i].word;
  981.     instrs[n].type[0] = predefs[i].arg_type1;
  982.     instrs[n].type[1] = predefs[i].arg_type2;
  983.     instrs[n].Default = predefs[i].Default;
  984.     instrs[n].ret_type = predefs[i].ret_type;
  985.     instrs[n].arg_index = predefs[i].arg_index;
  986.     }
  987.     add_instr_name("<", F_LT);
  988.     add_instr_name(">", F_GT);
  989.     add_instr_name("<=", F_LE);
  990.     add_instr_name(">=", F_GE);
  991.     add_instr_name("==", F_EQ);
  992.     add_instr_name("+=", F_ADD_EQ);
  993.     add_instr_name("!", F_NOT);
  994.     add_instr_name("index", F_INDEX_INSTR);
  995.     add_instr_name("push_indexed_lvalue", F_PUSH_INDEXED_LVALUE);
  996.     add_instr_name("identifier", F_IDENTIFIER);
  997.     add_instr_name("local", F_LOCAL_NAME);
  998.     add_instr_name("indirect", F_INDIRECT);
  999.     add_instr_name("number", F_NUMBER);
  1000.     add_instr_name("push_local_variable_lvalue", F_PUSH_LOCAL_VARIABLE_LVALUE);
  1001.     add_instr_name("const1", F_CONST1);
  1002.     add_instr_name("subtract", F_SUBTRACT);
  1003.     add_instr_name("assign", F_ASSIGN);
  1004.     add_instr_name("pop", F_POP_VALUE);
  1005.     add_instr_name("const0", F_CONST0);
  1006.     add_instr_name("jump_when_zero", F_JUMP_WHEN_ZERO);
  1007.     add_instr_name("jump_when_non_zero", F_JUMP_WHEN_NON_ZERO);
  1008.     add_instr_name("||", F_LOR);
  1009.     add_instr_name("&&", F_LAND);
  1010.     add_instr_name("-=", F_SUB_EQ);
  1011.     add_instr_name("jump", F_JUMP);
  1012.     add_instr_name("return", F_RETURN);
  1013.     add_instr_name("sscanf", F_SSCANF);
  1014.     add_instr_name("string", F_STRING);
  1015.     add_instr_name("call", F_CALL_FUNCTION_BY_ADDRESS);
  1016.     add_instr_name("aggregate", F_AGGREGATE);
  1017.     add_instr_name("push_identifier_lvalue", F_PUSH_IDENTIFIER_LVALUE);
  1018.     add_instr_name("+", F_ADD);
  1019.     add_instr_name("!=", F_NE);
  1020.     add_instr_name("dup", F_DUP);
  1021.     add_instr_name("catch", F_CATCH);
  1022.     add_instr_name("neg", F_NEGATE);
  1023.     add_instr_name("x++", F_POST_INC);
  1024.     add_instr_name("x--", F_POST_DEC);
  1025.     add_instr_name("switch",F_SWITCH);
  1026.     add_instr_name("break",F_BREAK);
  1027.     add_instr_name("range",F_RANGE);
  1028.     instrs[F_RANGE-F_OFFSET].type[0] = T_POINTER|T_STRING;
  1029. }
  1030.  
  1031. char *get_f_name(n)
  1032.     int n;
  1033. {
  1034.     if (instrs[n-F_OFFSET].name)
  1035.     return instrs[n-F_OFFSET].name;
  1036.     return "<OTHER>";
  1037. }
  1038.  
  1039. static int
  1040. lookupword(s, words, h)
  1041. char *s;
  1042. struct keyword *words;
  1043. int h;
  1044. {
  1045.     int i, l, r;
  1046.  
  1047.     l = 0;
  1048.     for(;;) {
  1049.       i = (l+h)/2;
  1050.       r = strcmp(s, words[i].word);
  1051.       if (r == 0)
  1052.           return words[i].token;
  1053.       else if (l == i)
  1054.           return -1;
  1055.       else if (r < 0)
  1056.           h = i;
  1057.       else
  1058.           l = i;
  1059.     }
  1060. }
  1061.  
  1062. static int lookup_resword(s)
  1063.     char *s;
  1064. {
  1065.     return lookupword(s, reswords, NELEM(reswords));
  1066. }
  1067.  
  1068. int lookup_predef(s)
  1069.     char *s;
  1070. {
  1071.     return lookupword(s, predefs, NELEM(predefs));
  1072. }
  1073.  
  1074. #define NARGS 25
  1075. #define MARKS '@'
  1076.  
  1077. #define SKIPWHITE do { while (isspace(*p)) {\
  1078.      p++; \
  1079.      if (*p == '/' && *(p+1)=='*') {\
  1080.        p += 2; \
  1081.        while (*p != '*' && *(p+1) != '/') p++; \
  1082.        p += 2; \
  1083.      }\
  1084.    } } while(0)
  1085.  
  1086. #define GETALPHA(p, q, m) \
  1087.     while(isalunum(*p)) {\
  1088.     *q = *p++;\
  1089.     if (q < (m))\
  1090.         q++;\
  1091.     else {\
  1092.         lexerror("Name too long");\
  1093.         return;\
  1094.     }\
  1095.     }\
  1096.     *q++ = 0
  1097.  
  1098. static int
  1099. cmygetc()
  1100. {
  1101.     int c;
  1102.  
  1103.     for(;;) {
  1104.     c = mygetc();
  1105.     if (c == '/') {
  1106.         if (gobble('*'))
  1107.         skip_comment();
  1108.         else
  1109.         return c;
  1110.     } else
  1111.         return c;
  1112.     }
  1113. }
  1114.  
  1115. static void
  1116. refill()
  1117. {
  1118.     char *p;
  1119.     int c;
  1120.  
  1121.     p = yytext;
  1122.     do {
  1123.     c = cmygetc();
  1124.     if (p < yytext+MAXLINE-5)
  1125.         *p++ = c;
  1126.     else {
  1127.         lexerror("Line too long");
  1128.         break;
  1129.     }
  1130.     } while(c != '\n' && c != EOF);
  1131.     p[-1] = ' ';
  1132.     *p = 0;
  1133.     nexpands=0;
  1134.     current_line++;
  1135.     if (inctop == 0)
  1136.     store_line_number_info();
  1137. }
  1138.  
  1139. static void
  1140. handle_define(yyt)
  1141. char *yyt;
  1142. {
  1143.     char namebuf[NSIZE];
  1144.     char args[NARGS][NSIZE];
  1145.     char mtext[MLEN];
  1146.     char *p, *q;
  1147.  
  1148.     p = yyt;
  1149.     strcat(p, " ");
  1150.     q = namebuf;
  1151.     GETALPHA(p, q, namebuf+NSIZE-1);
  1152.     if (*p == '(') {        /* if "function macro" */
  1153.     int arg;
  1154.     int inid;
  1155.     char *ids;
  1156.     p++;            /* skip '(' */
  1157.         SKIPWHITE;
  1158.     if (*p == ')') {
  1159.         arg = 0;
  1160.     } else {
  1161.         for(arg = 0; arg < NARGS; ) {
  1162.         q = args[arg];
  1163.         GETALPHA(p, q, args[arg]+NSIZE-1);
  1164.         arg++;
  1165.                 SKIPWHITE;
  1166.         if (*p == ')')
  1167.             break;
  1168.         if (*p++ != ',') {
  1169.             yyerror("Missing ',' in #define parameter list");
  1170.             return;
  1171.         }
  1172.                 SKIPWHITE;
  1173.         }
  1174.         if (arg == NARGS) {
  1175.         lexerror("Too many macro arguments");
  1176.         return;
  1177.         }
  1178.     }
  1179.     p++;            /* skip ')' */
  1180.     for(inid = 0, q = mtext; *p; ) {
  1181.         if (isalunum(*p)) {
  1182.         if (!inid) {
  1183.             inid++;
  1184.             ids = p;
  1185.         }
  1186.         } else {
  1187.         if (inid) {
  1188.             int idlen = p - ids;
  1189.             int n, l;
  1190.             for(n = 0; n < arg; n++) {
  1191.             l = strlen(args[n]);
  1192.             if (l == idlen && strncmp(args[n], ids, l) == 0) {
  1193.                 q -= idlen;
  1194.                 *q++ = MARKS;
  1195.                 *q++ = n+MARKS+1;
  1196.                 break;
  1197.             }
  1198.             }
  1199.             inid = 0;
  1200.         }
  1201.         }
  1202.         *q = *p;
  1203.         if (*p++ == MARKS)
  1204.         *++q = MARKS;
  1205.         if (q < mtext+MLEN-2)
  1206.         q++;
  1207.         else {
  1208.         lexerror("Macro text too long");
  1209.         return;
  1210.         }
  1211.         if (!*p && p[-2] == '\\') {
  1212.         q -= 2;
  1213.         refill();
  1214.         p = yytext;
  1215.         }
  1216.     }
  1217.     *--q = 0;
  1218.     add_define(namebuf, arg, mtext);
  1219.     } else {
  1220.     for(q = mtext; *p; ) {
  1221.         *q = *p++;
  1222.         if (q < mtext+MLEN-2)
  1223.         q++;
  1224.         else {
  1225.         lexerror("Macro text too long");
  1226.         return;
  1227.         }
  1228.         if (!*p && p[-2] == '\\') {
  1229.         q -= 2;
  1230.         refill();
  1231.         p = yytext;
  1232.         }
  1233.     }
  1234.     *--q = 0;
  1235.     add_define(namebuf, -1, mtext);
  1236.     }
  1237.     return;
  1238. }
  1239.  
  1240. static void
  1241. myungetc(c)
  1242. int c;
  1243. {
  1244.     *--outp = c;
  1245.     nbuf++;
  1246. }
  1247.  
  1248. static void
  1249. add_input(p)
  1250. char *p;
  1251. {
  1252.     int l = strlen(p);
  1253.  
  1254. /*if (l > 2)
  1255. fprintf(stderr, "add '%s'\n", p);*/
  1256.     if (nbuf+l >= DEFMAX-10) {
  1257.     lexerror("Macro expansion buffer overflow");
  1258.     return;
  1259.     }
  1260.     outp -= l;
  1261.     nbuf += l;
  1262.     strncpy(outp, p, l);
  1263. }
  1264.  
  1265. #define DEFHASH 33
  1266. struct defn *defns[DEFHASH];
  1267.  
  1268. #define defhash(s) hashstr(s, 10, DEFHASH)
  1269.  
  1270. static void
  1271. add_define(name, nargs, exps)
  1272. char *name, *exps;
  1273. int nargs;
  1274. {
  1275.     struct defn *p;
  1276.     int h;
  1277.  
  1278.     if (p = lookup_define(name)) {
  1279.     if (nargs != p->nargs || strcmp(exps, p->exps) != 0) {
  1280.         char buf[200+NSIZE];
  1281.         sprintf(buf, "Redefinition of #define %s", name);
  1282.         yyerror(buf);
  1283.     }
  1284.     return;
  1285.     }
  1286.     p = (struct defn *)xalloc(sizeof(struct defn));
  1287.     p->name = xalloc(strlen(name)+1);
  1288.     strcpy(p->name, name);
  1289.     p->undef = 0;
  1290.     p->nargs = nargs;
  1291.     p->exps = xalloc(strlen(exps)+1);
  1292.     strcpy(p->exps, exps);
  1293.     h = defhash(name);
  1294.     p->next = defns[h];
  1295.     defns[h] = p;
  1296. /*fprintf(stderr, "define '%s' %d '%s'\n", name, nargs, exps);*/
  1297. }
  1298.  
  1299. static void
  1300. free_defines()
  1301. {
  1302.     struct defn *p, *q;
  1303.     int i;
  1304.  
  1305.     for(i = 0; i < DEFHASH; i++) {
  1306.     for(p = defns[i]; p; p = q) {
  1307.         q = p->next;
  1308.         free(p->name);
  1309.         free(p->exps);
  1310.         free((char *)p);
  1311.     }
  1312.     defns[i] = 0;
  1313.     }
  1314.     nexpands = 0;
  1315. }
  1316.  
  1317. struct defn *
  1318. lookup_define(s)
  1319. char *s;
  1320. {
  1321.     struct defn *p;
  1322.     int h;
  1323.  
  1324.     h = defhash(s);
  1325.     for(p = defns[h]; p; p = p->next)
  1326.     if (!p->undef && strcmp(s, p->name) == 0)
  1327.         return p;
  1328.     return 0;
  1329. }
  1330.  
  1331. #define SKIPW  do { c = cmygetc(); } while(isspace(c));
  1332.  
  1333.  
  1334. /* Check if yytext is a macro and expand if it is. */
  1335. static int
  1336. expand_define()
  1337. {
  1338.     struct defn *p;
  1339.     char expbuf[DEFMAX];
  1340.     char *args[NARGS];
  1341.     char buf[DEFMAX];
  1342.     char *q, *e, *b;
  1343.  
  1344.     if (nexpands++ > EXPANDMAX) {
  1345.     lexerror("Too many macro expansions");
  1346.     return 0;
  1347.     }
  1348.     p = lookup_define(yytext);
  1349.     if (!p) {
  1350.     return 0;
  1351.     }
  1352.     if (p->nargs == -1) {
  1353.     add_input(p->exps);
  1354.     } else {
  1355.     int c, parcnt = 0, dquote = 0, squote = 0;
  1356.     int n;
  1357.     SKIPW;
  1358.     if (c != '(') {
  1359. /*
  1360.             myungetc(c);
  1361. */
  1362.         yyerror("Missing '(' in macro call");
  1363.         return 0;
  1364.     }
  1365.     SKIPW;
  1366.     if (c == ')')
  1367.         n = 0;
  1368.     else {
  1369.         q = expbuf;
  1370.         args[0] = q;
  1371.         for(n = 0; n < NARGS; ) {
  1372.         switch(c) {
  1373.         case '"': if (!squote) dquote ^= 1; break;
  1374.         case '\'': if (!dquote) squote ^= 1; break;
  1375.         case '(': if (!squote && !dquote) parcnt++; break;
  1376.         case ')': if (!squote && !dquote) parcnt--; break;
  1377.         case '\\': if (squote || dquote) { *q++ = c; c = mygetc();} break;
  1378.         case '\n': if (squote || dquote) { lexerror("Newline in string"); return 0; } break;
  1379.         }
  1380.         if (c == ',' && !parcnt && !dquote && !squote) {
  1381.             *q++ = 0;
  1382.             args[++n] = q;
  1383.         } else if (parcnt < 0) {
  1384.             *q++ = 0;
  1385.             n++;
  1386.             break;
  1387.         } else {
  1388.             if (c == EOF) {
  1389.             lexerror("Unexpected end of file");
  1390.             return 0;
  1391.             }
  1392.             if (q >= expbuf + DEFMAX - 5) {
  1393.             lexerror("Macro argument overflow");
  1394.             return 0;
  1395.             } else {
  1396.             *q++ = c;
  1397.             }
  1398.         }
  1399.         if (!squote && ! dquote)
  1400.             c = cmygetc();
  1401.         else
  1402.             c = mygetc();
  1403.         }
  1404.         if (n == NARGS) {
  1405.         lexerror("Maximum macro argument count exceeded");
  1406.         return 0;
  1407.         }
  1408.     }
  1409.     if (n != p->nargs) {
  1410.         yyerror("Wrong number of macro arguments");
  1411.         return 0;
  1412.     }
  1413.     /* Do expansion */
  1414.     b = buf;
  1415.     e = p->exps;
  1416.     while(*e) {
  1417.         if (*e == MARKS) {
  1418.         if (*++e == MARKS)
  1419.             *b++ = *e++;
  1420.         else {
  1421.             for(q = args[*e++ - MARKS - 1]; *q; ) {
  1422.             *b++ = *q++;
  1423.             if (b >= buf+DEFMAX) {
  1424.                 lexerror("Macro expansion overflow");
  1425.                 return 0;
  1426.             }
  1427.             }
  1428.         }
  1429.         } else {
  1430.         *b++ = *e++;
  1431.         if (b >= buf+DEFMAX) {
  1432.             lexerror("Macro expansion overflow");
  1433.             return 0;
  1434.         }
  1435.         }
  1436.     }
  1437.     *b++ = 0;
  1438.     add_input(buf);
  1439.     }
  1440.     return 1;
  1441. }
  1442.  
  1443.  
  1444. /* Stuff to evaluate expression.  I havn'r really checked it. /LA
  1445. ** Written by "J\"orn Rennecke" <amylaar@cs.tu-berlin.de>
  1446. */
  1447. #define SKPW     do c = mygetc(); while(isspace(c)); myungetc(c)
  1448.  
  1449.  
  1450. static int exgetc() {
  1451.   register char c,*yyp;
  1452.  
  1453.   c=mygetc();
  1454.   while ( isalpha(c) || c=='_' ) {
  1455.     yyp=yytext;
  1456.     do {
  1457.       SAVEC;
  1458.       c=mygetc();
  1459.     } while ( isalunum(c) );
  1460.     myungetc(c);
  1461.     *yyp='\0';
  1462.     if (strcmp(yytext, "defined") == 0) {
  1463.     /* handle the defined "function" in #if */
  1464.     do c = mygetc(); while(isspace(c));
  1465.     if (c != '(') {
  1466.         yyerror("Missing ( in defined");
  1467.         continue;
  1468.     }
  1469.     do c = mygetc(); while(isspace(c));
  1470.     yyp=yytext;
  1471.     while ( isalunum(c) ) {
  1472.         SAVEC;
  1473.         c=mygetc();
  1474.     }
  1475.     *yyp='\0';
  1476.     while(isspace(c)) c = mygetc();
  1477.     if (c != ')') {
  1478.         yyerror("Missing ) in defined");
  1479.         continue;
  1480.     }
  1481.     SKPW;
  1482.     if (lookup_define(yytext))
  1483.         add_input(" 1 ");
  1484.     else
  1485.         add_input(" 0 ");
  1486.     } else {
  1487.     if (!expand_define()) add_input(" 0 ");
  1488.     }
  1489.     c=mygetc();
  1490.   }
  1491.   return c;
  1492. }
  1493.  
  1494. #define BNOT   1
  1495. #define LNOT   2
  1496. #define UMINUS 3
  1497. #define UPLUS  4
  1498.  
  1499. #define MULT   1
  1500. #define DIV    2
  1501. #define MOD    3
  1502. #define BPLUS  4
  1503. #define BMINUS 5
  1504. #define LSHIFT 6
  1505. #define RSHIFT 7
  1506. #define LESS   8
  1507. #define LEQ    9
  1508. #define GREAT 10
  1509. #define GEQ   11
  1510. #define EQ    12
  1511. #define NEQ   13
  1512. #define BAND  14
  1513. #define XOR   15
  1514. #define BOR   16
  1515. #define LAND  17
  1516. #define LOR   18
  1517. #define QMARK 19
  1518.  
  1519. static char _optab[]=
  1520. {0,4,0,0,0,26,56,0,0,0,18,14,0,10,0,22,0,0,0,0,0,0,0,0,0,0,0,0,30,50,40,74,
  1521. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,0,
  1522. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63,0,1};
  1523. static char optab2[]=
  1524. {BNOT,0,0,LNOT,'=',NEQ,7,0,0,UMINUS,0,BMINUS,10,UPLUS,0,BPLUS,10,
  1525. 0,0,MULT,11,0,0,DIV,11,0,0,MOD,11,
  1526. 0,'<',LSHIFT,9,'=',LEQ,8,0,LESS,8,0,'>',RSHIFT,9,'=',GEQ,8,0,GREAT,8,
  1527. 0,'=',EQ,7,0,0,0,'&',LAND,3,0,BAND,6,0,'|',LOR,2,0,BOR,4,
  1528. 0,0,XOR,5,0,0,QMARK,1};
  1529. #define optab1 (_optab-' ')
  1530.  
  1531. static int cond_get_exp(priority)
  1532. int priority;
  1533. {
  1534.   int c;
  1535.   int value,value2,x;
  1536.  
  1537.   do c=exgetc(); while ( isspace(c) );
  1538.   if ( c=='(' ) {
  1539.  
  1540.     value=cond_get_exp(0);
  1541.     do c=exgetc(); while ( isspace(c) );
  1542.     if ( c!=')' ) {
  1543.       yyerror("bracket not paired in #if");
  1544.       if (!c) myungetc('\0');
  1545.     }
  1546.   } else if ( ispunct(c) ) {
  1547.     x=optab1[c];
  1548.     if (!x) {
  1549.       yyerror("illegal character in #if");
  1550.       return 0;
  1551.     }
  1552.     value=cond_get_exp(12);
  1553.     switch ( optab2[x-1] ) {
  1554.       case BNOT  : value = ~value; break;
  1555.       case LNOT  : value = !value; break;
  1556.       case UMINUS: value = -value; break;
  1557.       case UPLUS : value =  value; break;
  1558.       default :
  1559.     yyerror("illegal unary operator in #if");
  1560.     return 0;
  1561.     }
  1562.   } else {
  1563.     int base;
  1564.  
  1565.     if ( !isdigit(c) ) {
  1566.       if (!c) {
  1567.     yyerror("missing expression in #if");
  1568.     myungetc('\0');
  1569.       } else yyerror("illegal character in #if");
  1570.       return 0;
  1571.     }
  1572.     value=0;
  1573.     if ( c!='0' ) base=10;
  1574.     else {
  1575.       c=mygetc();
  1576.       if ( c=='x' || c=='X' ) {
  1577.     base=16;
  1578.     c=mygetc();
  1579.       } else base=8;
  1580.     }
  1581.     for(;;) {
  1582.       if ( isdigit(c) ) x= -'0';
  1583.       else if ( isupper(c) ) x= -'A'+10;
  1584.       else if ( islower(c) ) x= -'a'+10;
  1585.       else break;
  1586.       x+=c;
  1587.       if ( x > base ) break;
  1588.       value=value*base+x;
  1589.       c=mygetc();
  1590.     }
  1591.     myungetc(c);
  1592.   }
  1593.   for (;;) {
  1594.     do c=exgetc(); while ( isspace(c) );
  1595.     if ( !ispunct(c) ) break;
  1596.     x=optab1[c];
  1597.     if (!x) break;
  1598.     value2=mygetc();
  1599.     for(;;x+=3) {
  1600.       if ( !optab2[x] ) {
  1601.     myungetc(value2);
  1602.     if ( !optab2[x+1] ) {
  1603.       yyerror("illegal operator use in #if");
  1604.       return 0;
  1605.     }
  1606.     break;
  1607.       }
  1608.       if ( value2==optab2[x] ) break;
  1609.     }
  1610.     if ( priority >= optab2[x+2] ) {
  1611.       if( optab2[x] ) myungetc(value2);
  1612.       break;
  1613.     }
  1614.     value2=cond_get_exp(optab2[x+2]);
  1615.     switch ( optab2[x+1] ) {
  1616.       case MULT : value *= value2;    break;
  1617.       case DIV  : value /= value2;    break;
  1618.       case MOD  : value %= value2;    break;
  1619.       case BPLUS  : value += value2;    break;
  1620.       case BMINUS : value -= value2;    break;
  1621.       case LSHIFT : value <<= value2;    break;
  1622.       case RSHIFT : value >>= value2;    break;
  1623.       case LESS   : value = value <  value2;    break;
  1624.       case LEQ    : value = value <= value2;    break;
  1625.       case GREAT  : value = value >  value2;    break;
  1626.       case GEQ    : value = value >= value2;    break;
  1627.       case EQ     : value = value == value2;    break;
  1628.       case NEQ    : value = value != value2;    break;
  1629.       case BAND   : value &= value2;    break;
  1630.       case XOR    : value ^= value2;    break;
  1631.       case BOR    : value |= value2;    break;
  1632.       case LAND   : value = value && value2;    break;
  1633.       case LOR    : value = value || value2;    break;
  1634.       case QMARK  :
  1635.     do c=exgetc(); while( isspace(c) );
  1636.     if ( c!=':' ) {
  1637.       yyerror("'?' without ':' in #if");
  1638.       myungetc(c);
  1639.       return 0;
  1640.     }
  1641.     if ( value ) {
  1642.       cond_get_exp(1);
  1643.       value=value2;
  1644.     }
  1645.     else value=cond_get_exp(1);
  1646.     break;
  1647.     }
  1648.   }
  1649.   myungetc(c);
  1650.   return value;
  1651. }
  1652.  
  1653. void set_inc_list(sv)
  1654.     struct svalue *sv;
  1655. {
  1656.     int i;
  1657.     struct vector *v;
  1658.     char *p;
  1659.  
  1660.     if (sv == 0) {
  1661.     fprintf(stderr, "There must be a function 'define_include_dirs' in master.c.\n");
  1662.     fprintf(stderr, "This function should return an array of all directories to be searched\n");
  1663.     fprintf(stderr, "for include files.\n");
  1664.     exit(1);
  1665.     }
  1666.     if (sv->type != T_POINTER) {
  1667.     fprintf(stderr, "'define_include_dirs' in master.c did not return an array.\n");
  1668.     exit(1);
  1669.     }
  1670.     v = sv->u.vec;
  1671.     inc_list = (char **)xalloc(v->size * sizeof (char *));
  1672.     inc_list_size = v->size;
  1673.     for (i=0; i < v->size; i++) {
  1674.     if (v->item[i].type != T_STRING) {
  1675.         fprintf(stderr, "Illegal value returned from 'define_include_dirs' in master.c\n");
  1676.         exit(1);
  1677.     }
  1678.     p = v->item[i].u.string;
  1679.     /*
  1680.      * Even make sure that the game administrator has not made an error.
  1681.      */
  1682.     if (!legal_path(p+(*p == '/'))) {
  1683.         fprintf(stderr, "'define_include_dirs' must give paths without any '..'\n");
  1684.         exit(1);
  1685.     }
  1686.     inc_list[i] = make_shared_string(p);
  1687.     }
  1688. }
  1689.