lex.c.1
上传用户:upcnvip
上传日期:2007-01-06
资源大小:474k
文件大小:48k
源码类别:

编译器/解释器

开发平台:

C/C++

  1. /* "p2c", a Pascal to C translator.
  2.    Copyright (C) 1989 David Gillespie.
  3.    Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation (any version).
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; see the file COPYING.  If not, write to
  13. the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  14. #define PROTO_LEX_C
  15. #include "trans.h"
  16. /* Define LEXDEBUG for a token trace */
  17. #define LEXDEBUG
  18. #define EOFMARK 1
  19. Static char dollar_flag, lex_initialized;
  20. Static int if_flag, if_skip;
  21. Static int commenting_flag;
  22. Static char *commenting_ptr;
  23. Static int skipflag;
  24. Static char modulenotation;
  25. Static short inputkind;
  26. Static Strlist *instrlist;
  27. Static char inbuf[300];
  28. Static char *oldinfname, *oldctxname;
  29. Static Strlist *endnotelist;
  30. #define INP_FILE     0
  31. #define INP_INCFILE  1
  32. #define INP_STRLIST  2
  33. Static struct inprec {
  34.     struct inprec *next;
  35.     short kind;
  36.     char *fname, *inbufptr;
  37.     int lnum;
  38.     FILE *filep;
  39.     Strlist *strlistp, *tempopts;
  40.     Token curtok, saveblockkind;
  41.     Symbol *curtoksym;
  42.     Meaning *curtokmeaning;
  43. } *topinput;
  44. char *fixpascalname(name)
  45. char *name;
  46. {
  47.     char *cp, *cp2;
  48.     if (pascalsignif > 0) {
  49.         name = format_ds("%.*s", pascalsignif, name);
  50.         if (!pascalcasesens)
  51.             upc(name);
  52. else if (pascalcasesens == 3)
  53.     lwc(name);
  54.     } else if (!pascalcasesens)
  55.         name = strupper(name);
  56.     else if (pascalcasesens == 3)
  57. name = strlower(name);
  58.     if (ignorenonalpha) {
  59. for (cp = cp2 = name; *cp; cp++)
  60.     if (isalnum(*cp))
  61. *cp2++ = *cp;
  62.     }
  63.     return name;
  64. }
  65. Static void makekeyword(name)
  66. char *name;
  67. {
  68.     Symbol *sym;
  69.     if (*name) {
  70.         sym = findsymbol(name);
  71.         sym->flags |= AVOIDNAME;
  72.     }
  73. }
  74. Static void makeglobword(name)
  75. char *name;
  76. {
  77.     Symbol *sym;
  78.     if (*name) {
  79.         sym = findsymbol(name);
  80.         sym->flags |= AVOIDGLOB;
  81.     }
  82. }
  83. Static void makekeywords()
  84. {
  85.     makekeyword("auto");
  86.     makekeyword("break");
  87.     makekeyword("char");
  88.     makekeyword("continue");
  89.     makekeyword("default");
  90.     makekeyword("defined");   /* is this one really necessary? */
  91.     makekeyword("double");
  92.     makekeyword("enum");
  93.     makekeyword("extern");
  94.     makekeyword("float");
  95.     makekeyword("int");
  96.     makekeyword("long");
  97.     makekeyword("noalias");
  98.     makekeyword("register");
  99.     makekeyword("return");
  100.     makekeyword("short");
  101.     makekeyword("signed");
  102.     makekeyword("sizeof");
  103.     makekeyword("static");
  104.     makekeyword("struct");
  105.     makekeyword("switch");
  106.     makekeyword("typedef");
  107.     makekeyword("union");
  108.     makekeyword("unsigned");
  109.     makekeyword("void");
  110.     makekeyword("volatile");
  111.     makekeyword("asm");
  112.     makekeyword("fortran");
  113.     makekeyword("entry");
  114.     makekeyword("pascal");
  115.     if (cplus != 0) {
  116.         makekeyword("class");
  117.         makekeyword("delete");
  118.         makekeyword("friend");
  119.         makekeyword("inline");
  120.         makekeyword("new");
  121.         makekeyword("operator");
  122.         makekeyword("overload");
  123.         makekeyword("public");
  124.         makekeyword("this");
  125.         makekeyword("virtual");
  126.     }
  127.     makekeyword(name_UCHAR);
  128.     makekeyword(name_SCHAR);    /* any others? */
  129.     makekeyword(name_BOOLEAN);
  130.     makekeyword(name_PROCEDURE);
  131.     makekeyword(name_ESCAPE);
  132.     makekeyword(name_ESCIO);
  133.     makekeyword(name_CHKIO);
  134.     makekeyword(name_SETIO);
  135.     makeglobword("main");
  136.     makeglobword("vextern");     /* used in generated .h files */
  137.     makeglobword("argc");
  138.     makeglobword("argv");
  139.     makekeyword("TRY");
  140.     makekeyword("RECOVER");
  141.     makekeyword("RECOVER2");
  142.     makekeyword("ENDTRY");
  143. }
  144. Static Symbol *Pkeyword(name, tok)
  145. char *name;
  146. Token tok;
  147. {
  148.     Symbol *sp = NULL;
  149.     if (pascalcasesens != 2) {
  150. sp = findsymbol(strlower(name));
  151. sp->kwtok = tok;
  152.     }
  153.     if (pascalcasesens != 3) {
  154. sp = findsymbol(strupper(name));
  155. sp->kwtok = tok;
  156.     }
  157.     return sp;
  158. }
  159. Static Symbol *Pkeywordposs(name, tok)
  160. char *name;
  161. Token tok;
  162. {
  163.     Symbol *sp = NULL;
  164.     if (pascalcasesens != 2) {
  165. sp = findsymbol(strlower(name));
  166. sp->kwtok = tok;
  167. sp->flags |= KWPOSS;
  168.     }
  169.     if (pascalcasesens != 3) {
  170. sp = findsymbol(strupper(name));
  171. sp->kwtok = tok;
  172. sp->flags |= KWPOSS;
  173.     }
  174.     return sp;
  175. }
  176. Static void makePascalwords()
  177. {
  178.     Pkeyword("AND", TOK_AND);
  179.     Pkeyword("ARRAY", TOK_ARRAY);
  180.     Pkeywordposs("ANYVAR", TOK_ANYVAR);
  181.     Pkeywordposs("ABSOLUTE", TOK_ABSOLUTE);
  182.     Pkeyword("BEGIN", TOK_BEGIN);
  183.     Pkeywordposs("BY", TOK_BY);
  184.     Pkeyword("CASE", TOK_CASE);
  185.     Pkeyword("CONST", TOK_CONST);
  186.     Pkeyword("DIV", TOK_DIV);
  187.     Pkeywordposs("DEFINITION", TOK_DEFINITION);
  188.     Pkeyword("DO", TOK_DO);
  189.     Pkeyword("DOWNTO", TOK_DOWNTO);
  190.     Pkeyword("ELSE", TOK_ELSE);
  191.     Pkeywordposs("ELSIF", TOK_ELSIF);
  192.     Pkeyword("END", TOK_END);
  193.     Pkeywordposs("EXPORT", TOK_EXPORT);
  194.     Pkeyword("FILE", TOK_FILE);
  195.     Pkeyword("FOR", TOK_FOR);
  196.     Pkeywordposs("FROM", TOK_FROM);
  197.     Pkeyword("FUNCTION", TOK_FUNCTION);
  198.     Pkeyword("GOTO", TOK_GOTO);
  199.     Pkeyword("IF", TOK_IF);
  200.     Pkeywordposs("IMPLEMENT", TOK_IMPLEMENT);
  201.     Pkeywordposs("IMPLEMENTATION", TOK_IMPLEMENT);
  202.     Pkeywordposs("IMPORT", TOK_IMPORT);
  203.     Pkeyword("IN", TOK_IN);
  204.     Pkeywordposs("INLINE", TOK_INLINE);
  205.     Pkeywordposs("INTERFACE", TOK_EXPORT);
  206.     Pkeywordposs("INTERRUPT", TOK_INTERRUPT);
  207.     Pkeyword("LABEL", TOK_LABEL);
  208.     Pkeywordposs("LOOP", TOK_LOOP);
  209.     Pkeyword("MOD", TOK_MOD);
  210.     Pkeywordposs("MODULE", TOK_MODULE);
  211.     Pkeyword("NIL", TOK_NIL);
  212.     Pkeyword("NOT", TOK_NOT);
  213.     Pkeyword("OF", TOK_OF);
  214.     Pkeyword("OR", TOK_OR);
  215.     Pkeywordposs("ORIGIN", TOK_ORIGIN);
  216.     Pkeywordposs("OTHERWISE", TOK_OTHERWISE);
  217.     Pkeywordposs("OVERLAY", TOK_SEGMENT);
  218.     Pkeyword("PACKED", TOK_PACKED);
  219.     Pkeywordposs("POINTER", TOK_POINTER);
  220.     Pkeyword("PROCEDURE", TOK_PROCEDURE);
  221.     Pkeyword("PROGRAM", TOK_PROGRAM);
  222.     Pkeywordposs("QUALIFIED", TOK_QUALIFIED);
  223.     Pkeyword("RECORD", TOK_RECORD);
  224.     Pkeywordposs("RECOVER", TOK_RECOVER);
  225.     Pkeywordposs("REM", TOK_REM);
  226.     Pkeyword("REPEAT", TOK_REPEAT);
  227.     Pkeywordposs("RETURN", TOK_RETURN);
  228.     if (which_lang == LANG_UCSD)
  229. Pkeyword("SEGMENT", TOK_SEGMENT);
  230.     else
  231. Pkeywordposs("SEGMENT", TOK_SEGMENT);
  232.     Pkeyword("SET", TOK_SET);
  233.     Pkeywordposs("SHL", TOK_SHL);
  234.     Pkeywordposs("SHR", TOK_SHR);
  235.     Pkeyword("THEN", TOK_THEN);
  236.     Pkeyword("TO", TOK_TO);
  237.     Pkeywordposs("TRY", TOK_TRY);
  238.     Pkeyword("TYPE", TOK_TYPE);
  239.     Pkeyword("UNTIL", TOK_UNTIL);
  240.     Pkeywordposs("USES", TOK_IMPORT);
  241.     Pkeywordposs("UNIT", TOK_MODULE);
  242.     if (which_lang == LANG_VAX)
  243. Pkeyword("VALUE", TOK_VALUE);
  244.     else
  245. Pkeywordposs("VALUE", TOK_VALUE);
  246.     Pkeyword("VAR", TOK_VAR);
  247.     Pkeywordposs("VARYING", TOK_VARYING);
  248.     Pkeyword("WHILE", TOK_WHILE);
  249.     Pkeyword("WITH", TOK_WITH);
  250.     Pkeywordposs("XOR", TOK_XOR);
  251.     Pkeyword("__MODULE", TOK_MODULE);
  252.     Pkeyword("__IMPORT", TOK_IMPORT);
  253.     Pkeyword("__EXPORT", TOK_EXPORT);
  254.     Pkeyword("__IMPLEMENT", TOK_IMPLEMENT);
  255. }
  256. Static void deterministic(name)
  257. char *name;
  258. {
  259.     Symbol *sym;
  260.     if (*name) {
  261.         sym = findsymbol(name);
  262.         sym->flags |= DETERMF;
  263.     }
  264. }
  265. Static void nosideeff(name)
  266. char *name;
  267. {
  268.     Symbol *sym;
  269.     if (*name) {
  270.         sym = findsymbol(name);
  271.         sym->flags |= NOSIDEEFF;
  272.     }
  273. }
  274. Static void recordsideeffects()
  275. {
  276.     deterministic("abs");
  277.     deterministic("acos");
  278.     deterministic("asin");
  279.     deterministic("atan");
  280.     deterministic("atan2");
  281.     deterministic("atof");
  282.     deterministic("atoi");
  283.     deterministic("atol");
  284.     deterministic("ceil");
  285.     deterministic("cos");
  286.     deterministic("cosh");
  287.     deterministic("exp");
  288.     deterministic("fabs");
  289.     deterministic("feof");
  290.     deterministic("feoln");
  291.     deterministic("ferror");
  292.     deterministic("floor");
  293.     deterministic("fmod");
  294.     deterministic("ftell");
  295.     deterministic("isalnum");
  296.     deterministic("isalpha");
  297.     deterministic("isdigit");
  298.     deterministic("islower");
  299.     deterministic("isspace");
  300.     deterministic("isupper");
  301.     deterministic("labs");
  302.     deterministic("ldexp");
  303.     deterministic("log");
  304.     deterministic("log10");
  305.     deterministic("memcmp");
  306.     deterministic("memchr");
  307.     deterministic("pow");
  308.     deterministic("sin");
  309.     deterministic("sinh");
  310.     deterministic("sqrt");
  311.     deterministic("strchr");
  312.     deterministic("strcmp");
  313.     deterministic("strcspn");
  314.     deterministic("strlen");
  315.     deterministic("strncmp");
  316.     deterministic("strpbrk");
  317.     deterministic("strrchr");
  318.     deterministic("strspn");
  319.     deterministic("strstr");
  320.     deterministic("tan");
  321.     deterministic("tanh");
  322.     deterministic("tolower");
  323.     deterministic("toupper");
  324.     deterministic(setequalname);
  325.     deterministic(subsetname);
  326.     deterministic(signextname);
  327. }
  328. void init_lex()
  329. {
  330.     int i;
  331.     inputkind = INP_FILE;
  332.     inf_lnum = 0;
  333.     inf_ltotal = 0;
  334.     *inbuf = 0;
  335.     inbufptr = inbuf;
  336.     keepingstrlist = NULL;
  337.     tempoptionlist = NULL;
  338.     switch_strpos = 0;
  339.     dollar_flag = 0;
  340.     if_flag = 0;
  341.     if_skip = 0;
  342.     commenting_flag = 0;
  343.     skipflag = 0;
  344.     inbufindent = 0;
  345.     modulenotation = 1;
  346.     notephase = 0;
  347.     endnotelist = NULL;
  348.     for (i = 0; i < SYMHASHSIZE; i++)
  349.         symtab[i] = 0;
  350.     C_lex = 0;
  351.     lex_initialized = 0;
  352. }
  353. void setup_lex()
  354. {
  355.     lex_initialized = 1;
  356.     if (!strcmp(language, "MODCAL"))
  357.         sysprog_flag = 2;
  358.     else
  359.         sysprog_flag = 0;
  360.     if (shortcircuit < 0)
  361.         partial_eval_flag = (which_lang == LANG_TURBO ||
  362.      which_lang == LANG_VAX ||
  363.      which_lang == LANG_OREGON ||
  364.      modula2 ||
  365.      hpux_lang);
  366.     else
  367.         partial_eval_flag = shortcircuit;
  368.     iocheck_flag = 1;
  369.     range_flag = 1;
  370.     ovflcheck_flag = 1;
  371.     stackcheck_flag = 1;
  372.     fixedflag = 0;
  373.     withlevel = 0;
  374.     makekeywords();
  375.     makePascalwords();
  376.     recordsideeffects();
  377.     topinput = 0;
  378.     ignore_directives = 0;
  379.     skipping_module = 0;
  380.     blockkind = TOK_END;
  381.     gettok();
  382. }
  383. int checkeatnote(msg)
  384. char *msg;
  385. {
  386.     Strlist *lp;
  387.     char *cp;
  388.     int len;
  389.     for (lp = eatnotes; lp; lp = lp->next) {
  390. if (!strcmp(lp->s, "1")) {
  391.     echoword("[*]", 0);
  392.     return 1;
  393. }
  394. if (!strcmp(lp->s, "0"))
  395.     return 0;
  396. len = strlen(lp->s);
  397. cp = msg;
  398. while (*cp && (*cp != lp->s[0] || strncmp(cp, lp->s, len)))
  399.     cp++;
  400. if (*cp) {
  401.     cp = lp->s;
  402.     if (*cp != '[')
  403. cp = format_s("[%s", cp);
  404.     if (cp[strlen(cp)-1] != ']')
  405. cp = format_s("%s]", cp);
  406.     echoword(cp, 0);
  407.     return 1;
  408. }
  409.     }
  410.     return 0;
  411. }
  412. void beginerror()
  413. {
  414.     end_source();
  415.     if (showprogress) {
  416.         fprintf(stderr, "r%60sr", "");
  417.         clearprogress();
  418.     } else
  419. echobreak();
  420. }
  421. void counterror()
  422. {
  423.     if (maxerrors > 0) {
  424. if (--maxerrors == 0) {
  425.     fprintf(outf, "n/* Translation aborted: Too many errors. */n");
  426.     fprintf(outf,   "-------------------------------------------n");
  427.     if (outf != stdout)
  428. printf("Translation aborted: Too many errors.n");
  429.     if (verbose)
  430. fprintf(logf, "Translation aborted: Too many errors.n");
  431.     closelogfile();
  432.     exit(EXIT_FAILURE);
  433. }
  434.     }
  435. }
  436. void error(msg)     /* does not return */
  437. char *msg;
  438. {
  439.     flushcomments(NULL, -1, -1);
  440.     beginerror();
  441.     fprintf(outf, "/* %s, line %d: %s */n", infname, inf_lnum, msg);
  442.     fprintf(outf, "/* Translation aborted. */n");
  443.     fprintf(outf, "--------------------------n");
  444.     if (outf != stdout) {
  445.         printf("%s, line %d/%d: %sn", infname, inf_lnum, outf_lnum, msg);
  446.         printf("Translation aborted.n");
  447.     }
  448.     if (verbose) {
  449. fprintf(logf, "%s, line %d/%d: %sn",
  450. infname, inf_lnum, outf_lnum, msg);
  451. fprintf(logf, "Translation aborted.n");
  452.     }
  453.     closelogfile();
  454.     exit(EXIT_FAILURE);
  455. }
  456. void interror(proc, msg)      /* does not return */
  457. char *proc, *msg;
  458. {
  459.     error(format_ss("Internal error in %s: %s", proc, msg));
  460. }
  461. void warning(msg)
  462. char *msg;
  463. {
  464.     if (checkeatnote(msg)) {
  465. if (verbose)
  466.     fprintf(logf, "%s, %d/%d: Omitted warning: %sn",
  467.     infname, inf_lnum, outf_lnum, msg);
  468. return;
  469.     }
  470.     beginerror();
  471.     addnote(format_s("Warning: %s", msg), curserial);
  472.     counterror();
  473. }
  474. void intwarning(proc, msg)
  475. char *proc, *msg;
  476. {
  477.     if (checkeatnote(msg)) {
  478. if (verbose)
  479.     fprintf(logf, "%s, %d/%d: Omitted internal error in %s: %sn",
  480.     infname, inf_lnum, outf_lnum, proc, msg);
  481. return;
  482.     }
  483.     beginerror();
  484.     addnote(format_ss("Internal error in %s: %s", proc, msg), curserial);
  485.     if (error_crash)
  486.         exit(EXIT_FAILURE);
  487.     counterror();
  488. }
  489. void note(msg)
  490. char *msg;
  491. {
  492.     if (blockkind == TOK_IMPORT || checkeatnote(msg)) {
  493. if (verbose)
  494.     fprintf(logf, "%s, %d/%d: Omitted note: %sn",
  495.     infname, inf_lnum, outf_lnum, msg);
  496. return;
  497.     }
  498.     beginerror();
  499.     addnote(format_s("Note: %s", msg), curserial);
  500.     counterror();
  501. }
  502. void endnote(msg)
  503. char *msg;
  504. {
  505.     if (blockkind == TOK_IMPORT || checkeatnote(msg)) {
  506. if (verbose)
  507.     fprintf(logf, "%s, %d/%d: Omitted end-note: %sn",
  508.     infname, inf_lnum, outf_lnum, msg);
  509. return;
  510.     }
  511.     if (verbose)
  512. fprintf(logf, "%s, %d/%d: Recorded end-note: %sn",
  513. infname, inf_lnum, outf_lnum, msg);
  514.     (void) strlist_add(&endnotelist, msg);
  515. }
  516. void showendnotes()
  517. {
  518.     while (initialcalls) {
  519. if (initialcalls->value)
  520.     endnote(format_s("Remember to call %s in main program [215]",
  521.      initialcalls->s));
  522. strlist_eat(&initialcalls);
  523.     }
  524.     if (endnotelist) {
  525. end_source();
  526. while (endnotelist) {
  527.     if (outf != stdout) {
  528. beginerror();
  529. printf("Note: %sn", endnotelist->s);
  530.     }
  531.     fprintf(outf, "/* p2c: Note: %s */n", endnotelist->s);
  532.     outf_lnum++;
  533.     strlist_eat(&endnotelist);
  534. }
  535.     }
  536. }
  537. char *tok_name(tok)
  538. Token tok;
  539. {
  540.     if (tok == TOK_END && inputkind == INP_STRLIST)
  541. return "end of macro";
  542.     if (tok == curtok && tok == TOK_IDENT)
  543.         return format_s("'%s'", curtokcase);
  544.     if (!modulenotation) {
  545.         switch (tok) {
  546.             case TOK_MODULE:    return "UNIT";
  547.             case TOK_IMPORT:    return "USES";
  548.             case TOK_EXPORT:    return "INTERFACE";
  549.             case TOK_IMPLEMENT: return "IMPLEMENTATION";
  550.     default: break;
  551.         }
  552.     }
  553.     return toknames[(int) tok];
  554. }
  555. void expected(msg)
  556. char *msg;
  557. {
  558.     error(format_ss("Expected %s, found %s", msg, tok_name(curtok)));
  559. }
  560. void expecttok(tok)
  561. Token tok;
  562. {
  563.     if (curtok != tok)
  564.         expected(tok_name(tok));
  565. }
  566. void needtok(tok)
  567. Token tok;
  568. {
  569.     if (curtok != tok)
  570.         expected(tok_name(tok));
  571.     gettok();
  572. }
  573. int wexpected(msg)
  574. char *msg;
  575. {
  576.     warning(format_ss("Expected %s, found %s [227]", msg, tok_name(curtok)));
  577.     return 0;
  578. }
  579. int wexpecttok(tok)
  580. Token tok;
  581. {
  582.     if (curtok != tok)
  583.         return wexpected(tok_name(tok));
  584.     else
  585. return 1;
  586. }
  587. int wneedtok(tok)
  588. Token tok;
  589. {
  590.     if (wexpecttok(tok)) {
  591. gettok();
  592. return 1;
  593.     } else
  594. return 0;
  595. }
  596. void alreadydef(sym)
  597. Symbol *sym;
  598. {
  599.     warning(format_s("Symbol '%s' was already defined [220]", sym->name));
  600. }
  601. void undefsym(sym)
  602. Symbol *sym;
  603. {
  604.     warning(format_s("Symbol '%s' is not defined [221]", sym->name));
  605. }
  606. void symclass(sym)
  607. Symbol *sym;
  608. {
  609.     warning(format_s("Symbol '%s' is not of the appropriate class [222]", sym->name));
  610. }
  611. void badtypes()
  612. {
  613.     warning("Type mismatch [223]");
  614. }
  615. void valrange()
  616. {
  617.     warning("Value range error [224]");
  618. }
  619. void skipparens()
  620. {
  621.     Token begintok;
  622.     if (curtok == TOK_LPAR) {
  623.         gettok();
  624.         while (curtok != TOK_RPAR)
  625.             skipparens();
  626.     } else if (curtok == TOK_LBR) {
  627.         gettok();
  628.         while (curtok != TOK_RBR)
  629.             skipparens();
  630.     } else if (curtok == TOK_BEGIN || curtok == TOK_RECORD ||
  631.        curtok == TOK_CASE) {
  632. begintok = curtok;
  633.         gettok();
  634.         while (curtok != TOK_END)
  635.     if (curtok == TOK_CASE && begintok == TOK_RECORD)
  636. gettok();
  637.     else
  638. skipparens();
  639.     }
  640.     gettok();
  641. }
  642. void skiptotoken2(tok1, tok2)
  643. Token tok1, tok2;
  644. {
  645.     while (curtok != tok1 && curtok != tok2 &&
  646.    curtok != TOK_END && curtok != TOK_RPAR &&
  647.    curtok != TOK_RBR && curtok != TOK_EOF)
  648. skipparens();
  649. }
  650. void skippasttoken2(tok1, tok2)
  651. Token tok1, tok2;
  652. {
  653.     skiptotoken2(tok1, tok2);
  654.     if (curtok == tok1 || curtok == tok2)
  655. gettok();
  656. }
  657. void skippasttotoken(tok1, tok2)
  658. Token tok1, tok2;
  659. {
  660.     skiptotoken2(tok1, tok2);
  661.     if (curtok == tok1)
  662. gettok();
  663. }
  664. void skiptotoken(tok)
  665. Token tok;
  666. {
  667.     skiptotoken2(tok, tok);
  668. }
  669. void skippasttoken(tok)
  670. Token tok;
  671. {
  672.     skippasttoken2(tok, tok);
  673. }
  674. int skipopenparen()
  675. {
  676.     if (wneedtok(TOK_LPAR))
  677. return 1;
  678.     skiptotoken(TOK_SEMI);
  679.     return 0;
  680. }
  681. int skipcloseparen()
  682. {
  683.     if (curtok == TOK_COMMA)
  684. warning("Too many arguments for built-in routine [225]");
  685.     else
  686. if (wneedtok(TOK_RPAR))
  687.     return 1;
  688.     skippasttotoken(TOK_RPAR, TOK_SEMI);
  689.     return 0;
  690. }
  691. int skipcomma()
  692. {
  693.     if (curtok == TOK_RPAR)
  694. warning("Too few arguments for built-in routine [226]");
  695.     else
  696. if (wneedtok(TOK_COMMA))
  697.     return 1;
  698.     skippasttotoken(TOK_RPAR, TOK_SEMI);
  699.     return 0;
  700. }
  701. char *findaltname(name, num)
  702. char *name;
  703. int num;
  704. {
  705.     char *cp;
  706.     if (num <= 0)
  707.         return name;
  708.     if (num == 1 && *alternatename1)
  709.         return format_s(alternatename1, name);
  710.     if (num == 2 && *alternatename2)
  711.         return format_s(alternatename2, name);
  712.     if (*alternatename)
  713.         return format_sd(alternatename, name, num);
  714.     cp = name;
  715.     if (*alternatename1) {
  716.         while (--num >= 0)
  717.     cp = format_s(alternatename1, cp);
  718.     } else {
  719. while (--num >= 0)
  720.     cp = format_s("%s_", cp);
  721.     }
  722.     return cp;
  723. }
  724. Symbol *findsymbol_opt(name)
  725. char *name;
  726. {
  727.     register int i;
  728.     register unsigned int hash;
  729.     register char *cp;
  730.     register Symbol *sp;
  731.     hash = 0;
  732.     for (cp = name; *cp; cp++)
  733.         hash = hash*3 + *cp;
  734.     sp = symtab[hash % SYMHASHSIZE];
  735.     while (sp && (i = strcmp(sp->name, name)) != 0) {
  736.         if (i < 0)
  737.             sp = sp->left;
  738.         else
  739.             sp = sp->right;
  740.     }
  741.     return sp;
  742. }
  743. Symbol *findsymbol(name)
  744. char *name;
  745. {
  746.     register int i;
  747.     register unsigned int hash;
  748.     register char *cp;
  749.     register Symbol **prev, *sp;
  750.     hash = 0;
  751.     for (cp = name; *cp; cp++)
  752.         hash = hash*3 + *cp;
  753.     prev = symtab + (hash % SYMHASHSIZE);
  754.     while ((sp = *prev) != 0 &&
  755.            (i = strcmp(sp->name, name)) != 0) {
  756.         if (i < 0)
  757.             prev = &(sp->left);
  758.         else
  759.             prev = &(sp->right);
  760.     }
  761.     if (!sp) {
  762.         sp = ALLOCV(sizeof(Symbol) + strlen(name), Symbol, symbols);
  763.         sp->mbase = sp->fbase = NULL;
  764.         sp->left = sp->right = NULL;
  765.         strcpy(sp->name, name);
  766.         sp->flags = 0;
  767. sp->kwtok = TOK_NONE;
  768.         sp->symbolnames = NULL;
  769.         *prev = sp;
  770.     }
  771.     return sp;
  772. }
  773. void clearprogress()
  774. {
  775.     oldinfname = NULL;
  776. }
  777. void progress()
  778. {
  779.     char *ctxname;
  780.     int needrefr;
  781.     static int prevlen;
  782.     if (showprogress) {
  783.         if (!curctx || curctx == nullctx || curctx->kind == MK_MODULE ||
  784.             !strncmp(curctx->name, "__PROCPTR", 9) || blockkind == TOK_IMPORT)
  785.             ctxname = "";
  786.         else
  787.             ctxname = curctx->name;
  788.         needrefr = (inf_lnum & 15) == 0;
  789.         if (oldinfname != infname || oldctxname != ctxname) {
  790.     if (oldinfname != infname)
  791. prevlen = 60;
  792.             fprintf(stderr, "r%*s", prevlen + 2, "");
  793.             oldinfname = infname;
  794.             oldctxname = ctxname;
  795.             needrefr = 1;
  796.         }
  797.         if (needrefr) {
  798.             fprintf(stderr, "r%5d %s  %s", inf_lnum, infname, ctxname);
  799.     prevlen = 8 + strlen(infname) + strlen(ctxname);
  800.         } else {
  801.             fprintf(stderr, "r%5d", inf_lnum);
  802.     prevlen = 5;
  803. }
  804.     }
  805. }
  806. void getline()
  807. {
  808.     char *cp, *cp2;
  809.     switch (inputkind) {
  810.         case INP_FILE:
  811.         case INP_INCFILE:
  812.             inf_lnum++;
  813.     inf_ltotal++;
  814.             if (fgets(inbuf, 300, inf)) {
  815.                 cp = inbuf + strlen(inbuf);
  816.                 if (*inbuf && cp[-1] == 'n')
  817.                     cp[-1] = 0;
  818. if (inbuf[0] == '#' && inbuf[1] == ' ' && isdigit(inbuf[2])) {
  819.     cp = inbuf + 2;    /* in case input text came */
  820.     inf_lnum = 0;      /*  from the C preprocessor */
  821.     while (isdigit(*cp))
  822. inf_lnum = inf_lnum*10 + (*cp++) - '0';
  823.     inf_lnum--;
  824.     while (isspace(*cp)) cp++;
  825.     if (*cp == '"' && (cp2 = my_strchr(cp+1, '"')) != NULL) {
  826. cp++;
  827. infname = stralloc(cp);
  828. infname[cp2 - cp] = 0;
  829.     }
  830.     getline();
  831.     return;
  832. }
  833. if (copysource && *inbuf) {
  834.     start_source();
  835.     fprintf(outf, "%sn", inbuf);
  836. }
  837.                 if (keepingstrlist) {
  838.                     strlist_append(keepingstrlist, inbuf)->value = inf_lnum;
  839.                 }
  840.                 if (showprogress && inf_lnum % showprogress == 0)
  841.                     progress();
  842.             } else {
  843.                 if (showprogress)
  844.                     fprintf(stderr, "n");
  845.                 if (inputkind == INP_INCFILE) {
  846.                     pop_input();
  847.                     getline();
  848.                 } else
  849.                     strcpy(inbuf, "01");
  850.             }
  851.             break;
  852.         case INP_STRLIST:
  853.             if (instrlist) {
  854.                 strcpy(inbuf, instrlist->s);
  855.                 if (instrlist->value)
  856.                     inf_lnum = instrlist->value;
  857.                 else
  858.                     inf_lnum++;
  859.                 instrlist = instrlist->next;
  860.             } else
  861.                 strcpy(inbuf, "01");
  862.             break;
  863.     }
  864.     inbufptr = inbuf;
  865.     inbufindent = 0;
  866. }
  867. Static void push_input()
  868. {
  869.     struct inprec *inp;
  870.     inp = ALLOC(1, struct inprec, inprecs);
  871.     inp->kind = inputkind;
  872.     inp->fname = infname;
  873.     inp->lnum = inf_lnum;
  874.     inp->filep = inf;
  875.     inp->strlistp = instrlist;
  876.     inp->inbufptr = stralloc(inbufptr);
  877.     inp->curtok = curtok;
  878.     inp->curtoksym = curtoksym;
  879.     inp->curtokmeaning = curtokmeaning;
  880.     inp->saveblockkind = TOK_NIL;
  881.     inp->next = topinput;
  882.     topinput = inp;
  883.     inbufptr = inbuf + strlen(inbuf);
  884. }
  885. void push_input_file(fp, fname, isinclude)
  886. FILE *fp;
  887. char *fname;
  888. int isinclude;
  889. {
  890.     push_input();
  891.     inputkind = (isinclude == 1) ? INP_INCFILE : INP_FILE;
  892.     inf = fp;
  893.     inf_lnum = 0;
  894.     infname = fname;
  895.     *inbuf = 0;
  896.     inbufptr = inbuf;
  897.     topinput->tempopts = tempoptionlist;
  898.     tempoptionlist = NULL;
  899.     if (isinclude != 2)
  900.         gettok();
  901. }
  902. void include_as_import()
  903. {
  904.     if (inputkind == INP_INCFILE) {
  905. if (topinput->saveblockkind == TOK_NIL)
  906.     topinput->saveblockkind = blockkind;
  907. blockkind = TOK_IMPORT;
  908.     } else
  909. warning(format_s("%s ignored except in include files [228]",
  910.  interfacecomment));
  911. }
  912. void push_input_strlist(sp, fname)
  913. Strlist *sp;
  914. char *fname;
  915. {
  916.     push_input();
  917.     inputkind = INP_STRLIST;
  918.     instrlist = sp;
  919.     if (fname) {
  920.         infname = fname;
  921.         inf_lnum = 0;
  922.     } else
  923.         inf_lnum--;     /* adjust for extra getline() */
  924.     *inbuf = 0;
  925.     inbufptr = inbuf;
  926.     gettok();
  927. }
  928. void pop_input()
  929. {
  930.     struct inprec *inp;
  931.     if (inputkind == INP_FILE || inputkind == INP_INCFILE) {
  932. while (tempoptionlist) {
  933.     undooption(tempoptionlist->value, tempoptionlist->s);
  934.     strlist_eat(&tempoptionlist);
  935. }
  936. tempoptionlist = topinput->tempopts;
  937. if (inf)
  938.     fclose(inf);
  939.     }
  940.     inp = topinput;
  941.     topinput = inp->next;
  942.     if (inp->saveblockkind != TOK_NIL)
  943. blockkind = inp->saveblockkind;
  944.     inputkind = inp->kind;
  945.     infname = inp->fname;
  946.     inf_lnum = inp->lnum;
  947.     inf = inp->filep;
  948.     curtok = inp->curtok;
  949.     curtoksym = inp->curtoksym;
  950.     curtokmeaning = inp->curtokmeaning;
  951.     strcpy(inbuf, inp->inbufptr);
  952.     FREE(inp->inbufptr);
  953.     inbufptr = inbuf;
  954.     instrlist = inp->strlistp;
  955.     FREE(inp);
  956. }
  957. int undooption(i, name)
  958. int i;
  959. char *name;
  960. {
  961.     char kind = rctable[i].kind;
  962.     switch (kind) {
  963.         case 'S':
  964. case 'B':
  965.     if (rcprevvalues[i]) {
  966.                 *((short *)rctable[i].ptr) = rcprevvalues[i]->value;
  967.                 strlist_eat(&rcprevvalues[i]);
  968.                 return 1;
  969.             }
  970.             break;
  971.         case 'I':
  972.         case 'D':
  973.             if (rcprevvalues[i]) {
  974.                 *((int *)rctable[i].ptr) = rcprevvalues[i]->value;
  975.                 strlist_eat(&rcprevvalues[i]);
  976.                 return 1;
  977.             }
  978.             break;
  979.         case 'L':
  980.             if (rcprevvalues[i]) {
  981.                 *((long *)rctable[i].ptr) = rcprevvalues[i]->value;
  982.                 strlist_eat(&rcprevvalues[i]);
  983.                 return 1;
  984.             }
  985.             break;
  986. case 'R':
  987.     if (rcprevvalues[i]) {
  988. *((double *)rctable[i].ptr) = atof(rcprevvalues[i]->s);
  989. strlist_eat(&rcprevvalues[i]);
  990. return 1;
  991.     }
  992.     break;
  993.         case 'C':
  994.         case 'U':
  995.             if (rcprevvalues[i]) {
  996.                 strcpy((char *)rctable[i].ptr, rcprevvalues[i]->s);
  997.                 strlist_eat(&rcprevvalues[i]);
  998.                 return 1;
  999.             }
  1000.             break;
  1001.         case 'A':
  1002.             strlist_remove((Strlist **)rctable[i].ptr, name);
  1003.             return 1;
  1004.         case 'X':
  1005.             if (rctable[i].def == 1) {
  1006.                 strlist_remove((Strlist **)rctable[i].ptr, name);
  1007.                 return 1;
  1008.             }
  1009.             break;
  1010.     }
  1011.     return 0;
  1012. }
  1013. void badinclude()
  1014. {
  1015.     warning("Can't handle an "include" directive here [229]");
  1016.     inputkind = INP_INCFILE;     /* expand it in-line */
  1017.     gettok();
  1018. }
  1019. int handle_include(fn)
  1020. char *fn;
  1021. {
  1022.     FILE *fp = NULL;
  1023.     Strlist *sl;
  1024.     for (sl = includedirs; sl; sl = sl->next) {
  1025. fp = fopen(format_s(sl->s, fn), "r");
  1026. if (fp) {
  1027.     fn = stralloc(format_s(sl->s, fn));
  1028.     break;
  1029. }
  1030.     }
  1031.     if (!fp) {
  1032.         perror(fn);
  1033.         warning(format_s("Could not open include file %s [230]", fn));
  1034.         return 0;
  1035.     } else {
  1036.         if (!quietmode && !showprogress)
  1037.     if (outf == stdout)
  1038. fprintf(stderr, "Reading include file "%s"n", fn);
  1039.     else
  1040. printf("Reading include file "%s"n", fn);
  1041. if (verbose)
  1042.     fprintf(logf, "Reading include file "%s"n", fn);
  1043.         if (expandincludes == 0) {
  1044.             push_input_file(fp, fn, 2);
  1045.             curtok = TOK_INCLUDE;
  1046.             strcpy(curtokbuf, fn);
  1047.         } else {
  1048.             push_input_file(fp, fn, 1);
  1049.         }
  1050.         return 1;
  1051.     }
  1052. }
  1053. int turbo_directive(closing, after)
  1054. char *closing, *after;
  1055. {
  1056.     char *cp, *cp2;
  1057.     int i, result;
  1058.     if (!strcincmp(inbufptr, "$double", 7)) {
  1059. cp = inbufptr + 7;
  1060. while (isspace(*cp)) cp++;
  1061. if (cp == closing) {
  1062.     inbufptr = after;
  1063.     doublereals = 1;
  1064.     return 1;
  1065. }
  1066.     } else if (!strcincmp(inbufptr, "$nodouble", 9)) {
  1067. cp = inbufptr + 9;
  1068. while (isspace(*cp)) cp++;
  1069. if (cp == closing) {
  1070.     inbufptr = after;
  1071.     doublereals = 0;
  1072.     return 1;
  1073. }
  1074.     }
  1075.     switch (inbufptr[2]) {
  1076.         case '+':
  1077.         case '-':
  1078.             result = 1;
  1079.             cp = inbufptr + 1;
  1080.             for (;;) {
  1081.                 if (!isalpha(*cp++))
  1082.                     return 0;
  1083.                 if (*cp != '+' && *cp != '-')
  1084.                     return 0;
  1085.                 if (++cp == closing)
  1086.                     break;
  1087.                 if (*cp++ != ',')
  1088.                     return 0;
  1089.             }
  1090.             cp = inbufptr + 1;
  1091.             do {
  1092.                 switch (*cp++) {
  1093.                     case 'b':
  1094.                     case 'B':
  1095.                         if (shortcircuit < 0 && which_lang != LANG_MPW)
  1096.                             partial_eval_flag = (*cp == '-');
  1097.                         break;
  1098.                     case 'i':
  1099.                     case 'I':
  1100.                         iocheck_flag = (*cp == '+');
  1101.                         break;
  1102.                     case 'r':
  1103.                     case 'R':
  1104.                         if (*cp == '+') {
  1105.                             if (!range_flag)
  1106.                                 note("Range checking is ON [216]");
  1107.                             range_flag = 1;
  1108.                         } else {
  1109.                             if (range_flag)
  1110.                                 note("Range checking is OFF [216]");
  1111.                             range_flag = 0;
  1112.                         }
  1113.                         break;
  1114.                     case 's':
  1115.                     case 'S':
  1116.                         if (*cp == '+') {
  1117.                             if (!stackcheck_flag)
  1118.                                 note("Stack checking is ON [217]");
  1119.                             stackcheck_flag = 1;
  1120.                         } else {
  1121.                             if (stackcheck_flag)
  1122.                                 note("Stack checking is OFF [217]");
  1123.                             stackcheck_flag = 0;
  1124.                         }
  1125.                         break;
  1126.                     default:
  1127.                         result = 0;
  1128.                         break;
  1129.                 }
  1130.                 cp++;
  1131.             } while (*cp++ == ',');
  1132.             if (result)
  1133.                 inbufptr = after;
  1134.             return result;
  1135. case 'c':
  1136. case 'C':
  1137.     if (toupper(inbufptr[1]) == 'S' &&
  1138. (inbufptr[3] == '+' || inbufptr[3] == '-') &&
  1139. inbufptr + 4 == closing) {
  1140. if (shortcircuit < 0)
  1141.     partial_eval_flag = (inbufptr[3] == '+');
  1142. inbufptr = after;
  1143. return 1;
  1144.     }
  1145.     return 0;
  1146.         case ' ':
  1147.             switch (inbufptr[1]) {
  1148.                 case 'i':
  1149.                 case 'I':
  1150.                     if (skipping_module)
  1151.                         break;
  1152.                     cp = inbufptr + 3;
  1153.                     while (isspace(*cp)) cp++;
  1154.                     cp2 = cp;
  1155.                     i = 0;
  1156.                     while (*cp2 && cp2 != closing)
  1157.                         i++, cp2++;
  1158.                     if (cp2 != closing)
  1159.                         return 0;
  1160.                     while (isspace(cp[i-1]))
  1161.                         if (--i <= 0)
  1162.                             return 0;
  1163.                     inbufptr = after;
  1164.                     cp2 = ALLOC(i + 1, char, strings);
  1165.                     strncpy(cp2, cp, i);
  1166.                     cp2[i] = 0;
  1167.                     if (handle_include(cp2))
  1168. return 2;
  1169.     break;
  1170. case 's':
  1171. case 'S':
  1172.     cp = inbufptr + 3;
  1173.     outsection(minorspace);
  1174.     if (cp == closing) {
  1175. output("#undef __SEG__n");
  1176.     } else {
  1177. output("#define __SEG__ ");
  1178. while (*cp && cp != closing)
  1179.     cp++;
  1180. if (*cp) {
  1181.     i = *cp;
  1182.     *cp = 0;
  1183.     output(inbufptr + 3);
  1184.     *cp = i;
  1185. }
  1186. output("n");
  1187.     }
  1188.     outsection(minorspace);
  1189.     inbufptr = after;
  1190.     return 1;
  1191.             }
  1192.             return 0;
  1193. case '}':
  1194. case '*':
  1195.     if (inbufptr + 2 == closing) {
  1196. switch (inbufptr[1]) {
  1197.     
  1198.   case 's':
  1199.   case 'S':
  1200.     outsection(minorspace);
  1201.     output("#undef __SEG__n");
  1202.     outsection(minorspace);
  1203.     inbufptr = after;
  1204.     return 1;
  1205. }
  1206.     }
  1207.     return 0;
  1208.         case 'f':   /* $ifdef etc. */
  1209.         case 'F':
  1210.             if (toupper(inbufptr[1]) == 'I' &&
  1211.                 ((toupper(inbufptr[3]) == 'O' &&
  1212.                   toupper(inbufptr[4]) == 'P' &&
  1213.                   toupper(inbufptr[5]) == 'T') ||
  1214.                  (toupper(inbufptr[3]) == 'D' &&
  1215.                   toupper(inbufptr[4]) == 'E' &&
  1216.                   toupper(inbufptr[5]) == 'F') ||
  1217.                  (toupper(inbufptr[3]) == 'N' &&
  1218.                   toupper(inbufptr[4]) == 'D' &&
  1219.                   toupper(inbufptr[5]) == 'E' &&
  1220.                   toupper(inbufptr[6]) == 'F'))) {
  1221.                 note("Turbo Pascal conditional compilation directive was ignored [218]");
  1222.             }
  1223.             return 0;
  1224.     }
  1225.     return 0;
  1226. }
  1227. extern Strlist *addmacros;
  1228. void defmacro(name, kind, fname, lnum)
  1229. char *name, *fname;
  1230. long kind;
  1231. int lnum;
  1232. {
  1233.     Strlist *defsl, *sl, *sl2;
  1234.     Symbol *sym, *sym2;
  1235.     Meaning *mp;
  1236.     Expr *ex;
  1237.     defsl = NULL;
  1238.     sl = strlist_append(&defsl, name);
  1239.     C_lex++;
  1240.     if (fname && !strcmp(fname, "<macro>") && curtok == TOK_IDENT)
  1241.         fname = curtoksym->name;
  1242.     push_input_strlist(defsl, fname);
  1243.     if (fname)
  1244.         inf_lnum = lnum;
  1245.     switch (kind) {
  1246.         case MAC_VAR:
  1247.             if (!wexpecttok(TOK_IDENT))
  1248. break;
  1249.     for (mp = curtoksym->mbase; mp; mp = mp->snext) {
  1250. if (mp->kind == MK_VAR)
  1251.     warning(format_s("VarMacro must be defined before declaration of variable %s [231]", curtokcase));
  1252.     }
  1253.             sl = strlist_append(&varmacros, curtoksym->name);
  1254.             gettok();
  1255.             if (!wneedtok(TOK_EQ))
  1256. break;
  1257.             sl->value = (long)pc_expr();
  1258.             break;
  1259.         case MAC_CONST:
  1260.             if (!wexpecttok(TOK_IDENT))
  1261. break;
  1262.     for (mp = curtoksym->mbase; mp; mp = mp->snext) {
  1263. if (mp->kind == MK_CONST)
  1264.     warning(format_s("ConstMacro must be defined before declaration of variable %s [232]", curtokcase));
  1265.     }
  1266.             sl = strlist_append(&constmacros, curtoksym->name);
  1267.             gettok();
  1268.             if (!wneedtok(TOK_EQ))
  1269. break;
  1270.             sl->value = (long)pc_expr();
  1271.             break;
  1272.         case MAC_FIELD:
  1273.             if (!wexpecttok(TOK_IDENT))
  1274. break;
  1275.             sym = curtoksym;
  1276.             gettok();
  1277.             if (!wneedtok(TOK_DOT))
  1278. break;
  1279.             if (!wexpecttok(TOK_IDENT))
  1280. break;
  1281.     sym2 = curtoksym;
  1282.             gettok();
  1283.     if (!wneedtok(TOK_EQ))
  1284. break;
  1285.             funcmacroargs = NULL;
  1286.             sym->flags |= FMACREC;
  1287.             ex = pc_expr();
  1288.             sym->flags &= ~FMACREC;
  1289.     for (mp = sym2->fbase; mp; mp = mp->snext) {
  1290. if (mp->rectype && mp->rectype->meaning &&
  1291.     mp->rectype->meaning->sym == sym)
  1292.     break;
  1293.     }
  1294.     if (mp) {
  1295. mp->constdefn = ex;
  1296.     } else {
  1297. sl = strlist_append(&fieldmacros, 
  1298.     format_ss("%s.%s", sym->name, sym2->name));
  1299. sl->value = (long)ex;
  1300.     }
  1301.             break;
  1302.         case MAC_FUNC:
  1303.             if (!wexpecttok(TOK_IDENT))
  1304. break;
  1305.             sym = curtoksym;
  1306.             if (sym->mbase &&
  1307. (sym->mbase->kind == MK_FUNCTION ||
  1308.  sym->mbase->kind == MK_SPECIAL))
  1309.                 sl = NULL;
  1310.             else
  1311.                 sl = strlist_append(&funcmacros, sym->name);
  1312.             gettok();
  1313.             funcmacroargs = NULL;
  1314.             if (curtok == TOK_LPAR) {
  1315.                 do {
  1316.                     gettok();
  1317.     if (curtok == TOK_RPAR && !funcmacroargs)
  1318. break;
  1319.                     if (!wexpecttok(TOK_IDENT)) {
  1320. skiptotoken2(TOK_COMMA, TOK_RPAR);
  1321. continue;
  1322.     }
  1323.                     sl2 = strlist_append(&funcmacroargs, curtoksym->name);
  1324.                     sl2->value = (long)curtoksym;
  1325.                     curtoksym->flags |= FMACREC;
  1326.                     gettok();
  1327.                 } while (curtok == TOK_COMMA);
  1328.                 if (!wneedtok(TOK_RPAR))
  1329.     skippasttotoken(TOK_RPAR, TOK_EQ);
  1330.             }
  1331.             if (!wneedtok(TOK_EQ))
  1332. break;
  1333.             if (sl)
  1334.                 sl->value = (long)pc_expr();
  1335.             else
  1336.                 sym->mbase->constdefn = pc_expr();
  1337.             for (sl2 = funcmacroargs; sl2; sl2 = sl2->next) {
  1338.                 sym2 = (Symbol *)sl2->value;
  1339.                 sym2->flags &= ~FMACREC;
  1340.             }
  1341.             strlist_empty(&funcmacroargs);
  1342.             break;
  1343.     }
  1344.     if (curtok != TOK_EOF)
  1345.         warning(format_s("Junk (%s) at end of macro definition [233]", tok_name(curtok)));
  1346.     pop_input();
  1347.     C_lex--;
  1348.     strlist_empty(&defsl);
  1349. }
  1350. void check_unused_macros()
  1351. {
  1352.     Strlist *sl;
  1353.     if (warnmacros) {
  1354.         for (sl = varmacros; sl; sl = sl->next)
  1355.             warning(format_s("VarMacro %s was never used [234]", sl->s));
  1356.         for (sl = constmacros; sl; sl = sl->next)
  1357.             warning(format_s("ConstMacro %s was never used [234]", sl->s));
  1358.         for (sl = fieldmacros; sl; sl = sl->next)
  1359.             warning(format_s("FieldMacro %s was never used [234]", sl->s));
  1360.         for (sl = funcmacros; sl; sl = sl->next)
  1361.             warning(format_s("FuncMacro %s was never used [234]", sl->s));
  1362.     }
  1363. }
  1364. #define skipspc(cp)   while (isspace(*cp)) cp++
  1365. Static int parsecomment(p2c_only, starparen)
  1366. int p2c_only, starparen;
  1367. {
  1368.     char namebuf[302];
  1369.     char *cp, *cp2 = namebuf, *closing, *after;
  1370.     char kind, chgmode, upcflag;
  1371.     long val, oldval, sign;
  1372.     double dval;
  1373.     int i, tempopt, hassign;
  1374.     Strlist *sp;
  1375.     Symbol *sym;
  1376.     if (if_flag)
  1377.         return 0;
  1378.     if (!p2c_only) {
  1379.         if (!strncmp(inbufptr, noskipcomment, strlen(noskipcomment)) &&
  1380.      *noskipcomment) {
  1381.             inbufptr += strlen(noskipcomment);
  1382.     if (skipflag < 0) {
  1383. curtok = TOK_ENDIF;
  1384. skipflag = 1;
  1385. return 2;
  1386.     }
  1387.     skipflag = 1;
  1388.             return 1;
  1389.         }
  1390.     }
  1391.     closing = inbufptr;
  1392.     while (*closing && (starparen
  1393. ? (closing[0] != '*' || closing[1] != ')')
  1394. : (closing[0] != '}')))
  1395. closing++;
  1396.     if (!*closing)
  1397. return 0;
  1398.     after = closing + (starparen ? 2 : 1);
  1399.     cp = inbufptr;
  1400.     while (cp < closing && (*cp != '#' || cp[1] != '#'))
  1401. cp++;    /* Ignore comments */
  1402.     if (cp < closing) {
  1403. while (isspace(cp[-1]))
  1404.     cp--;
  1405. *cp = '#';   /* avoid skipping spaces past closing! */
  1406. closing = cp;
  1407.     }
  1408.     if (!p2c_only) {
  1409.         if (!strncmp(inbufptr, "DUMP-SYMBOLS", 12) &&
  1410.      closing == inbufptr + 12) {
  1411.             wrapup();
  1412.             inbufptr = after;
  1413.             return 1;
  1414.         }
  1415.         if (!strncmp(inbufptr, fixedcomment, strlen(fixedcomment)) &&
  1416.      *fixedcomment &&
  1417.      inbufptr + strlen(fixedcomment) == closing) {
  1418.             fixedflag++;
  1419.             inbufptr = after;
  1420.             return 1;
  1421.         }
  1422.         if (!strncmp(inbufptr, permanentcomment, strlen(permanentcomment)) &&
  1423.      *permanentcomment &&
  1424.      inbufptr + strlen(permanentcomment) == closing) {
  1425.             permflag = 1;
  1426.             inbufptr = after;
  1427.             return 1;
  1428.         }
  1429.         if (!strncmp(inbufptr, interfacecomment, strlen(interfacecomment)) &&
  1430.      *interfacecomment &&
  1431.      inbufptr + strlen(interfacecomment) == closing) {
  1432.             inbufptr = after;
  1433.     curtok = TOK_INTFONLY;
  1434.             return 2;
  1435.         }
  1436.         if (!strncmp(inbufptr, skipcomment, strlen(skipcomment)) &&
  1437.      *skipcomment &&
  1438.      inbufptr + strlen(skipcomment) == closing) {
  1439.             inbufptr = after;
  1440.     skipflag = -1;
  1441.     skipping_module++;    /* eat comments in skipped portion */
  1442.     do {
  1443. gettok();
  1444.     } while (curtok != TOK_ENDIF);
  1445.     skipping_module--;
  1446.             return 1;
  1447.         }
  1448. if (!strncmp(inbufptr, signedcomment, strlen(signedcomment)) &&
  1449.      *signedcomment && !p2c_only &&
  1450.      inbufptr + strlen(signedcomment) == closing) {
  1451.     inbufptr = after;
  1452.     gettok();
  1453.     if (curtok == TOK_IDENT && curtokmeaning &&
  1454. curtokmeaning->kind == MK_TYPE &&
  1455. curtokmeaning->type == tp_char) {
  1456. curtokmeaning = mp_schar;
  1457.     } else
  1458. warning("{SIGNED} applied to type other than CHAR [314]");
  1459.     return 2;
  1460. }
  1461. if (!strncmp(inbufptr, unsignedcomment, strlen(unsignedcomment)) &&
  1462.      *unsignedcomment && !p2c_only &&
  1463.      inbufptr + strlen(unsignedcomment) == closing) {
  1464.     inbufptr = after;
  1465.     gettok();
  1466.     if (curtok == TOK_IDENT && curtokmeaning &&
  1467. curtokmeaning->kind == MK_TYPE &&
  1468. curtokmeaning->type == tp_char) {
  1469. curtokmeaning = mp_uchar;
  1470.     } else if (curtok == TOK_IDENT && curtokmeaning &&
  1471.        curtokmeaning->kind == MK_TYPE &&
  1472.        curtokmeaning->type == tp_integer) {
  1473. curtokmeaning = mp_unsigned;
  1474.     } else if (curtok == TOK_IDENT && curtokmeaning &&
  1475.        curtokmeaning->kind == MK_TYPE &&
  1476.        curtokmeaning->type == tp_int) {
  1477. curtokmeaning = mp_uint;
  1478.     } else
  1479. warning("{UNSIGNED} applied to type other than CHAR or INTEGER [313]");
  1480.     return 2;
  1481. }
  1482.         if (*inbufptr == '$') {
  1483.             i = turbo_directive(closing, after);
  1484.             if (i)
  1485.                 return i;
  1486.         }
  1487.     }
  1488.     tempopt = 0;
  1489.     cp = inbufptr;
  1490.     if (*cp == '*') {
  1491.         cp++;
  1492.         tempopt = 1;
  1493.     }
  1494.     if (!isalpha(*cp))
  1495.         return 0;
  1496.     while ((isalnum(*cp) || *cp == '_') && cp2 < namebuf+300)
  1497.         *cp2++ = toupper(*cp++);
  1498.     *cp2 = 0;
  1499.     i = numparams;
  1500.     while (--i >= 0 && strcmp(rctable[i].name, namebuf)) ;
  1501.     if (i < 0)
  1502.         return 0;
  1503.     kind = rctable[i].kind;
  1504.     chgmode = rctable[i].chgmode;
  1505.     if (chgmode == ' ')    /* allowed in p2crc only */
  1506.         return 0;
  1507.     if (chgmode == 'T' && lex_initialized) {
  1508.         if (cp == closing || *cp == '=' || *cp == '+' || *cp == '-')
  1509.             warning(format_s("%s works only at top of program [235]",
  1510.                              rctable[i].name));
  1511.     }
  1512.     if (cp == closing) {
  1513.         if (kind == 'S' || kind == 'I' || kind == 'D' || kind == 'L' ||
  1514.     kind == 'R' || kind == 'B' || kind == 'C' || kind == 'U') {
  1515.             undooption(i, "");
  1516.             inbufptr = after;
  1517.             return 1;
  1518.         }
  1519.     }
  1520.     switch (kind) {
  1521.         case 'S':
  1522.         case 'I':
  1523.         case 'L':
  1524.             val = oldval = (kind == 'L') ? *(( long *)rctable[i].ptr) :
  1525.                            (kind == 'S') ? *((short *)rctable[i].ptr) :
  1526.                                            *((  int *)rctable[i].ptr);
  1527.             switch (*cp) {
  1528.                 case '=':
  1529.                     skipspc(cp);
  1530.     hassign = (*++cp == '-' || *cp == '+');
  1531.                     sign = (*cp == '-') ? -1 : 1;
  1532.     cp += hassign;
  1533.                     if (isdigit(*cp)) {
  1534.                         val = 0;
  1535.                         while (isdigit(*cp))
  1536.                             val = val * 10 + (*cp++) - '0';
  1537.                         val *= sign;
  1538. if (kind == 'D' && !hassign)
  1539.     val += 10000;
  1540.                     } else if (toupper(cp[0]) == 'D' &&
  1541.                                toupper(cp[1]) == 'E' &&
  1542.                                toupper(cp[2]) == 'F') {
  1543.                         val = rctable[i].def;
  1544.                         cp += 3;
  1545.                     }
  1546.                     break;
  1547.                 case '+':
  1548.                 case '-':
  1549.                     if (chgmode != 'R')
  1550.                         return 0;
  1551.                     for (;;) {
  1552.                         if (*cp == '+')
  1553.                             val++;
  1554.                         else if (*cp == '-')
  1555.                             val--;
  1556.                         else
  1557.                             break;
  1558.                         cp++;
  1559.                     }
  1560.                     break;
  1561.             }
  1562.             skipspc(cp);
  1563.             if (cp != closing)
  1564.                 return 0;
  1565.             strlist_insert(&rcprevvalues[i], "")->value = oldval;
  1566.             if (tempopt)
  1567.                 strlist_insert(&tempoptionlist, "")->value = i;
  1568.             if (kind == 'L')
  1569.                 *((long *)rctable[i].ptr) = val;
  1570.             else if (kind == 'S')
  1571.                 *((short *)rctable[i].ptr) = val;
  1572.             else
  1573.                 *((int *)rctable[i].ptr) = val;
  1574.             inbufptr = after;
  1575.             return 1;
  1576. case 'D':
  1577.             val = oldval = *((int *)rctable[i].ptr);
  1578.     if (*cp++ != '=')
  1579. return 0;
  1580.     skipspc(cp);
  1581.     if (toupper(cp[0]) == 'D' &&
  1582. toupper(cp[1]) == 'E' &&
  1583. toupper(cp[2]) == 'F') {
  1584. val = rctable[i].def;
  1585. cp += 3;
  1586.     } else {
  1587.                 cp2 = namebuf;
  1588.                 while (*cp && cp != closing && !isspace(*cp))
  1589.                     *cp2++ = *cp++;
  1590. *cp2 = 0;
  1591. val = parsedelta(namebuf, -1);
  1592. if (!val)
  1593.     return 0;
  1594.     }
  1595.     skipspc(cp);
  1596.             if (cp != closing)
  1597.                 return 0;
  1598.             strlist_insert(&rcprevvalues[i], "")->value = oldval;
  1599.             if (tempopt)
  1600.                 strlist_insert(&tempoptionlist, "")->value = i;
  1601.             *((int *)rctable[i].ptr) = val;
  1602.             inbufptr = after;
  1603.             return 1;
  1604.         case 'R':
  1605.     if (*cp++ != '=')
  1606. return 0;
  1607.     skipspc(cp);
  1608.     if (toupper(cp[0]) == 'D' &&
  1609. toupper(cp[1]) == 'E' &&
  1610. toupper(cp[2]) == 'F') {
  1611. dval = rctable[i].def / 100.0;
  1612. cp += 3;
  1613.     } else {
  1614. cp2 = cp;
  1615. while (isdigit(*cp) || *cp == '-' || *cp == '+' ||
  1616.        *cp == '.' || toupper(*cp) == 'E')
  1617.     cp++;
  1618. if (cp == cp2)
  1619.     return 0;
  1620. dval = atof(cp2);
  1621.     }
  1622.     skipspc(cp);
  1623.     if (cp != closing)
  1624. return 0;
  1625.     sprintf(namebuf, "%g", *((double *)rctable[i].ptr));
  1626.             strlist_insert(&rcprevvalues[i], namebuf);
  1627.             if (tempopt)
  1628.                 strlist_insert(&tempoptionlist, namebuf)->value = i;
  1629.     *((double *)rctable[i].ptr) = dval;
  1630.             inbufptr = after;
  1631.             return 1;
  1632.         case 'B':
  1633.     if (*cp++ != '=')
  1634. return 0;
  1635.     skipspc(cp);
  1636.     if (toupper(cp[0]) == 'D' &&
  1637. toupper(cp[1]) == 'E' &&
  1638. toupper(cp[2]) == 'F') {
  1639. val = rctable[i].def;
  1640. cp += 3;
  1641.     } else {
  1642. val = parse_breakstr(cp);
  1643. while (*cp && cp != closing && !isspace(*cp))
  1644.     cp++;
  1645.     }
  1646.     skipspc(cp);
  1647.     if (cp != closing || val == -1)
  1648. return 0;
  1649.             strlist_insert(&rcprevvalues[i], "")->value =
  1650. *((short *)rctable[i].ptr);
  1651.             if (tempopt)
  1652.                 strlist_insert(&tempoptionlist, "")->value = i;
  1653.     *((short *)rctable[i].ptr) = val;
  1654.             inbufptr = after;
  1655.             return 1;
  1656.         case 'C':
  1657.         case 'U':
  1658.             if (*cp == '=') {
  1659.                 cp++;
  1660.                 skipspc(cp);
  1661.                 for (cp2 = cp; cp2 != closing && !isspace(*cp2); cp2++)
  1662.                     if (!*cp2 || cp2-cp >= rctable[i].def)
  1663.                         return 0;
  1664.                 cp2 = (char *)rctable[i].ptr;
  1665.                 sp = strlist_insert(&rcprevvalues[i], cp2);
  1666.                 if (tempopt)
  1667.                     strlist_insert(&tempoptionlist, "")->value = i;
  1668.                 while (cp != closing && !isspace(*cp2))
  1669.                     *cp2++ = *cp++;
  1670.                 *cp2 = 0;
  1671.                 if (kind == 'U')
  1672.                     upc((char *)rctable[i].ptr);
  1673.                 skipspc(cp);
  1674.                 if (cp != closing)
  1675.                     return 0;
  1676.                 inbufptr = after;
  1677.                 if (!strcmp(rctable[i].name, "LANGUAGE") &&
  1678.                     !strcmp((char *)rctable[i].ptr, "MODCAL"))
  1679.                     sysprog_flag |= 2;
  1680.                 return 1;
  1681.             }
  1682.             return 0;
  1683.         case 'F':
  1684.         case 'G':
  1685.             if (*cp == '=' || *cp == '+' || *cp == '-') {
  1686.                 upcflag = (kind == 'F' && !pascalcasesens);
  1687.                 chgmode = *cp++;
  1688.                 skipspc(cp);
  1689.                 cp2 = namebuf;
  1690.                 while (isalnum(*cp) || *cp == '_' || *cp == '$' || *cp == '%')
  1691.                     *cp2++ = *cp++;
  1692.                 *cp2++ = 0;
  1693. if (!*namebuf)
  1694.     return 0;
  1695.                 skipspc(cp);
  1696.                 if (cp != closing)
  1697.                     return 0;
  1698.                 if (upcflag)
  1699.                     upc(namebuf);
  1700.                 sym = findsymbol(namebuf);
  1701. if (rctable[i].def & FUNCBREAK)
  1702.     sym->flags &= ~FUNCBREAK;
  1703.                 if (chgmode == '-')
  1704.                     sym->flags &= ~rctable[i].def;
  1705.                 else
  1706.                     sym->flags |= rctable[i].def;
  1707.                 inbufptr = after;
  1708.                 return 1;
  1709.            }
  1710.            return 0;
  1711.         case 'A':
  1712.             if (*cp == '=' || *cp == '+' || *cp == '-') {
  1713.                 chgmode = *cp++;
  1714.                 skipspc(cp);
  1715.                 cp2 = namebuf;
  1716.                 while (cp != closing && !isspace(*cp) && *cp)
  1717.                     *cp2++ = *cp++;
  1718.                 *cp2++ = 0;
  1719.                 skipspc(cp);
  1720.                 if (cp != closing)
  1721.                     return 0;
  1722.                 if (chgmode != '+')
  1723.                     strlist_remove((Strlist **)rctable[i].ptr, namebuf);
  1724.                 if (chgmode != '-')
  1725.                     sp = strlist_insert((Strlist **)rctable[i].ptr, namebuf);
  1726.                 if (tempopt)
  1727.                     strlist_insert(&tempoptionlist, namebuf)->value = i;
  1728.                 inbufptr = after;
  1729.                 return 1;
  1730.             }
  1731.             return 0;
  1732.         case 'M':
  1733.             if (!isspace(*cp))
  1734.                 return 0;
  1735.             skipspc(cp);
  1736.             if (!isalpha(*cp))
  1737.                 return 0;
  1738.             for (cp2 = cp; *cp2 && cp2 != closing; cp2++) ;
  1739.             if (cp2 > cp && cp2 == closing) {
  1740.                 inbufptr = after;
  1741.                 cp2 = format_ds("%.*s", (int)(cp2-cp), cp);
  1742.                 if (tp_integer != NULL) {
  1743.                     defmacro(cp2, rctable[i].def, NULL, 0);
  1744.                 } else {
  1745.                     sp = strlist_append(&addmacros, cp2);
  1746.                     sp->value = rctable[i].def;
  1747.                 }
  1748.                 return 1;
  1749.             }
  1750.             return 0;
  1751.         case 'X':
  1752.             switch (rctable[i].def) {
  1753.                 case 1:     /* strlist with string values */
  1754.                     if (!isspace(*cp) && *cp != '=' && 
  1755.                         *cp != '+' && *cp != '-')
  1756.                         return 0;
  1757.                     chgmode = *cp++;
  1758.                     skipspc(cp);
  1759.                     cp2 = namebuf;
  1760.                     while (isalnum(*cp) || *cp == '_' ||
  1761.    *cp == '$' || *cp == '%' ||
  1762.    *cp == '.' || *cp == '-' ||
  1763.    (*cp == ''' && cp[1] && cp[2] == ''' &&
  1764.     cp+1 != closing && cp[1] != '=')) {
  1765. if (*cp == ''') {
  1766.     *cp2++ = *cp++;
  1767.     *cp2++ = *cp++;
  1768. }     
  1769.                         *cp2++ = *cp++;
  1770.     }
  1771.                     *cp2++ = 0;
  1772.                     if (chgmode == '-') {
  1773.                         skipspc(cp);