home *** CD-ROM | disk | FTP | other *** search
/ Total Destruction / Total_Destruction.iso / addons / Lccwin32.exe / Lccwin32 / lccpub / src / Ncpp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-11  |  74.4 KB  |  3,505 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <stdarg.h>
  6. #include <fcntl.h>
  7. #ifndef UNIX_COMPILE
  8. #include <windows.h>
  9. #include <io.h>
  10. #endif
  11. #pragma pack(1)
  12. #define PATH_SEPARATOR '\\'
  13. #define BUG_LCC_CORRECTED
  14. extern FILE *xrefFile;
  15. #define    INS    (32*1024)        /* input buffer */
  16. #define    OBS    4096        /* outbut buffer */
  17. #define    NARG    32        /* Max number arguments to a macro */
  18. #define    NINCLUDE 32        /* Max number of include directories (-I) */
  19. #define    NIF    32        /* depth of nesting of #if */
  20. #ifndef EOF
  21. #define    EOF    (-1)
  22. #endif
  23. #ifndef NULL
  24. #define NULL    0
  25. #endif
  26. extern int outputLine;
  27. #ifdef __LCC__
  28. //#define ASM_LIB
  29. #endif
  30. typedef unsigned char uchar;
  31.  
  32. enum toktype { END, UNCLASS, NAME, NUMBER, STRING, CCON, NL, WS, DSHARP,
  33.         EQ, NEQ, LEQ, GEQ, LSH, RSH, LAND, LOR, PPLUS, MMINUS,
  34.         ARROW, SBRA, SKET, LP, RP, DOT, AND, STAR, PLUS, MINUS,
  35.         TILDE, NOT, SLASH, PCT, LT, GT, CIRC, OR, QUEST,
  36.         COLON, ASGN, COMMA, SHARP, SEMIC, CBRA, CKET,
  37.         ASPLUS, ASMINUS, ASSTAR, ASSLASH, ASPCT, ASCIRC, ASLSH,
  38.         ASRSH, ASOR, ASAND, ELLIPS,
  39.         DSHARP1, NAME1, DEFINED, UMINUS,
  40. FLOATK,
  41. DOUBLEK,
  42. CHARK,
  43. SHORTK,
  44. INTK,
  45. UNSIGNEDK,
  46. VOIDK,
  47. STRUCTK,
  48. UNION,
  49. ENUM,
  50. LONGK,
  51. CONSTK,
  52. VOLATILEK,
  53. SIZEOFK,
  54. AUTOK,
  55. BREAK,
  56. CASE,
  57. CONTINUE,
  58. DEFAULT,
  59. DO,
  60. ELSE,
  61. EXTERNK,
  62. FOR,
  63. GOTO,
  64. IF,
  65. REGISTER,
  66. RETURN,
  67. SIGNED,
  68. STATICK,
  69. SWITCH,
  70. TYPEDEF,
  71. WHILE,
  72. PASCALKEYW
  73.  };
  74.  
  75. enum kwtype { KIF, KIFDEF, KIFNDEF, KELIF, KELSE, KENDIF, KINCLUDE, KDEFINE,
  76.         KUNDEF, KLINE, KERROR, KPRAGMA, KDEFINED,
  77.         KLINENO, KFILE, KDATE, KTIME, KSTDC, KEVAL };
  78.  
  79. #define    ISDEFINED    0x1    /* has #defined value */
  80. #define    ISKW        0x2    /* is PP keyword */
  81. #define    ISUNCHANGE    0x4    /* can't be #defined in PP */
  82. #define    ISMAC        0x8    /* builtin macro, e.g. __LINE__ */
  83. #define ISUSED        0x10 /* is used somwhere */
  84.  
  85. #define    EOB    0xFE        /* sentinel for end of input buffer */
  86. #define    EOFC    0xFD        /* sentinel for end of input file */
  87. #define    XPWS    1        /* token flag: white space to assure token sep. */
  88.  
  89. typedef struct token {
  90.     unsigned char    type;
  91.     unsigned char     flag;
  92.     unsigned short    hideset;
  93.     unsigned int    wslen;
  94.     unsigned int    len;
  95.     uchar    *t;
  96. } Token;
  97.  
  98. typedef struct tokenrow {
  99.     Token    *tp;        /* current one to scan */
  100.     Token    *bp;        /* base (allocated value) */
  101.     Token    *lp;        /* last+1 token used */
  102.     int    max;        /* number allocated */
  103. } Tokenrow;
  104.  
  105. typedef struct source {
  106.     char    *filename;    /* name of file of the source */
  107.     int    line;        /* current line number */
  108.     int    lineinc;    /* adjustment for \\n lines */
  109.     uchar    *inb;        /* input buffer */
  110.     uchar    *inp;        /* input pointer */
  111.     uchar    *inl;        /* end of input */
  112.     int    fd;        /* input source */
  113.     int    ifdepth;    /* conditional nesting in include */
  114.     struct    source *next;    /* stack for #include */
  115. } Source;
  116.  
  117. typedef struct nlist {
  118.     struct nlist *next;
  119.     uchar    *name;
  120.     int    len;
  121.     int h;
  122.     Tokenrow *vp;        /* value as macro */
  123.     Tokenrow *ap;        /* list of argument names, if any */
  124.     char    val;        /* value as preprocessor name */
  125.     char    flag;        /* is defined, is pp name */
  126.     unsigned short srcline;
  127.     uchar *filename;
  128. } Nlist;
  129.  
  130. typedef    struct    includelist {
  131.     unsigned char    deleted;
  132.     unsigned char    always;
  133.     unsigned char    *file;
  134. } Includelist;
  135.  
  136. #define    new(t)    (t *)domalloc(sizeof(t))
  137. #define    quicklook(a,b)    (namebit[(a)&077] & (1<<((b)&037)))
  138. #define    quickset(a,b)    namebit[(a)&077] |= (1<<((b)&037))
  139. static    unsigned long namebit[077+1];
  140.  
  141. enum errtype { CPPWARNING, CPPERROR, CPPFATAL };
  142. static void    expandlex(void);
  143. static void    fixlex(void);
  144. static void    setup(unsigned char *);
  145. static int    gettokens(Tokenrow *, int);
  146. static int    comparetokens(Tokenrow *, Tokenrow *);
  147. static Source    *setsource(unsigned char *, int, char *);
  148. static void    unsetsource(void);
  149. static int        puttokens(Tokenrow *);
  150. static int        process(Tokenrow *);
  151. static void    *domalloc(int);
  152. static void    dofree(void *);
  153. static void    error(enum errtype, char *, ...);
  154. static void    flushout(void);
  155. static int    fillbuf(Source *);
  156. static int    trigraph(Source *);
  157. static int    foldline(Source *);
  158. #ifndef ASM_LIB
  159. static Nlist    *cpplookup(Token *);
  160. #else
  161. extern Nlist *cpplookup(Token *);
  162. #endif
  163. static Nlist    *InstallToken(Token *);
  164. static void    control(Tokenrow *);
  165. static Nlist *dodefine(Tokenrow *);
  166. static Nlist *doadefine(Tokenrow *, int);
  167. static void    doinclude(Tokenrow *);
  168. static void    doif(Tokenrow *, enum kwtype);
  169. static void    expand(Tokenrow *, Nlist *);
  170. static void    builtin(Tokenrow *, int);
  171. static int    gatherargs(Tokenrow *, Tokenrow **, int *);
  172. static void    substargs(Nlist *, Tokenrow *, Tokenrow **);
  173. static void    expandrow(Tokenrow *,unsigned char *);
  174. static void    maketokenrow(int, Tokenrow *);
  175. static Tokenrow *copytokenrow(Tokenrow *, Tokenrow *);
  176. static Token    *growtokenrow(Tokenrow *);
  177. static Tokenrow *normtokenrow(Tokenrow *);
  178. static void    adjustrow(Tokenrow *, int);
  179. static void    insertrow(Tokenrow *, int, Tokenrow *);
  180. static void    peektokens(Tokenrow *, char *);
  181. static void    doconcat(Tokenrow *);
  182. static Tokenrow *stringify(Tokenrow *);
  183. static int    lookuparg(Nlist *, Token *);
  184. static long    eval(Tokenrow *, int);
  185. static int    genline(void);
  186. static void    setempty(Tokenrow *);
  187. static void    makespace(Tokenrow *);
  188. static char    *outnum(char *, int);
  189. static int    digit(int);
  190. static unsigned char *newstring(unsigned char *, int, int);
  191. static int    checkhideset(int, Nlist *);
  192. static void    prhideset(int);
  193. static int    newhideset(int, Nlist *);
  194. static int    unionhideset(int, int);
  195. static void    iniths(void);
  196. static void    setobjname(unsigned char *);
  197. #ifndef LRC
  198. static void dodeclspec(Tokenrow *trp);
  199. #endif
  200. #define    rowlen(tokrow)    ((tokrow)->lp - (tokrow)->bp)
  201.  
  202. #define    OUTS    4096
  203. static char    outbuf[OUTS+OUTS];
  204. static char    *OutputPtr = outbuf;
  205. static Source    *cursource;
  206. static int    nerrs;
  207. static struct    token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" };
  208. static char    *curtime;
  209. static int    incdepth;
  210. static int    ifdepth;
  211. static int    ifsatisfied[NIF];
  212. static int    skipping;
  213. static    int    Cplusplus;
  214. static Nlist    *kwdefined;
  215. static char    wd[128];
  216. int    Mflag;    /* only print active include files */
  217. static int    Cplusplus = 1;
  218. long CharsRead=0;
  219. #ifndef LRC
  220. int dotokfile = 0;
  221. int TraceDependencies= 0;
  222. #endif
  223. #define    NLSIZE    1024
  224. static unsigned char wbuf[4*OBS];
  225. static unsigned char *wbp = wbuf;
  226. static int PartialSize = 0;
  227. #ifdef ASM_LIB
  228. Nlist *nlist[NLSIZE];
  229. #else
  230. static Nlist    *nlist[NLSIZE];
  231. #endif
  232.  
  233.  
  234. static struct    kwtab {
  235.     char    *kw;
  236.     int    val;
  237.     int    flag;
  238. } kwtab[] = {
  239.     "if",        KIF,        ISKW,
  240.     "ifdef",    KIFDEF,        ISKW,
  241.     "ifndef",    KIFNDEF,    ISKW,
  242.     "elif",        KELIF,        ISKW,
  243.     "else",        KELSE,        ISKW,
  244.     "endif",    KENDIF,        ISKW,
  245.     "include",    KINCLUDE,    ISKW,
  246.     "define",    KDEFINE,    ISKW,
  247.     "undef",    KUNDEF,        ISKW,
  248.     "line",        KLINE,        ISKW,
  249.     "error",    KERROR,        ISKW,
  250.     "pragma",    KPRAGMA,    ISKW,
  251.     "eval",        KEVAL,        ISKW,
  252.     "defined",    KDEFINED,    ISDEFINED+ISUNCHANGE,
  253.     "__LINE__",    KLINENO,    ISMAC+ISUNCHANGE,
  254.     "__FILE__",    KFILE,        ISMAC+ISUNCHANGE,
  255.     "__DATE__",    KDATE,        ISMAC+ISUNCHANGE,
  256.     "__TIME__",    KTIME,        ISMAC+ISUNCHANGE,
  257. //    "__STDC__",    KSTDC,        ISUNCHANGE,
  258.     NULL
  259. };
  260. #define movetokenrow(dtr,str) memmove(dtr->tp, str->bp, (char *)str->lp - (char *)str->bp)
  261. #ifndef LRC
  262. typedef struct tagFileList {
  263.     struct tagFileList *Next;
  264.     char *fName;
  265. } FILELIST;
  266. static FILELIST *fList;
  267. void AddToFileTable(char *fname)
  268. {
  269.     FILELIST *rvp;
  270.     if (fList == NULL) {
  271.         fList = malloc(sizeof(FILELIST));
  272.         rvp = fList;
  273.     }
  274.     else {
  275.         rvp = fList;
  276.         while (rvp->Next) {
  277.             rvp = rvp->Next;
  278.         }
  279.         rvp->Next = malloc(sizeof(FILELIST));
  280.         rvp = rvp->Next;
  281.     }
  282.     rvp->Next = NULL;
  283.     rvp->fName = malloc(strlen(fname)+1);
  284.     strcpy(rvp->fName,fname);
  285. }
  286.  
  287. int GetFileNumber(char *fname)
  288. {
  289.     FILELIST *rvp;
  290.     int i;
  291.  
  292.     rvp = fList;
  293.     i = 1;
  294.     while (rvp) {
  295.         if (!strcmp(fname,rvp->fName)) return(i);
  296.         i++;
  297.         rvp = rvp->Next;
  298.     }
  299.     return(0);
  300. }
  301. void PrintIncludeTree(char *iname)
  302. {
  303.     Source *rvp;
  304.  
  305.     if (cursource) {
  306.         rvp = cursource->next;
  307.         while (rvp) {
  308.             fprintf(stdout,"%s: line %d\n",rvp->filename,rvp->line);
  309.             rvp = rvp->next;
  310.         }
  311.         fprintf(stdout,"%s: line %d --> %s\n---\n",cursource->filename,cursource->line,iname);
  312.     }
  313.  
  314. }
  315. #endif // LRC
  316. #ifdef UNIX_COMPILE
  317. int DoOpen(char *name)
  318. {
  319.     return(open(name,0));
  320. }
  321. int DoRead(int h,char *buf,int siz)
  322. {
  323.     return(read(h,buf,siz));
  324. }
  325. static int DoClose(int h)
  326. {
  327.     return(close(h));
  328. }
  329. #else
  330. static int DoOpen(unsigned char *fname)
  331. {
  332.     void *fh;
  333.  
  334.     
  335.     fh = CreateFileA(fname,
  336.         GENERIC_READ,
  337.         FILE_SHARE_READ,
  338.         NULL, /* no security */
  339.         OPEN_EXISTING,
  340.         FILE_ATTRIBUTE_NORMAL,
  341.         0);
  342.     if (fh == (void *)INVALID_HANDLE_VALUE) return -1;
  343.     return((int)fh);
  344. }
  345. int ReadTime;
  346. #ifdef ASM_LIB
  347. extern int DoRead(int,char *,int);
  348. #else
  349. static int DoRead(int hf,char *buf,int siz)
  350. {
  351.     unsigned long br;
  352.     register char *p1,*p2;
  353.     
  354.     br = 0;
  355.     ReadFile((void *)hf,buf,siz,&br,0);
  356.     CharsRead += br;
  357.     {
  358.         int i;
  359.         p1 = p2 = buf;
  360.         i = 0;
  361.         while (i++ < br) {
  362.             if (*p1 != '\r') {
  363.                 *p2++ = *p1;
  364.             }
  365.             p1++;
  366.         }
  367.     }
  368.     return(br-(p1 - p2));
  369. }
  370. #endif
  371.  
  372. static int DoClose(int fh)
  373. {
  374.     return(CloseHandle((void *)fh));
  375. }
  376. #endif /* UNIX_COMPILE */
  377.  
  378.  
  379. static int outfile;
  380. static char *IncPath;
  381. static Tokenrow TokenRow;
  382. #ifndef LRC
  383. static FILE *tokfile;
  384. static unsigned char tbuf[512];
  385. static unsigned char *TokFileName;
  386. #endif
  387. int CppInit(void)
  388. {
  389.     time_t t;
  390.  
  391.     outfile = 1;
  392. /*    setbuf(stderr, ebuf);*/
  393.     t = time(NULL);
  394.     curtime = ctime(&t);
  395.     maketokenrow(3, &TokenRow);
  396.     expandlex();
  397. #ifndef LRC
  398.     if (Mflag) {
  399.         TraceDependencies = 1;
  400.     }
  401. #endif
  402.     return(1);
  403. }
  404.  
  405. int StartCpp(unsigned char *filename)
  406. {
  407.     setup(filename);
  408.     fixlex();
  409.     iniths();
  410. #ifndef LRC
  411.     if (dotokfile) {
  412.         tokfile = fopen(TokFileName,"wb");
  413.         tbuf[0] = 0;
  414.     }
  415. #endif
  416.     genline();
  417.     return(1);
  418. }
  419. #ifndef LRC
  420. int FinishCpp(void)
  421. {
  422.     fflush(stderr);
  423.     return nerrs;
  424. }
  425. #endif
  426. static int anymacros = 0;
  427. static int process(Tokenrow *trp)
  428. {
  429.     int readMore = 1;
  430.     int isEOF = 0;
  431.  
  432.     while (readMore) {
  433.         if (trp->tp >= trp->lp) {
  434.             trp->tp = trp->lp = trp->bp;
  435.             OutputPtr = outbuf;
  436.             anymacros |= gettokens(trp, 1);
  437.             trp->tp = trp->bp;
  438.         }
  439.         if (trp->tp->type == END) {
  440.             if (--incdepth>=0) {
  441.                 if (cursource->ifdepth)
  442.                     error(CPPERROR,
  443.                      "Unterminated conditional in #include");
  444.                 unsetsource();
  445.                 cursource->line += cursource->lineinc;
  446.                 trp->tp = trp->lp;
  447.                 genline();
  448.                 continue;
  449.             }
  450.             isEOF = 1;
  451.             if (ifdepth)
  452.                 error(CPPERROR, "Unterminated #if/#ifdef/#ifndef");
  453.             break;
  454.         }
  455.         if (trp->tp->type==SHARP) {
  456.             trp->tp += 1;
  457.             control(trp);
  458.         } else if (!skipping && anymacros)
  459.             expandrow(trp, NULL);
  460.         if (skipping)
  461.             setempty(trp);
  462.         readMore = puttokens(trp);
  463.         anymacros = 0;
  464.         cursource->line += cursource->lineinc;
  465.         if (cursource->lineinc>1) {
  466.             readMore = genline();
  467.         }
  468.     }
  469.     return(isEOF);
  470. }
  471.  
  472. static int isEOF = 0;
  473. int ReadFromCpp(unsigned char *buf,int siz)
  474. {
  475.     int r = 0;
  476.     unsigned char *stop;
  477.     extern clock_t CppTime;
  478.  
  479.     stop = &wbuf[OBS];
  480. #ifndef LRC
  481.     if (TraceDependencies) {
  482.         while (!isEOF) {
  483.             isEOF = process(&TokenRow);
  484.             wbp = wbuf;
  485.         }
  486.         return(0);
  487.     }
  488. #endif
  489.     if (isEOF) {
  490.         r = (wbp - wbuf);
  491.         if (r > siz) {
  492.             memcpy(buf,wbuf,siz);
  493.             memcpy(wbuf,wbuf+siz,r-siz);
  494.             wbp = wbuf + r-siz;
  495.             return(siz);
  496.         }
  497.         else if (r) memcpy(buf,wbuf,r);
  498.         wbp -= r;
  499.         return(r);
  500.     }
  501.     if (wbp < stop) {
  502.         do {
  503.             isEOF = process(&TokenRow);
  504.         } while (isEOF == 0 && wbp < stop);
  505.     }
  506.     if (wbp >= stop) {
  507.         memcpy(buf,wbuf,OBS);
  508.         r = OBS;
  509.         if (wbp > stop)
  510.             memcpy(wbuf, wbuf+OBS, wbp - stop);
  511.         wbp -= OBS;
  512.     }
  513.     else {
  514.         r = (wbp - wbuf);
  515.         memcpy(buf,wbuf,r);
  516.         wbp -= r;
  517.     }
  518.     return(r);
  519. }
  520.  
  521. static void control(Tokenrow *trp)
  522. {
  523.     Nlist *np;
  524.     Token *tp;
  525.  
  526.     tp = trp->tp;
  527.     if (tp->type!=NAME) {
  528.         if (tp->type==NUMBER)
  529.             goto kline;
  530.         if (tp->type != NL)
  531.             error(CPPERROR, "Unidentifiable control line");
  532.         return;            /* else empty line */
  533.     }
  534.     if ((np = cpplookup(tp))==NULL || (np->flag&ISKW)==0 && !skipping) {
  535.         error(CPPWARNING, "Unknown preprocessor control %t", tp);
  536.         return;
  537.     }
  538.     if (skipping) {
  539.         switch (np->val) {
  540.         case KENDIF:
  541.             if (--ifdepth<skipping)
  542.                 skipping = 0;
  543.             --cursource->ifdepth;
  544.             setempty(trp);
  545.             return;
  546.  
  547.         case KIFDEF:
  548.         case KIFNDEF:
  549.         case KIF:
  550.             if (++ifdepth >= NIF)
  551.                 error(CPPFATAL, "#if too deeply nested");
  552.             ++cursource->ifdepth;
  553.             return;
  554.  
  555.         case KELIF:
  556.         case KELSE:
  557.             if (ifdepth<=skipping)
  558.                 break;
  559.             return;
  560.  
  561.         default:
  562.             return;
  563.         }
  564.     }
  565.     switch (np->val) {
  566.     case KDEFINE:
  567.         dodefine(trp);
  568.         break;
  569.  
  570.     case KUNDEF:
  571.         tp += 1;
  572.         if (tp->type!=NAME || trp->lp - trp->bp != 4) {
  573.             error(CPPERROR, "Syntax error in #undef");
  574.             break;
  575.         }
  576.         if ((np = cpplookup(tp)) != NULL)
  577.             np->flag &= ~ISDEFINED;
  578.         break;
  579.  
  580.     case KPRAGMA:
  581.         return;
  582.  
  583.     case KIFDEF:
  584.     case KIFNDEF:
  585.     case KIF:
  586.         if (++ifdepth >= NIF)
  587.             error(CPPFATAL, "#if too deeply nested");
  588.         ++cursource->ifdepth;
  589.         ifsatisfied[ifdepth] = 0;
  590.         if (eval(trp, np->val))
  591.             ifsatisfied[ifdepth] = 1;
  592.         else
  593.             skipping = ifdepth;
  594.         break;
  595.  
  596.     case KELIF:
  597.         if (ifdepth==0) {
  598.             error(CPPERROR, "#elif with no #if");
  599.             return;
  600.         }
  601.         if (ifsatisfied[ifdepth]==2)
  602.             error(CPPERROR, "#elif after #else");
  603.         if (eval(trp, np->val)) {
  604.             if (ifsatisfied[ifdepth])
  605.                 skipping = ifdepth;
  606.             else {
  607.                 skipping = 0;
  608.                 ifsatisfied[ifdepth] = 1;
  609.             }
  610.         } else
  611.             skipping = ifdepth;
  612.         break;
  613.  
  614.     case KELSE:
  615.         if (ifdepth==0 || cursource->ifdepth==0) {
  616.             error(CPPERROR, "#else with no #if");
  617.             return;
  618.         }
  619.         if (ifsatisfied[ifdepth]==2)
  620.             error(CPPERROR, "#else after #else");
  621.         if (trp->lp - trp->bp != 3)
  622.             error(CPPERROR, "Syntax error in #else");
  623.         skipping = ifsatisfied[ifdepth]? ifdepth: 0;
  624.         ifsatisfied[ifdepth] = 2;
  625.         break;
  626.  
  627.     case KENDIF:
  628.         if (ifdepth==0 || cursource->ifdepth==0) {
  629.             error(CPPERROR, "#endif with no #if");
  630.             return;
  631.         }
  632.         --ifdepth;
  633.         --cursource->ifdepth;
  634.         if (trp->lp - trp->bp != 3)
  635.             error(CPPWARNING, "Syntax error in #endif");
  636.         break;
  637.  
  638.     case KERROR:
  639.         trp->tp = tp+1;
  640.         error(CPPWARNING, "#error directive: %r", trp);
  641.         break;
  642.  
  643.     case KLINE:
  644.         trp->tp = tp+1;
  645.         expandrow(trp,(unsigned char *) "<line>");
  646.         tp = trp->bp+2;
  647.     kline:
  648.         if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
  649.          || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){
  650.             error(CPPERROR, "Syntax error in #line");
  651.             return;
  652.         }
  653.         cursource->line = atol((char*)tp->t)-1;
  654.         if (cursource->line<0 || cursource->line>=32768)
  655.             error(CPPWARNING, "#line specifies number out of range");
  656.         tp = tp+1;
  657.         if (tp+1<trp->lp)
  658.             cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
  659.         return;
  660.  
  661.     case KDEFINED:
  662.         error(CPPERROR, "Bad syntax for control line");
  663.         break;
  664.  
  665.     case KINCLUDE:
  666.         doinclude(trp);
  667.         trp->lp = trp->bp;
  668.         return;
  669.  
  670.     case KEVAL:
  671.         eval(trp, np->val);
  672.         break;
  673.  
  674.     default:
  675.         error(CPPERROR, "Preprocessor control `%t' not yet implemented", tp);
  676.         break;
  677.     }
  678.     setempty(trp);
  679.     return;
  680. }
  681.  
  682. static void *domalloc(int size)
  683. {
  684.     void *p;
  685.  
  686.     p = malloc(size);
  687.  
  688.     if (p==NULL)
  689.         error(CPPFATAL, "Out of memory from malloc");
  690.     memset(p,0,size);
  691.     return p;
  692. }
  693.  
  694. static void dofree(void *p)
  695. {
  696.     free(p);
  697. }
  698.  
  699. static void error(enum errtype type, char *string, ...)
  700. {
  701.     va_list ap;
  702.     char *cp, *ep;
  703.     Token *tp;
  704.     Tokenrow *trp;
  705.     Source *s;
  706.     int i;
  707.  
  708. #ifdef LRC
  709.     fprintf(stderr, "lrc: ");
  710. #else
  711.     if (TraceDependencies && type == CPPWARNING) return;
  712.     fprintf(stderr, "cpp: ");
  713. #endif
  714.     for (s=cursource; s; s=s->next)
  715.         if (*s->filename)
  716.             fprintf(stderr, "%s:%d ", s->filename, s->line);
  717.     va_start(ap, string);
  718.     for (ep=string; *ep; ep++) {
  719.         if (*ep=='%') {
  720.             switch (*++ep) {
  721.  
  722.             case 's':
  723.                 cp = va_arg(ap, char *);
  724.                 fprintf(stderr, "%s", cp);
  725.                 break;
  726.             case 'd':
  727.                 i = va_arg(ap, int);
  728.                 fprintf(stderr, "%d", i);
  729.                 break;
  730.             case 't':
  731.                 tp = va_arg(ap, Token *);
  732.                 fprintf(stderr, "%.*s", tp->len, tp->t);
  733.                 break;
  734.  
  735.             case 'r':
  736.                 trp = va_arg(ap, Tokenrow *);
  737.                 for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
  738.                     if (tp>trp->tp && tp->wslen)
  739.                         fputc(' ', stderr);
  740.                     fprintf(stderr, "%.*s", tp->len, tp->t);
  741.                 }
  742.                 break;
  743.  
  744.             default:
  745.                 fputc(*ep, stderr);
  746.                 break;
  747.             }
  748.         } else
  749.             fputc(*ep, stderr);
  750.     }
  751.     va_end(ap);
  752.     fputc('\n', stderr);
  753.     if (type==CPPFATAL)
  754.         exit(1);
  755.     if (type!=CPPWARNING)
  756.         nerrs = 1;
  757.     fflush(stderr);
  758. }
  759. #define    NSTAK    32
  760. #define    SGN    0
  761. #define    UNS    1
  762. #define    UND    2
  763.  
  764. #define    UNSMARK    0x1000
  765.  
  766. struct value {
  767.     long    val;
  768.     int    type;
  769. };
  770.  
  771. /* conversion types */
  772. #define    RELAT    1
  773. #define    ARITH    2
  774. #define    LOGIC    3
  775. #define    SPCL    4
  776. #define    SHIFT    5
  777. #define    UNARY    6
  778.  
  779. /* operator priority, arity, and conversion type, indexed by tokentype */
  780. static struct pri {
  781.     char    pri;
  782.     char    arity;
  783.     char    ctype;
  784. } priority[] = {
  785.     { 0, 0, 0 },        /* END */
  786.     { 0, 0, 0 },        /* UNCLASS */
  787.     { 0, 0, 0 },        /* NAME */
  788.     { 0, 0, 0 },        /* NUMBER */
  789.     { 0, 0, 0 },        /* STRING */
  790.     { 0, 0, 0 },        /* CCON */
  791.     { 0, 0, 0 },        /* NL */
  792.     { 0, 0, 0 },        /* WS */
  793.     { 0, 0, 0 },        /* DSHARP */
  794.     { 11, 2, RELAT },    /* EQ */
  795.     { 11, 2, RELAT },    /* NEQ */
  796.     { 12, 2, RELAT },    /* LEQ */
  797.     { 12, 2, RELAT },    /* GEQ */
  798.     { 13, 2, SHIFT },    /* LSH */
  799.     { 13, 2, SHIFT },    /* RSH */
  800.     { 7, 2, LOGIC },    /* LAND */
  801.     { 6, 2, LOGIC },    /* LOR */
  802.     { 0, 0, 0 },        /* PPLUS */
  803.     { 0, 0, 0 },        /* MMINUS */
  804.     { 0, 0, 0 },        /* ARROW */
  805.     { 0, 0, 0 },        /* SBRA */
  806.     { 0, 0, 0 },        /* SKET */
  807.     { 3, 0, 0 },        /* LP */
  808.     { 3, 0, 0 },        /* RP */
  809.     { 0, 0, 0 },        /* DOT */
  810.     { 10, 2, ARITH },    /* AND */
  811.     { 15, 2, ARITH },    /* STAR */
  812.     { 14, 2, ARITH },    /* PLUS */
  813.     { 14, 2, ARITH },    /* MINUS */
  814.     { 16, 1, UNARY },    /* TILDE */
  815.     { 16, 1, UNARY },    /* NOT */
  816.     { 15, 2, ARITH },    /* SLASH */
  817.     { 15, 2, ARITH },    /* PCT */
  818.     { 12, 2, RELAT },    /* LT */
  819.     { 12, 2, RELAT },    /* GT */
  820.     { 9, 2, ARITH },    /* CIRC */
  821.     { 8, 2, ARITH },    /* OR */
  822.     { 5, 2, SPCL },        /* QUEST */
  823.     { 5, 2, SPCL },        /* COLON */
  824.     { 0, 0, 0 },        /* ASGN */
  825.     { 4, 2, 0 },        /* COMMA */
  826.     { 0, 0, 0 },        /* SHARP */
  827.     { 0, 0, 0 },        /* SEMIC */
  828.     { 0, 0, 0 },        /* CBRA */
  829.     { 0, 0, 0 },        /* CKET */
  830.     { 0, 0, 0 },        /* ASPLUS */
  831.      { 0, 0, 0 },        /* ASMINUS */
  832.      { 0, 0, 0 },        /* ASSTAR */
  833.      { 0, 0, 0 },        /* ASSLASH */
  834.      { 0, 0, 0 },        /* ASPCT */
  835.      { 0, 0, 0 },        /* ASCIRC */
  836.      { 0, 0, 0 },        /* ASLSH */
  837.     { 0, 0, 0 },        /* ASRSH */
  838.      { 0, 0, 0 },        /* ASOR */
  839.      { 0, 0, 0 },        /* ASAND */
  840.     { 0, 0, 0 },        /* ELLIPS */
  841.     { 0, 0, 0 },        /* DSHARP1 */
  842.     { 0, 0, 0 },        /* NAME1 */
  843.     { 16, 1, UNARY },    /* DEFINED */
  844.     { 16, 0, UNARY },    /* UMINUS */
  845. };
  846.  
  847. static int    evalop(struct pri);
  848. static struct    value tokval(Token *);
  849. static struct value vals[NSTAK], *vp;
  850. static enum toktype ops[NSTAK], *op;
  851.  
  852. /*
  853.  * Evaluate an #if #elif #ifdef #ifndef line.  trp->tp points to the keyword.
  854.  */
  855. static long eval(Tokenrow *trp, int kw)
  856. {
  857.     Token *tp;
  858.     Nlist *np;
  859.     int ntok, rand;
  860.  
  861.     trp->tp++;
  862.     if (kw==KIFDEF || kw==KIFNDEF) {
  863.         if (trp->lp - trp->bp != 4 || trp->tp->type!=NAME) {
  864.             error(CPPERROR, "Syntax error in #ifdef/#ifndef");
  865.             return 0;
  866.         }
  867.         np = cpplookup(trp->tp);
  868.         return (kw==KIFDEF) == (np && np->flag&ISDEFINED);
  869.     }
  870.     ntok = trp->tp - trp->bp;
  871.     kwdefined->val = KDEFINED;    /* activate special meaning of defined */
  872.     expandrow(trp,(unsigned char *) "<if>");
  873.     kwdefined->val = NAME;
  874.     vp = vals;
  875.     op = ops;
  876.     *op++ = END;
  877.     for (rand=0, tp = trp->bp+ntok; tp < trp->lp; tp++) {
  878.         switch(tp->type) {
  879.         case WS:
  880.         case NL:
  881.             continue;
  882.  
  883.         /* nilary */
  884.         case NAME:
  885.         case NAME1:
  886.         case NUMBER:
  887.         case CCON:
  888.         case STRING:
  889.             if (rand)
  890.                 goto syntax;
  891.             *vp++ = tokval(tp);
  892.             rand = 1;
  893.             continue;
  894.  
  895.         /* unary */
  896.         case DEFINED:
  897.         case TILDE:
  898.         case NOT:
  899.             if (rand)
  900.                 goto syntax;
  901.             *op++ = tp->type;
  902.             continue;
  903.  
  904.         /* unary-binary */
  905.         case PLUS: case MINUS: case STAR: case AND:
  906.             if (rand==0) {
  907.                 if (tp->type==MINUS)
  908.                     *op++ = UMINUS;
  909.                 if (tp->type==STAR || tp->type==AND) {
  910.                     error(CPPERROR, "Illegal operator * or & in #if/#elsif");
  911.                     return 0;
  912.                 }
  913.                 continue;
  914.             }
  915.             /* flow through */
  916.  
  917.         /* plain binary */
  918.         case EQ: case NEQ: case LEQ: case GEQ: case LSH: case RSH:
  919.         case LAND: case LOR: case SLASH: case PCT:
  920.         case LT: case GT: case CIRC: case OR: case QUEST:
  921.         case COLON: case COMMA:
  922.             if (rand==0)
  923.                 goto syntax;
  924.             if (evalop(priority[tp->type])!=0)
  925.                 return 0;
  926.             *op++ = tp->type;
  927.             rand = 0;
  928.             continue;
  929.  
  930.         case LP:
  931.             if (rand)
  932.                 goto syntax;
  933.             *op++ = LP;
  934.             continue;
  935.  
  936.         case RP:
  937.             if (!rand)
  938.                 goto syntax;
  939.             if (evalop(priority[RP])!=0)
  940.                 return 0;
  941.             if (op<=ops || op[-1]!=LP) {
  942.                 goto syntax;
  943.             }
  944.             op--;
  945.             continue;
  946.  
  947.         default:
  948.             error(CPPERROR,"Bad operator (%t) in #if/#elsif", tp);
  949.             return 0;
  950.         }
  951.     }
  952.     if (rand==0)
  953.         goto syntax;
  954.     if (evalop(priority[END])!=0)
  955.         return 0;
  956.     if (op!=&ops[1] || vp!=&vals[1]) {
  957.         error(CPPERROR, "Botch in #if/#elsif");
  958.         return 0;
  959.     }
  960.     if (vals[0].type==UND)
  961.         error(CPPERROR, "Undefined expression value");
  962.     return vals[0].val;
  963. syntax:
  964.     error(CPPERROR, "Syntax error in #if/#elsif");
  965.     return 0;
  966. }
  967.  
  968. static int evalop(struct pri pri)
  969. {
  970.     struct value v1, v2;
  971.     long rv1, rv2;
  972.     int rtype, oper;
  973.  
  974.     rv2=0;
  975.     rtype=0;
  976.     while (pri.pri < priority[op[-1]].pri) {
  977.         oper = *--op;
  978.         if (priority[oper].arity==2) {
  979.             v2 = *--vp;
  980.             rv2 = v2.val;
  981.         }
  982. #ifdef BUG_LCC_CORRECTED
  983.         v1 = *--vp;
  984. #else
  985.         --vp;
  986.         v1 = *vp;
  987. #endif
  988.         rv1 = v1.val;
  989. /*lint -e574 -e644 */
  990.         switch (priority[oper].ctype) {
  991.         case 0:
  992.         default:
  993.             error(CPPWARNING, "Syntax error in #if/#endif");
  994.             return 1;
  995.         case ARITH:
  996.         case RELAT:
  997.             if (v1.type==UNS || v2.type==UNS)
  998.                 rtype = UNS;
  999.             else
  1000.                 rtype = SGN;
  1001.             if (v1.type==UND || v2.type==UND)
  1002.                 rtype = UND;
  1003.             if (priority[oper].ctype==RELAT && rtype==UNS) {
  1004.                 oper |= UNSMARK;
  1005.                 rtype = SGN;
  1006.             }
  1007.             break;
  1008.         case SHIFT:
  1009.             if (v1.type==UND || v2.type==UND)
  1010.                 rtype = UND;
  1011.             else
  1012.                 rtype = v1.type;
  1013.             if (rtype==UNS)
  1014.                 oper |= UNSMARK;
  1015.             break;
  1016.         case UNARY:
  1017.             rtype = v1.type;
  1018.             break;
  1019.         case LOGIC:
  1020.         case SPCL:
  1021.             break;
  1022.         }
  1023.         switch (oper) {
  1024.         case EQ: case EQ|UNSMARK:
  1025.             rv1 = rv1==rv2; break;
  1026.         case NEQ: case NEQ|UNSMARK:
  1027.             rv1 = rv1!=rv2; break;
  1028.         case LEQ:
  1029.             rv1 = rv1<=rv2; break;
  1030.         case GEQ:
  1031.             rv1 = rv1>=rv2; break;
  1032.         case LT:
  1033.             rv1 = rv1<rv2; break;
  1034.         case GT:
  1035.             rv1 = rv1>rv2; break;
  1036.         case LEQ|UNSMARK:
  1037.             rv1 = (rv1<=rv2); break;
  1038.         case GEQ|UNSMARK:
  1039.             rv1 = rv1>=rv2; break;
  1040.         case LT|UNSMARK:
  1041.             rv1 = rv1<rv2; break;
  1042.         case GT|UNSMARK:
  1043.             rv1 = rv1>rv2; break;
  1044.         case LSH:
  1045.             rv1 <<= rv2; break;
  1046.         case LSH|UNSMARK:
  1047.             rv1 = (unsigned long)rv1<<rv2; break;
  1048.         case RSH:
  1049.             rv1 >>= rv2; break;
  1050.         case RSH|UNSMARK:
  1051.             rv1 = (unsigned long)rv1>>rv2; break;
  1052.         case LAND:
  1053.             rtype = UND;
  1054.             if (v1.type==UND)
  1055.                 break;
  1056.             if (rv1!=0) {
  1057.                 if (v2.type==UND)
  1058.                     break;
  1059.                 rv1 = rv2!=0;
  1060.             } else
  1061.                 rv1 = 0;
  1062.             rtype = SGN;
  1063.             break;
  1064.         case LOR:
  1065.             rtype = UND;
  1066.             if (v1.type==UND)
  1067.                 break;
  1068.             if (rv1==0) {
  1069.                 if (v2.type==UND)
  1070.                     break;
  1071.                 rv1 = rv2!=0;
  1072.             } else
  1073.                 rv1 = 1;
  1074.             rtype = SGN;
  1075.             break;
  1076.         case AND:
  1077.             rv1 &= rv2; break;
  1078.         case STAR:
  1079.             rv1 *= rv2; break;
  1080.         case PLUS:
  1081.             rv1 += rv2; break;
  1082.         case MINUS:
  1083.             rv1 -= rv2; break;
  1084.         case UMINUS:
  1085.             if (v1.type==UND)
  1086.                 rtype = UND;
  1087.             rv1 = -rv1; break;
  1088.         case OR:
  1089.             rv1 |= rv2; break;
  1090.         case CIRC:
  1091.             rv1 ^= rv2; break;
  1092.         case TILDE:
  1093.             rv1 = ~rv1; break;
  1094.         case NOT:
  1095.             rv1 = !rv1; if (rtype!=UND) rtype = SGN; break;
  1096.         case SLASH:
  1097.             if (rv2==0) {
  1098.                 rtype = UND;
  1099.                 break;
  1100.             }
  1101.             if (rtype==UNS)
  1102.                 rv1 /= (unsigned long)rv2;
  1103.             else
  1104.                 rv1 /= rv2;
  1105.             break;
  1106.         case PCT:
  1107.             if (rv2==0) {
  1108.                 rtype = UND;
  1109.                 break;
  1110.             }
  1111.             if (rtype==UNS)
  1112.                 rv1 %= (unsigned long)rv2;
  1113.             else
  1114.                 rv1 %= rv2;
  1115.             break;
  1116.         case COLON:
  1117.             if (op[-1] != QUEST)
  1118.                 error(CPPERROR, "Bad ?: in #if/endif");
  1119.             else {
  1120.                 op--;
  1121.                 if ((--vp)->val==0)
  1122.                     v1 = v2;
  1123.                 rtype = v1.type;
  1124.                 rv1 = v1.val;
  1125.             }
  1126.             break;
  1127.         case DEFINED:
  1128.             break;
  1129.         default:
  1130.             error(CPPERROR, "Eval botch (unknown operator)");
  1131.             return 1;
  1132.         }
  1133. /*lint +e574 +e644 */
  1134.         v1.val = rv1;
  1135.         v1.type = rtype;
  1136. #ifdef BUG_LCC_CORRECTED
  1137.         *vp++ = v1;
  1138. #else
  1139.         *vp = v1;
  1140.         vp++;
  1141. #endif
  1142.     }
  1143.     return 0;
  1144. }
  1145.  
  1146. static struct value tokval(Token *tp)
  1147. {
  1148.     struct value v;
  1149.     Nlist *np;
  1150.     int i, base, c;
  1151.     unsigned long n;
  1152.     uchar *p;
  1153.  
  1154.     v.type = SGN;
  1155.     v.val = 0;
  1156.     switch (tp->type) {
  1157.  
  1158.     case NAME:
  1159.         v.val = 0;
  1160.         break;
  1161.  
  1162.     case NAME1:
  1163.         if ((np = cpplookup(tp)) != NULL && np->flag&ISDEFINED)
  1164.             v.val = 1;
  1165.         break;
  1166.  
  1167.     case NUMBER:
  1168.         n = 0;
  1169.         base = 10;
  1170.         p = tp->t;
  1171.         c = p[tp->len];
  1172.         p[tp->len] = '\0';
  1173.         if (*p=='0') {
  1174.             base = 8;
  1175.             if (p[1]=='x' || p[1]=='X') {
  1176.                 base = 16;
  1177.                 p++;
  1178.             }
  1179.             p++;
  1180.         }
  1181.         for (;; p++) {
  1182.             if ((i = digit(*p)) < 0)
  1183.                 break;
  1184.             if (i>=base)
  1185.                 error(CPPWARNING,
  1186.                   "Bad digit in number %t", tp);
  1187.             n *= base;
  1188.             n += i;
  1189.         }
  1190.         if (n>=0x80000000 && base!=10)
  1191.             v.type = UNS;
  1192.         for (; *p; p++) {
  1193.             if (*p=='u' || *p=='U')
  1194.                 v.type = UNS;
  1195.             else if (*p=='l' || *p=='L')
  1196.                 ;
  1197.             else {
  1198.                 error(CPPERROR,
  1199.                   "Bad number %t in #if/#elsif", tp);
  1200.                 break;
  1201.             }
  1202.         }
  1203.         v.val = n;
  1204.         tp->t[tp->len] = (unsigned char)c;
  1205.         break;
  1206.  
  1207.     case CCON:
  1208.         n = 0;
  1209.         p = tp->t;
  1210.         if (*p=='L') {
  1211.             p += 1;
  1212.             error(CPPWARNING, "Wide char constant value undefined");
  1213.         }
  1214.         p += 1;
  1215.         if (*p=='\\') {
  1216.             p += 1;
  1217.             if ((i = digit(*p))>=0 && i<=7) {
  1218.                 n = i;
  1219.                 p += 1;
  1220.                 if ((i = digit(*p))>=0 && i<=7) {
  1221.                     p += 1;
  1222.                     n <<= 3;
  1223.                     n += i;
  1224.                     if ((i = digit(*p))>=0 && i<=7) {
  1225.                         p += 1;
  1226.                         n <<= 3;
  1227.                         n += i;
  1228.                     }
  1229.                 }
  1230.             } else if (*p=='x') {
  1231.                 p += 1;
  1232.                 while ((i = digit(*p))>=0 && i<=15) {
  1233.                     p += 1;
  1234.                     n <<= 4;
  1235.                     n += i;
  1236.                 }
  1237.             } else {
  1238.                 static char cvcon[]
  1239.                   = "a\ab\bf\fn\nr\rt\tv\v''\"\"??\\\\";
  1240.                 for (i=0; i<sizeof(cvcon); i+=2) {
  1241.                     if (*p == cvcon[i]) {
  1242.                         n = cvcon[i+1];
  1243.                         break;
  1244.                     }
  1245.                 }
  1246.                 p += 1;
  1247.                 if (i>=sizeof(cvcon))
  1248.                     error(CPPWARNING,
  1249.                      "Undefined escape in character constant");
  1250.             }
  1251.         } else if (*p=='\'')
  1252.             error(CPPERROR, "Empty character constant");
  1253.         else
  1254.             n = *p++;
  1255.         if (*p!='\'')
  1256.             error(CPPWARNING, "Multibyte character constant undefined");
  1257.         else if (n>127)
  1258.             error(CPPWARNING, "Character constant taken as not signed");
  1259.         v.val = n;
  1260.         break;
  1261.  
  1262.     case STRING:
  1263.         error(CPPERROR, "String in #if/#elsif");
  1264.         break;
  1265.     }
  1266.     return v;
  1267. }
  1268.  
  1269. static int digit(int i)
  1270. {
  1271.     if ('0'<=i && i<='9')
  1272.         i -= '0';
  1273.     else if ('a'<=i && i<='f')
  1274.         i -= 'a'-10;
  1275.     else if ('A'<=i && i<='F')
  1276.         i -= 'A'-10;
  1277.     else
  1278.         i = -1;
  1279.     return i;
  1280. }
  1281.  
  1282. /*
  1283.  * A hideset is a null-terminated array of Nlist pointers.
  1284.  * They are referred to by indices in the hidesets array.
  1285.  * Hideset 0 is empty.
  1286.  */
  1287.  
  1288. #define    HSSIZ    32
  1289. typedef    Nlist    **Hideset;
  1290. static Hideset    *hidesets;
  1291. static int    nhidesets = 0;
  1292. static int    maxhidesets = 3;
  1293. static int    inserths(Hideset, Hideset, Nlist *);
  1294.  
  1295. /*
  1296.  * Test for membership in a hideset
  1297.  */
  1298. static int checkhideset(int hs, Nlist *np)
  1299. {
  1300.     Hideset hsp;
  1301.  
  1302.     if (hs>=nhidesets)
  1303.         abort();
  1304.     for (hsp = hidesets[hs]; *hsp; hsp++) {
  1305.         if (*hsp == np)
  1306.             return 1;
  1307.     }
  1308.     return 0;
  1309. }
  1310.  
  1311. /*
  1312.  * Return the (possibly new) hideset obtained by adding np to hs.
  1313.  */
  1314. static int newhideset(int hs, Nlist *np)
  1315. {
  1316.     int i, len;
  1317.     Nlist *nhs[HSSIZ+3];
  1318.     Hideset hs1, hs2;
  1319.  
  1320.     len = inserths(nhs, hidesets[hs], np);
  1321.     for (i=0; i<nhidesets; i++) {
  1322.         for (hs1=nhs, hs2=hidesets[i]; *hs1==*hs2; hs1++, hs2++)
  1323.             if (*hs1 == NULL)
  1324.                 return i;
  1325.     }
  1326.     if (len>=HSSIZ)
  1327.         return hs;
  1328.     if (nhidesets >= maxhidesets) {
  1329.         maxhidesets = 3*maxhidesets/2+1;
  1330.         hidesets = (Hideset *)realloc(hidesets, (sizeof (Hideset *))*maxhidesets);
  1331.     }
  1332.     hs1 = (Hideset)domalloc(len*sizeof(Hideset));
  1333.     memmove(hs1, nhs, len*sizeof(Hideset));
  1334.     hidesets[nhidesets] = hs1;
  1335.     return nhidesets++;
  1336. }
  1337.  
  1338. static int inserths(Hideset dhs, Hideset shs, Nlist *np)
  1339. {
  1340.     Hideset odhs = dhs;
  1341.  
  1342.     while (*shs && *shs < np)
  1343.         *dhs++ = *shs++;
  1344.     if (*shs != np)
  1345.         *dhs++ = np;
  1346.     do {
  1347.         *dhs++ = *shs;
  1348.     } while (*shs++);
  1349.     return dhs - odhs;
  1350. }
  1351.  
  1352. /*
  1353.  * Hideset union
  1354.  */
  1355. static int unionhideset(int hs1, int hs2)
  1356. {
  1357.     Hideset hp;
  1358.  
  1359.     for (hp = hidesets[hs2]; *hp; hp++)
  1360.         hs1 = newhideset(hs1, *hp);
  1361.     return hs1;
  1362. }
  1363.  
  1364. static void iniths(void)
  1365. {
  1366.     hidesets = (Hideset *)domalloc(maxhidesets*sizeof(Hideset *));
  1367.     hidesets[0] = (Hideset)domalloc(sizeof(Hideset));
  1368.     *hidesets[0] = NULL;
  1369.     nhidesets++;
  1370. }
  1371. #if 0
  1372. static void prhideset(int hs)
  1373. {
  1374.     Hideset np;
  1375.  
  1376.     for (np = hidesets[hs]; *np; np++) {
  1377.         fprintf(stderr, (char*)(*np)->name, (*np)->len);
  1378.         fprintf(stderr, " ");
  1379.     }
  1380. }
  1381. #endif
  1382. static Includelist    includelist[NINCLUDE];
  1383.  
  1384. static unsigned char    *objname;
  1385. int IsAbsolutePath(unsigned char *fname)
  1386. {
  1387.     int drive = *fname;
  1388.  
  1389.     if (drive >= 'a' && drive <= 'z') drive -= ' ';
  1390.     if (fname[1] == ':' && (drive >= 'A' && drive <= 'Z'))
  1391.         return(1);
  1392.     if (drive == '\\') return 1;
  1393.     return(0);
  1394. }
  1395. static void doinclude(Tokenrow *trp)
  1396. {
  1397.     unsigned char fname[256], iname[256],*p;
  1398.     Includelist *ip;
  1399.     int angled, len, fd, i;
  1400.  
  1401.     trp->tp += 1;
  1402.     if (trp->tp>=trp->lp)
  1403.         goto syntax;
  1404.     if (trp->tp->type!=STRING && trp->tp->type!=LT) {
  1405.         len = trp->tp - trp->bp;
  1406.         expandrow(trp,(unsigned char *) "<include>");
  1407.         trp->tp = trp->bp+len;
  1408.     }
  1409.     if (trp->tp->type==STRING) {
  1410.         len = trp->tp->len-2;
  1411.         if (len > sizeof(fname) - 1)
  1412.             len = sizeof(fname) - 1;
  1413.         strncpy(fname, trp->tp->t+1, len);
  1414.         angled = 0;
  1415.     } else {
  1416.         len = 0;
  1417.         trp->tp++;
  1418.         while (trp->tp->type!=GT) {
  1419.             if (trp->tp>trp->lp || len+trp->tp->len+2 >= sizeof(fname))
  1420.                 goto syntax;
  1421.             strncpy(fname+len, trp->tp->t, trp->tp->len);
  1422.             len += trp->tp->len;
  1423.             trp->tp++;
  1424.         }
  1425.         angled = 1;
  1426.     }
  1427.     trp->tp += 2;
  1428.     if (trp->tp < trp->lp || len==0)
  1429.         goto syntax;
  1430.     fname[len] = '\0';
  1431.     p = fname;
  1432.     while (*p) {
  1433.         if (*p == '/') *p = '\\';
  1434.         p++;
  1435.     }
  1436.     if (IsAbsolutePath(fname)) {
  1437.         fd = DoOpen(fname);
  1438.         strcpy(iname, fname);
  1439.     } else for (fd = -1,i=NINCLUDE-1; i>=0; i--) {
  1440.         ip = &includelist[i];
  1441.         if (ip->file==NULL || ip->deleted || (angled && ip->always==0))
  1442.             continue;
  1443.         if (strlen(fname)+strlen(ip->file)+2 > sizeof(iname))
  1444.             continue;
  1445.         sprintf(iname,"%s%c%s",ip->file,PATH_SEPARATOR,fname);
  1446.         if ((fd = DoOpen(iname)) >= 0)
  1447.             break;
  1448.     }
  1449. #ifndef LRC
  1450.     if ( Mflag>1 || (!angled&&Mflag==1)) {
  1451.         if (Mflag > 1) PrintIncludeTree(iname);
  1452.         else if (incdepth == 0) {
  1453.             printf("%s --> %s\n",objname,iname);
  1454.         }
  1455.     }
  1456. #endif
  1457.     if (fd >= 0) {
  1458.         if (++incdepth > 10)
  1459.             error(CPPFATAL, "#include too deeply nested");
  1460.         setsource((char*)newstring((uchar*)iname, strlen(iname), 0), fd, NULL);
  1461.         genline();
  1462.     } else {
  1463.         trp->tp = trp->bp+2;
  1464.         error(CPPERROR, "Could not find include file %r", trp);
  1465.     }
  1466.     return;
  1467. syntax:
  1468.     error(CPPERROR, "Syntax error in #include");
  1469.     return;
  1470. }
  1471.  
  1472. /*
  1473.  * Generate a line directive for cursource
  1474.  */
  1475. static int genline(void)
  1476. {
  1477.     static Token ta = { UNCLASS, 0, 0, 0 };
  1478.     static Tokenrow tr = { &ta, &ta, &ta+1, 1 };
  1479.     uchar *p;
  1480.  
  1481.     ta.t = p = (uchar*)OutputPtr;
  1482.     if (outputLine) {
  1483.         strcpy((char*)p, "#line ");
  1484.         p += sizeof("#line ")-1;
  1485.     }
  1486.     else {
  1487.         strcpy((char *)p,"# ");
  1488.         p +=sizeof("# ")-1;
  1489.     }
  1490.     p = (uchar*)outnum((char*)p, cursource->line);
  1491.     *p++ = ' '; *p++ = '"';
  1492.     if (cursource->filename[0]!=PATH_SEPARATOR && wd[0]) {
  1493.         strcpy((char*)p, wd);
  1494.         p += strlen(wd);
  1495.         *p++ = PATH_SEPARATOR;
  1496.     }
  1497.     strcpy((char*)p, cursource->filename);
  1498.     p += strlen((char*)p);
  1499.     *p++ = '"'; *p++ = '\n';
  1500.     ta.len = (char*)p-OutputPtr;
  1501.     OutputPtr = (char*)p;
  1502.     tr.tp = tr.bp;
  1503.     return(puttokens(&tr));
  1504. }
  1505.  
  1506. static void setobjname(unsigned char *f)
  1507. {
  1508.     if (objname == NULL) {
  1509.         objname = (char*)domalloc(255);
  1510.     }
  1511.     strcpy(objname,f);
  1512. }
  1513.  
  1514. /*
  1515.  * lexical FSM encoding
  1516.  *   when in state state, and one of the characters
  1517.  *   in ch arrives, enter nextstate.
  1518.  *   States >= S_SELF are either final, or at least require special action.
  1519.  *   In 'fsm' there is a line for each state X charset X nextstate.
  1520.  *   List chars that overwrite previous entries later (e.g. C_ALPH
  1521.  *   can be overridden by '_' by a later entry; and C_XX is the
  1522.  *   the universal set, and should always be first.
  1523.  *   States above S_SELF are represented in the big table as negative values.
  1524.  *   S_SELF and S_SELFB encode the resulting token type in the upper bits.
  1525.  *   These actions differ in that S_SELF doesn't have a lookahead char,
  1526.  *   S_SELFB does.
  1527.  *
  1528.  *   The encoding is blown out into a big table for time-efficiency.
  1529.  *   Entries have
  1530.  *      nextstate: 6 bits; ?\ marker: 1 bit; tokentype: 9 bits.
  1531.  */
  1532.  
  1533. #define    MAXSTATE 32
  1534. #define    ACT(tok,act)    ((tok<<7)+act)
  1535. #define    QBSBIT    0100
  1536. #define    GETACT(st)    (st>>7)&0x1ff
  1537.  
  1538. /* character classes */
  1539. #define    C_WS    1
  1540. #define    C_ALPH    2
  1541. #define    C_NUM    3
  1542. #define    C_EOF    4
  1543. #define    C_XX    5
  1544.  
  1545. enum state {
  1546.     START=0, NUM1, NUM2, NUM3, ID1, ST1, ST2, ST3, COM1, COM2, COM3, COM4,
  1547.     CC1, CC2, WS1, PLUS1, MINUS1, STAR1, SLASH1, PCT1, SHARP1,
  1548.     CIRC1, GT1, GT2, LT1, LT2, OR1, AND1, ASG1, NOT1, DOTS1,
  1549.     S_SELF=MAXSTATE, S_SELFB, S_EOF, S_NL, S_EOFSTR,
  1550.     S_STNL, S_COMNL, S_EOFCOM, S_COMMENT, S_EOB, S_WS, S_NAME
  1551. };
  1552.  
  1553. struct    fsm {
  1554.     int    state;        /* if in this state */
  1555.     uchar    ch[4];        /* and see one of these characters */
  1556.     int    nextstate;    /* enter this state if +ve */
  1557. };
  1558.  
  1559. static struct fsm fsm[] = {
  1560.     /* start state */
  1561.     START,    { C_XX },    ACT(UNCLASS,S_SELF),
  1562.     START,    { ' ', '\t', '\v'  },    WS1,
  1563.     START,    { C_NUM },    NUM1,
  1564.     START,    { '.' },    NUM3,
  1565.     START,    { C_ALPH },    ID1,
  1566.     START,    { 'L' },    ST1,
  1567.     START,    { '"' },    ST2,
  1568.     START,    { '\'' },    CC1,
  1569.     START,    { '/' },    COM1,
  1570.     START,    { EOFC },    S_EOF,
  1571.     START,    { '\n' },    S_NL,
  1572.     START,  { '\r' },    S_NL,
  1573.     START,    { '-' },    MINUS1,
  1574.     START,    { '+' },    PLUS1,
  1575.     START,    { '<' },    LT1,
  1576.     START,    { '>' },    GT1,
  1577.     START,    { '=' },    ASG1,
  1578.     START,    { '!' },    NOT1,
  1579.     START,    { '&' },    AND1,
  1580.     START,    { '|' },    OR1,
  1581.     START,    { '#' },    SHARP1,
  1582.     START,    { '%' },    PCT1,
  1583.     START,    { '[' },    ACT(SBRA,S_SELF),
  1584.     START,    { ']' },    ACT(SKET,S_SELF),
  1585.     START,    { '(' },    ACT(LP,S_SELF),
  1586.     START,    { ')' },    ACT(RP,S_SELF),
  1587.     START,    { '*' },    STAR1,
  1588.     START,    { ',' },    ACT(COMMA,S_SELF),
  1589.     START,    { '?' },    ACT(QUEST,S_SELF),
  1590.     START,    { ':' },    ACT(COLON,S_SELF),
  1591.     START,    { ';' },    ACT(SEMIC,S_SELF),
  1592.     START,    { '{' },    ACT(CBRA,S_SELF),
  1593.     START,    { '}' },    ACT(CKET,S_SELF),
  1594.     START,    { '~' },    ACT(TILDE,S_SELF),
  1595.     START,    { '^' },    CIRC1,
  1596.  
  1597.     /* saw a digit */
  1598.     NUM1,    { C_XX },    ACT(NUMBER,S_SELFB),
  1599.     NUM1,    { C_NUM, C_ALPH, '.' },    NUM1,
  1600.     NUM1,    { 'E', 'e' },    NUM2,
  1601.     NUM1,    { '_' },    ACT(NUMBER,S_SELFB),
  1602.  
  1603.     /* saw possible start of exponent, digits-e */
  1604.     NUM2,    { C_XX },    ACT(NUMBER,S_SELFB),
  1605.     NUM2,    { '+', '-' },    NUM1,
  1606.     NUM2,    { C_NUM, C_ALPH },    NUM1,
  1607.     NUM2,    { '_' },    ACT(NUMBER,S_SELFB),
  1608.  
  1609.     /* saw a '.', which could be a number or an operator */
  1610.     NUM3,    { C_XX },    ACT(DOT,S_SELFB),
  1611.     NUM3,    { '.' },    DOTS1,
  1612.     NUM3,    { C_NUM },    NUM1,
  1613.  
  1614.     DOTS1,    { C_XX },    ACT(UNCLASS, S_SELFB),
  1615.     DOTS1,    { C_NUM },    NUM1,
  1616.     DOTS1,    { '.' },    ACT(ELLIPS, S_SELF),
  1617.  
  1618.     /* saw a letter or _ */
  1619.     ID1,    { C_XX },    ACT(NAME,S_NAME),
  1620.     ID1,    { C_ALPH, C_NUM },    ID1,
  1621.  
  1622.     /* saw L (start of wide string?) */
  1623.     ST1,    { C_XX },    ACT(NAME,S_NAME),
  1624.     ST1,    { C_ALPH, C_NUM },    ID1,
  1625.     ST1,    { '"' },    ST2,
  1626.     ST1,    { '\'' },    CC1,
  1627.  
  1628.     /* saw " beginning string */
  1629.     ST2,    { C_XX },    ST2,
  1630.     ST2,    { '"' },    ACT(STRING, S_SELF),
  1631.     ST2,    { '\\' },    ST3,
  1632.     ST2,    { '\n' },    S_STNL,
  1633.     ST2,    { EOFC },    S_EOFSTR,
  1634.  
  1635.     /* saw \ in string */
  1636.     ST3,    { C_XX },    ST2,
  1637.     ST3,    { '\n' },    S_STNL,
  1638.     ST3,    { EOFC },    S_EOFSTR,
  1639.  
  1640.     /* saw ' beginning character const */
  1641.     CC1,    { C_XX },    CC1,
  1642.     CC1,    { '\'' },    ACT(CCON, S_SELF),
  1643.     CC1,    { '\\' },    CC2,
  1644.     CC1,    { '\n' },    S_STNL,
  1645.     CC1,    { EOFC },    S_EOFSTR,
  1646.  
  1647.     /* saw \ in ccon */
  1648.     CC2,    { C_XX },    CC1,
  1649.     CC2,    { '\n' },    S_STNL,
  1650.     CC2,    { EOFC },    S_EOFSTR,
  1651.  
  1652.     /* saw /, perhaps start of comment */
  1653.     COM1,    { C_XX },    ACT(SLASH, S_SELFB),
  1654.     COM1,    { '=' },    ACT(ASSLASH, S_SELF),
  1655.     COM1,    { '*' },    COM2,
  1656.     COM1,    { '/' },    COM4,
  1657.  
  1658.     /* saw "/ *", start of comment */
  1659.     COM2,    { C_XX },    COM2,
  1660.     COM2,    { '\n' },    S_COMNL,
  1661.     COM2,    { '*' },    COM3,
  1662.     COM2,    { EOFC },    S_EOFCOM,
  1663.  
  1664.     /* saw the * possibly ending a comment */
  1665.     COM3,    { C_XX },    COM2,
  1666.     COM3,    { '\n' },    S_COMNL,
  1667.     COM3,    { '*' },    COM3,
  1668.     COM3,    { '/' },    S_COMMENT,
  1669.  
  1670.     /* // comment */
  1671.     COM4,    { C_XX },    COM4,
  1672.     COM4,    { '\n' },    S_NL,
  1673.     COM4,    { EOFC },    S_EOFCOM,
  1674.  
  1675.     /* saw white space, eat it up */
  1676.     WS1,    { C_XX },    S_WS,
  1677.     WS1,    { ' ', '\t', '\v' },    WS1,
  1678.  
  1679.     /* saw -, check --, -=, -> */
  1680.     MINUS1,    { C_XX },    ACT(MINUS, S_SELFB),
  1681.     MINUS1,    { '-' },    ACT(MMINUS, S_SELF),
  1682.     MINUS1,    { '=' },    ACT(ASMINUS,S_SELF),
  1683.     MINUS1,    { '>' },    ACT(ARROW,S_SELF),
  1684.  
  1685.     /* saw +, check ++, += */
  1686.     PLUS1,    { C_XX },    ACT(PLUS, S_SELFB),
  1687.     PLUS1,    { '+' },    ACT(PPLUS, S_SELF),
  1688.     PLUS1,    { '=' },    ACT(ASPLUS, S_SELF),
  1689.  
  1690.     /* saw <, check <<, <<=, <= */
  1691.     LT1,    { C_XX },    ACT(LT, S_SELFB),
  1692.     LT1,    { '<' },    LT2,
  1693.     LT1,    { '=' },    ACT(LEQ, S_SELF),
  1694.     LT2,    { C_XX },    ACT(LSH, S_SELFB),
  1695.     LT2,    { '=' },    ACT(ASLSH, S_SELF),
  1696.  
  1697.     /* saw >, check >>, >>=, >= */
  1698.     GT1,    { C_XX },    ACT(GT, S_SELFB),
  1699.     GT1,    { '>' },    GT2,
  1700.     GT1,    { '=' },    ACT(GEQ, S_SELF),
  1701.     GT2,    { C_XX },    ACT(RSH, S_SELFB),
  1702.     GT2,    { '=' },    ACT(ASRSH, S_SELF),
  1703.  
  1704.     /* = */
  1705.     ASG1,    { C_XX },    ACT(ASGN, S_SELFB),
  1706.     ASG1,    { '=' },    ACT(EQ, S_SELF),
  1707.  
  1708.     /* ! */
  1709.     NOT1,    { C_XX },    ACT(NOT, S_SELFB),
  1710.     NOT1,    { '=' },    ACT(NEQ, S_SELF),
  1711.  
  1712.     /* & */
  1713.     AND1,    { C_XX },    ACT(AND, S_SELFB),
  1714.     AND1,    { '&' },    ACT(LAND, S_SELF),
  1715.     AND1,    { '=' },    ACT(ASAND, S_SELF),
  1716.  
  1717.     /* | */
  1718.     OR1,    { C_XX },    ACT(OR, S_SELFB),
  1719.     OR1,    { '|' },    ACT(LOR, S_SELF),
  1720.     OR1,    { '=' },    ACT(ASOR, S_SELF),
  1721.  
  1722.     /* # */
  1723.     SHARP1,    { C_XX },    ACT(SHARP, S_SELFB),
  1724.     SHARP1,    { '#' },    ACT(DSHARP, S_SELF),
  1725.  
  1726.     /* % */
  1727.     PCT1,    { C_XX },    ACT(PCT, S_SELFB),
  1728.     PCT1,    { '=' },    ACT(ASPCT, S_SELF),
  1729.  
  1730.     /* * */
  1731.     STAR1,    { C_XX },    ACT(STAR, S_SELFB),
  1732.     STAR1,    { '=' },    ACT(ASSTAR, S_SELF),
  1733.  
  1734.     /* ^ */
  1735.     CIRC1,    { C_XX },    ACT(CIRC, S_SELFB),
  1736.     CIRC1,    { '=' },    ACT(ASCIRC, S_SELF),
  1737.  
  1738.     -1
  1739. };
  1740.  
  1741. /* first index is char, second is state */
  1742. /* increase #states to power of 2 to encourage use of shift */
  1743. static short    bigfsm[256][MAXSTATE];
  1744.  
  1745. static void expandlex(void)
  1746. {
  1747.     /*const*/ struct fsm *fp;
  1748.     int i, j, nstate;
  1749.  
  1750.     for (fp = fsm; fp->state>=0; fp++) {
  1751.         for (i=0; fp->ch[i]; i++) {
  1752.             nstate = fp->nextstate;
  1753.             if (nstate >= S_SELF)
  1754.                 nstate = ~nstate;
  1755.             switch (fp->ch[i]) {
  1756.  
  1757.             case C_XX:        /* random characters */
  1758.                 for (j=0; j<256; j++)
  1759.                     bigfsm[j][fp->state] = (short)nstate;
  1760.                 continue;
  1761.             case C_ALPH:
  1762.                 for (j=0; j<=256; j++)
  1763.                     if ('a'<=j&&j<='z' || 'A'<=j&&j<='Z'
  1764.                       || j=='_')
  1765.                         bigfsm[j][fp->state] = (short)nstate;
  1766.                 continue;
  1767.             case C_NUM:
  1768.                 for (j='0'; j<='9'; j++)
  1769.                     bigfsm[j][fp->state] = (short)nstate;
  1770.                 continue;
  1771.             default:
  1772.                 bigfsm[fp->ch[i]][fp->state] = (short)nstate;
  1773.             }
  1774.         }
  1775.     }
  1776.  
  1777.     /* install special cases for ? (trigraphs),  \ (splicing), runes, and EOB */
  1778.     for (i=0; i<MAXSTATE; i++) {
  1779.         for (j=0; j<0xFF; j++)
  1780.             if (j=='?' || j=='\\') {
  1781.                 if (bigfsm[j][i]>0)
  1782.                     bigfsm[j][i] = (short)~bigfsm[j][i];
  1783.                 bigfsm[j][i] &= ~QBSBIT;
  1784.             }
  1785.         bigfsm[EOB][i] = ~S_EOB;
  1786.         if (bigfsm[EOFC][i]>=0)
  1787.             bigfsm[EOFC][i] = ~S_EOF;
  1788.     }
  1789. }
  1790.  
  1791. static void fixlex(void)
  1792. {
  1793.     /* do C++ comments? */
  1794.     if (Cplusplus==0)
  1795.         bigfsm['/'][COM1] = bigfsm['x'][COM1];
  1796. }
  1797.  
  1798. /*
  1799.  * fill in a row of tokens from input, terminated by NL or END
  1800.  * First token is put at trp->lp.
  1801.  * Reset is non-zero when the input buffer can be "rewound."
  1802.  * The value is a flag indicating that possible macros have
  1803.  * been seen in the row.
  1804.  */
  1805. static int gettokens(Tokenrow *trp, int reset)
  1806. {
  1807.     register unsigned int c;
  1808.     int state, oldstate;
  1809.     register uchar *ip;
  1810.     register Token *tp, *maxp;
  1811.     int runelen;
  1812.     Source *s = cursource;
  1813.     int nmac = 0;
  1814.  
  1815.     tp = trp->lp;
  1816.     ip = s->inp;
  1817.     if (reset) {
  1818.         s->lineinc = 0;
  1819.         if (ip>=s->inl) {        /* nothing in buffer */
  1820.             s->inl = s->inb;
  1821.             fillbuf(s);
  1822.             ip = s->inp = s->inb;
  1823.         } else if (ip >= s->inb+(3*INS/4)) {
  1824.             memmove(s->inb, ip, 4+s->inl-ip);
  1825.             s->inl = s->inb+(s->inl-ip);
  1826.             ip = s->inp = s->inb;
  1827.         }
  1828.     }
  1829.     maxp = &trp->bp[trp->max];
  1830.     runelen = 1;
  1831.     for (;;) {
  1832.        continue2:
  1833.         if (tp>=maxp) {
  1834.             trp->lp = tp;
  1835.             tp = growtokenrow(trp);
  1836.             maxp = &trp->bp[trp->max];
  1837.         }
  1838.         tp->type = UNCLASS;
  1839.         tp->hideset = 0;
  1840.         tp->t = ip;
  1841.         tp->wslen = 0;
  1842.         tp->flag = 0;
  1843.         state = START;
  1844.         for (;;) {
  1845.             oldstate = state;
  1846.             c = *ip;
  1847.             if ((state = bigfsm[c][state]) >= 0) {
  1848.                 ip += runelen;
  1849.                 runelen = 1;
  1850.                 continue;
  1851.             }
  1852.             state = ~state;
  1853.         reswitch:
  1854.             switch (state&0177) {
  1855.             case S_SELF:
  1856.                 ip += runelen;
  1857.                 runelen = 1;
  1858.             case S_SELFB:
  1859.                 tp->type = (unsigned char)GETACT(state);
  1860.                 tp->len = ip - tp->t;
  1861.                 tp++;
  1862.                 goto continue2;
  1863.  
  1864.             case S_NAME:    /* like S_SELFB but with nmac check */
  1865.                 tp->type = NAME;
  1866.                 tp->len = ip - tp->t;
  1867.                 nmac |= quicklook(tp->t[0], tp->len>1?tp->t[1]:0);
  1868.                 tp++;
  1869.                 goto continue2;
  1870.  
  1871.             case S_WS:
  1872.                 tp->wslen = ip - tp->t;
  1873.                 tp->t = ip;
  1874.                 state = START;
  1875.                 continue;
  1876.  
  1877.             default:
  1878.                 if ((state&QBSBIT)==0) {
  1879.                     ip += runelen;
  1880.                     runelen = 1;
  1881.                     continue;
  1882.                 }
  1883.                 state &= ~QBSBIT;
  1884.                 s->inp = ip;
  1885.                 if (c=='?') {     /* check trigraph */
  1886.                     if (trigraph(s)) {
  1887.                         state = oldstate;
  1888.                         continue;
  1889.                     }
  1890.                     goto reswitch;
  1891.                 }
  1892.                 if (c=='\\') { /* line-folding */
  1893.                     if (foldline(s)) {
  1894.                         s->lineinc++;
  1895.                         state = oldstate;
  1896.                         continue;
  1897.                     }
  1898.                     goto reswitch;
  1899.                 }
  1900.                 error(CPPWARNING, "Lexical botch in cpp");
  1901.                 ip += runelen;
  1902.                 runelen = 1;
  1903.                 continue;
  1904.  
  1905.             case S_EOB:
  1906.                 s->inp = ip;
  1907.                 fillbuf(cursource);
  1908.                 state = oldstate;
  1909.                 continue;
  1910.  
  1911.             case S_EOF:
  1912.                 tp->type = END;
  1913.                 tp->len = 0;
  1914.                 s->inp = ip;
  1915.                 if (tp!=trp->bp && (tp-1)->type!=NL && cursource->fd!=-1)
  1916.                     error(CPPWARNING,"No newline at end of file");
  1917.                 trp->lp = tp+1;
  1918.                 return nmac;
  1919.  
  1920.             case S_STNL:
  1921.                 error(CPPERROR, "Unterminated string or char const");
  1922.             case S_NL:
  1923.                 tp->t = ip;
  1924.                 tp->type = NL;
  1925.                 tp->len = 1;
  1926.                 tp->wslen = 0;
  1927.                 s->lineinc++;
  1928.                 s->inp = ip+1;
  1929.                 trp->lp = tp+1;
  1930.                 return nmac;
  1931.  
  1932.             case S_EOFSTR:
  1933.                 error(CPPFATAL, "EOF in string or char constant");
  1934.                 break;
  1935.  
  1936.             case S_COMNL:
  1937.                 s->lineinc++;
  1938.                 state = COM2;
  1939.                 ip += runelen;
  1940.                 runelen = 1;
  1941.                 continue;
  1942.  
  1943.             case S_EOFCOM:
  1944.                 error(CPPWARNING, "EOF inside comment");
  1945.                 --ip;
  1946.             case S_COMMENT:
  1947.                 ++ip;
  1948.                 tp->t = ip;
  1949.                 tp->t[-1] = ' ';
  1950.                 tp->wslen = 1;
  1951.                 state = START;
  1952.                 continue;
  1953.             }
  1954.             break;
  1955.         }
  1956.         ip += runelen;
  1957.         runelen = 1;
  1958.         tp->len = ip - tp->t;
  1959.         tp++;
  1960.     }
  1961. }
  1962.  
  1963. /* have seen ?; handle the trigraph it starts (if any) else 0 */
  1964. static int trigraph(Source *s)
  1965. {
  1966.     int c;
  1967.  
  1968.     while (s->inp+2 >= s->inl && fillbuf(s)!=EOF)
  1969.         ;
  1970.     if (s->inp[1]!='?')
  1971.         return 0;
  1972.     c = 0;
  1973.     switch(s->inp[2]) {
  1974.     case '=':
  1975.         c = '#'; break;
  1976.     case '(':
  1977.         c = '['; break;
  1978.     case '/':
  1979.         c = '\\'; break;
  1980.     case ')':
  1981.         c = ']'; break;
  1982.     case '\'':
  1983.         c = '^'; break;
  1984.     case '<':
  1985.         c = '{'; break;
  1986.     case '!':
  1987.         c = '|'; break;
  1988.     case '>':
  1989.         c = '}'; break;
  1990.     case '-':
  1991.         c = '~'; break;
  1992.     }
  1993.     if (c) {
  1994.         *s->inp = (unsigned char)c;
  1995.         memmove(s->inp+1, s->inp+3, s->inl-s->inp+2);
  1996.         s->inl -= 2;
  1997.     }
  1998.     return c;
  1999. }
  2000.  
  2001. static int foldline(Source *s)
  2002. {
  2003.     while (s->inp+1 >= s->inl && fillbuf(s)!=EOF)
  2004.         ;
  2005.     if (s->inp[1] == '\n') {
  2006.         memmove(s->inp, s->inp+2, s->inl-s->inp+3);
  2007.         s->inl -= 2;
  2008.         return 1;
  2009.     }
  2010.     return 0;
  2011. }
  2012.  
  2013. static int fillbuf(Source *s)
  2014. {
  2015.     int n;
  2016.  
  2017.     if (s->fd<0 || (n=DoRead(s->fd, (char *)s->inl, INS/8)) <= 0)
  2018.         n = 0;
  2019.     
  2020.     s->inl += n;
  2021.     s->inl[0] = s->inl[1]= s->inl[2]= s->inl[3] = EOB;
  2022.     if (n==0) {
  2023.         s->inl[0] = s->inl[1]= s->inl[2]= s->inl[3] = EOFC;
  2024.         return EOF;
  2025.     }
  2026.     return 0;
  2027. }
  2028.  
  2029. /*
  2030.  * Push down to new source of characters.
  2031.  * If fd>0 and str==NULL, then from a file `name';
  2032.  * if fd==-1 and str, then from the string.
  2033.  */
  2034. static Source *setsource(unsigned char *name, int fd, char *str)
  2035. {
  2036.     Source *s = new(Source);
  2037.     int len;
  2038.  
  2039.     s->line = 1;
  2040.     s->lineinc = 0;
  2041.     s->fd = fd;
  2042.     s->filename = name;
  2043.     s->next = cursource;
  2044.     s->ifdepth = 0;
  2045.     cursource = s;
  2046.     /* slop at right for EOB */
  2047.     if (str) {
  2048.         len = strlen(str);
  2049.         s->inb = domalloc(len+4);
  2050.         s->inp = s->inb;
  2051.         strncpy((char *)s->inp, str, len);
  2052.     }
  2053.     else {
  2054.         s->inb = domalloc(INS+4);
  2055.         s->inp = s->inb;
  2056.         len = 0;
  2057.     }
  2058.     s->inl = s->inp+len;
  2059.     s->inl[0] = s->inl[1] = EOB;
  2060. #ifndef LRC
  2061.     if (fd >= 0 && xrefFile) {
  2062.         fprintf(xrefFile,"f %s\n",name);
  2063.         AddToFileTable(name);
  2064.     }
  2065. #endif
  2066.     return s;
  2067. }
  2068.  
  2069. static void unsetsource(void)
  2070. {
  2071.     Source *s = cursource;
  2072.  
  2073.     if (s->fd>=0) {
  2074.         DoClose(s->fd);
  2075.         dofree(s->inb);
  2076.     }
  2077.     cursource = s->next;
  2078.     dofree(s);
  2079. }
  2080.  
  2081.  
  2082. /*
  2083.  * do a macro definition.  tp points to the name being defined in the line
  2084.  */
  2085. static Nlist *dodefine(Tokenrow *trp)
  2086. {
  2087.     Token *tp;
  2088.     Nlist *np;
  2089.     Tokenrow *def, *args;
  2090.  
  2091.     tp = trp->tp+1;
  2092.     if (tp>=trp->lp || tp->type!=NAME) {
  2093.         error(CPPERROR, "#defined token is not a name");
  2094.         return NULL;
  2095.     }
  2096.     np = InstallToken(tp);
  2097.     if (np->flag&ISUNCHANGE) {
  2098.         error(CPPWARNING, "#defined token %t can't be redefined", tp);
  2099.         return NULL;
  2100.     }
  2101.     /* collect arguments */
  2102.     tp += 1;
  2103.     args = NULL;
  2104.     if (tp<trp->lp && tp->type==LP && tp->wslen==0) {
  2105.         /* macro with args */
  2106.         int narg = 0;
  2107.         tp += 1;
  2108.         args = new(Tokenrow);
  2109.         maketokenrow(2, args);
  2110.         if (tp->type!=RP) {
  2111.             int err = 0;
  2112.             for (;;) {
  2113.                 Token *atp;
  2114.                 if (tp->type!=NAME) {
  2115.                     err++;
  2116.                     break;
  2117.                 }
  2118.                 if (narg>=args->max)
  2119.                     growtokenrow(args);
  2120.                 for (atp=args->bp; atp<args->lp; atp++)
  2121.                     if (atp->len==tp->len
  2122.                      && strncmp((char*)atp->t, (char*)tp->t, tp->len)==0)
  2123.                         error(CPPERROR, "Duplicate macro argument");
  2124. #ifdef BUG_LCC_CORRECTED
  2125.                 *args->lp++ = *tp;
  2126. #else
  2127.                 memcpy(args->lp,tp,sizeof(Token));
  2128.                 args->lp++;
  2129. #endif
  2130.                 narg++;
  2131.                 tp += 1;
  2132.                 if (tp->type==RP)
  2133.                     break;
  2134.                 if (tp->type!=COMMA) {
  2135.                     err++;
  2136.                     break;
  2137.                 }
  2138.                 tp += 1;
  2139.             }
  2140.             if (err) {
  2141.                 error(CPPERROR, "Syntax error in macro parameters");
  2142.                 return NULL;
  2143.             }
  2144.         }
  2145.         tp += 1;
  2146.     }
  2147.     trp->tp = tp;
  2148.     if (((trp->lp)-1)->type==NL)
  2149.         trp->lp -= 1;
  2150.     def = normtokenrow(trp);
  2151.     if (np->flag&ISDEFINED) {
  2152.         if (comparetokens(def, np->vp)
  2153.          || (np->ap==NULL) != (args==NULL)
  2154.          || np->ap && comparetokens(args, np->ap))
  2155.             error(CPPERROR, "Macro redefinition of %t", trp->bp+2);
  2156.     }
  2157.     if (args) {
  2158.         Tokenrow *tap;
  2159.         tap = normtokenrow(args);
  2160.         dofree(args->bp);
  2161.         args = tap;
  2162.     }
  2163.     np->ap = args;
  2164.     np->vp = def;
  2165.     np->flag |= ISDEFINED;
  2166.     np->srcline = (unsigned short)cursource->line;
  2167.     np->filename = cursource->filename;
  2168.     return np;
  2169. }
  2170.  
  2171. /*
  2172.  * Definition received via -D or -U
  2173.  */
  2174. static Nlist *doadefine(Tokenrow *trp, int type)
  2175. {
  2176.     Nlist *np;
  2177.     static Token onetoken[1] = {{ NUMBER, 0, 0, 0, 1, (uchar*)"1" }};
  2178.     static Tokenrow onetr = { onetoken, onetoken, onetoken+1, 1 };
  2179.  
  2180.     trp->tp = trp->bp;
  2181.     if (type=='U') {
  2182.         if (trp->lp-trp->tp != 2 || trp->tp->type!=NAME)
  2183.             goto syntax;
  2184.         if ((np = cpplookup(trp->tp)) == NULL)
  2185.             return NULL;
  2186.         np->flag &= ~ISDEFINED;
  2187.         return NULL;
  2188.     }
  2189.     if (trp->tp >= trp->lp || trp->tp->type!=NAME)
  2190.         goto syntax;
  2191.     np = InstallToken(trp->tp);
  2192.     np->flag |= ISDEFINED;
  2193.     trp->tp += 1;
  2194.     if (trp->tp >= trp->lp || trp->tp->type==END) {
  2195.         np->vp = &onetr;
  2196.         return np;
  2197.     }
  2198.     if (trp->tp->type!=ASGN)
  2199.         goto syntax;
  2200.     trp->tp += 1;
  2201.     if ((trp->lp-1)->type == END)
  2202.         trp->lp -= 1;
  2203.     np->vp = normtokenrow(trp);
  2204.     return np;
  2205. syntax:
  2206.     error(CPPFATAL, "Illegal -D or -U argument %r", trp);
  2207.     return NULL;
  2208. }
  2209.  
  2210. /*
  2211.  * Do macro expansion in a row of tokens.
  2212.  * Flag is NULL if more input can be gathered.
  2213.  */
  2214. static void expandrow(Tokenrow *trp,unsigned char *flag)
  2215. {
  2216.     Token *tp;
  2217.     Nlist *np;
  2218.  
  2219.     if (flag)
  2220.         setsource(flag, -1, "");
  2221.     for (tp = trp->tp; tp<trp->lp; ) {
  2222.         if (tp->type!=NAME
  2223.          || quicklook(tp->t[0], tp->len>1?tp->t[1]:0)==0
  2224.          || (np = cpplookup(tp))==NULL
  2225.          || (np->flag&(ISDEFINED|ISMAC))==0
  2226.          || tp->hideset && checkhideset(tp->hideset, np)) {
  2227.             tp++;
  2228.             continue;
  2229.         }
  2230.         trp->tp = tp;
  2231.         if (np->val==KDEFINED) {
  2232.             tp->type = DEFINED;
  2233.             if ((tp+1)<trp->lp && (tp+1)->type==NAME)
  2234.                 (tp+1)->type = NAME1;
  2235.             else if ((tp+3)<trp->lp && (tp+1)->type==LP
  2236.              && (tp+2)->type==NAME && (tp+3)->type==RP)
  2237.                 (tp+2)->type = NAME1;
  2238.             else
  2239.                 error(CPPERROR, "Incorrect syntax for 'defined'");
  2240.             tp++;
  2241.             continue;
  2242.         }
  2243.         if (np->flag&ISMAC) {
  2244. #ifndef LRC
  2245.             if (trp->tp->len == 10 && trp->tp->t[2] == 'd') {
  2246.                 dodeclspec(trp);
  2247.                 expand(trp,np);
  2248.             }
  2249.             else 
  2250. #endif
  2251.                 builtin(trp, np->val);
  2252.         }
  2253.         else {
  2254.             expand(trp, np);
  2255.         }
  2256.         tp = trp->tp;
  2257.     }
  2258.     if (flag)
  2259.         unsetsource();
  2260. }
  2261.  
  2262. /*
  2263.  * Expand the macro whose name is np, at token trp->tp, in the tokenrow.
  2264.  * Return trp->tp at the first token next to be expanded
  2265.  * (ordinarily the beginning of the expansion)
  2266.  */
  2267. static void expand(Tokenrow *trp, Nlist *np)
  2268. {
  2269.     Tokenrow ntr;
  2270.     int ntokc, narg, i;
  2271.     Token *tp;
  2272.     Tokenrow *atr[NARG+1];
  2273.     int hs;
  2274.  
  2275.     copytokenrow(&ntr, np->vp);        /* copy macro value */
  2276.     np->flag |= ISUSED;
  2277.     if (np->ap==NULL)            /* parameterless */
  2278.         ntokc = 1;
  2279.     else {
  2280.  
  2281.         ntokc = gatherargs(trp, atr, &narg);
  2282.  
  2283.         if (narg<0) {            /* not actually a call (no '(') */
  2284.             trp->tp += 1;
  2285.             return;
  2286.         }
  2287.         if (narg != rowlen(np->ap)) {
  2288.             error(CPPERROR, "Disagreement in number of macro arguments");
  2289.             trp->tp->hideset = (unsigned short)newhideset(trp->tp->hideset, np);
  2290.             trp->tp += ntokc;
  2291.             return;
  2292.         }
  2293.  
  2294.         substargs(np, &ntr, atr);    /* put args into replacement */
  2295.         for (i=0; i<narg; i++) {
  2296.             dofree(atr[i]->bp);
  2297.             dofree(atr[i]);
  2298.         }
  2299.     }
  2300.     doconcat(&ntr);                /* execute ## operators */
  2301.     hs = newhideset(trp->tp->hideset, np);
  2302.     for (tp=ntr.bp; tp<ntr.lp; tp++) {    /* distribute hidesets */
  2303.         if (tp->type==NAME) {
  2304.             if (tp->hideset==0)
  2305.                 tp->hideset = (unsigned short)hs;
  2306.             else
  2307.                 tp->hideset = (unsigned short)unionhideset(tp->hideset, hs);
  2308.         }
  2309.     }
  2310.     ntr.tp = ntr.bp;
  2311.     insertrow(trp, ntokc, &ntr);
  2312.     trp->tp -= rowlen(&ntr);
  2313.     dofree(ntr.bp);
  2314.     return;
  2315. }
  2316.  
  2317. /*
  2318.  * Gather an arglist, starting in trp with tp pointing at the macro name.
  2319.  * Return total number of tokens passed, stash number of args found.
  2320.  * trp->tp is not changed relative to the tokenrow.
  2321.  */
  2322. static int gatherargs(Tokenrow *trp, Tokenrow **atr, int *narg)
  2323. {
  2324.     int parens = 1;
  2325.     int ntok = 0;
  2326.     Token *bp, *lp;
  2327.     Tokenrow ttr;
  2328.     int ntokp;
  2329.  
  2330.     *narg = -1;            /* means that there is no macro call */
  2331.     /* look for the ( */
  2332.     for (;;) {
  2333.         trp->tp++;
  2334.         ntok++;
  2335.         if (trp->tp >= trp->lp) {
  2336.             gettokens(trp, 0);
  2337.             if ((trp->lp-1)->type==END) {
  2338.                 trp->lp -= 1;
  2339.                 trp->tp -= ntok;
  2340.                 return ntok;
  2341.             }
  2342.         }
  2343.         if (trp->tp->type==LP)
  2344.             break;
  2345.         if (trp->tp->type!=NL)
  2346.             return ntok;
  2347.     }
  2348.     *narg = 0;
  2349.     ntok++;
  2350.     ntokp = ntok;
  2351.     trp->tp++;
  2352.     /* search for the terminating ), possibly extending the row */
  2353.     while (parens>0) {
  2354.         if (trp->tp >= trp->lp)
  2355.             gettokens(trp, 0);
  2356.         if (trp->tp->type==END) {
  2357.             trp->lp -= 1;
  2358.             trp->tp -= ntok;
  2359.             error(CPPERROR, "EOF in macro arglist");
  2360.             return ntok;
  2361.         }
  2362.         if (trp->tp->type==NL) {
  2363.             trp->tp += 1;
  2364.             adjustrow(trp, -1);
  2365.             trp->tp -= 1;
  2366.             makespace(trp);
  2367.             continue;
  2368.         }
  2369.         if (trp->tp->type==LP)
  2370.             parens++;
  2371.         else if (trp->tp->type==RP)
  2372.             parens--;
  2373.         trp->tp++;
  2374.         ntok++;
  2375.     }
  2376.     trp->tp -= ntok;
  2377.     /* Now trp->tp won't move underneath us */
  2378.     lp = bp = trp->tp+ntokp;
  2379.     for (; parens>=0; lp++) {
  2380.         if (lp->type == LP) {
  2381.             parens++;
  2382.             continue;
  2383.         }
  2384.         if (lp->type==RP)
  2385.             parens--;
  2386.         if (lp->type==DSHARP)
  2387.             lp->type = DSHARP1;    /* ## not special in arg */
  2388.         if (lp->type==COMMA && parens==0 || parens<0 && (lp-1)->type!=LP) {
  2389.             if (*narg>=NARG-1)
  2390.                 error(CPPFATAL, "Sorry, too many macro arguments");
  2391.             ttr.bp = ttr.tp = bp;
  2392.             ttr.lp = lp;
  2393.             atr[(*narg)++] = normtokenrow(&ttr);
  2394.             bp = lp+1;
  2395.         }
  2396.     }
  2397.     return ntok;
  2398. }
  2399.  
  2400. /*
  2401.  * substitute the argument list into the replacement string
  2402.  *  This would be simple except for ## and #
  2403.  */
  2404. static void substargs(Nlist *np, Tokenrow *rtr, Tokenrow **atr)
  2405. {
  2406.     Tokenrow tatr;
  2407.     Token *tp;
  2408.     int ntok, argno;
  2409.  
  2410.     for (rtr->tp=rtr->bp; rtr->tp<rtr->lp; ) {
  2411.         if (rtr->tp->type==SHARP) {    /* string operator */
  2412.             tp = rtr->tp;
  2413.             rtr->tp += 1;
  2414.             if ((argno = lookuparg(np, rtr->tp))<0) {
  2415.                 error(CPPERROR, "# not followed by macro parameter");
  2416.                 continue;
  2417.             }
  2418.             ntok = 1 + (rtr->tp - tp);
  2419.             rtr->tp = tp;
  2420.             insertrow(rtr, ntok, stringify(atr[argno]));
  2421.             continue;
  2422.         }
  2423.         if (rtr->tp->type==NAME
  2424.          && (argno = lookuparg(np, rtr->tp)) >= 0) {
  2425.             if ((rtr->tp+1)->type==DSHARP
  2426.              || rtr->tp!=rtr->bp && (rtr->tp-1)->type==DSHARP)
  2427.                 insertrow(rtr, 1, atr[argno]);
  2428.             else {
  2429.                 copytokenrow(&tatr, atr[argno]);
  2430.                 expandrow(&tatr, "<macro>");
  2431.                 insertrow(rtr, 1, &tatr);
  2432.                 dofree(tatr.bp);
  2433.             }
  2434.             continue;
  2435.         }
  2436.         rtr->tp++;
  2437.     }
  2438. }
  2439.  
  2440. /*
  2441.  * Evaluate the ## operators in a tokenrow
  2442. The double-number-sign or 'token-pasting' operator (##), which is sometimes
  2443. called the 'merging' operator, is used in both object-like and function-like
  2444. macros. It permits separate tokens to be joined into a single token and 
  2445. therefore cannot be the first or last token in the macro definition.
  2446. If a formal parameter in a macro definition is preceded or followed by the 
  2447. token-pasting operator, the formal parameter is immediately replaced by the 
  2448. unexpanded actual argument. Macro expansion is not performed on the argument
  2449. prior to replacement. 
  2450.  */
  2451. static void doconcat(Tokenrow *trp)
  2452. {
  2453.     Token *ltp, *ntp;
  2454.     Tokenrow ntr;
  2455.     int len;
  2456.  
  2457.     for (trp->tp=trp->bp; trp->tp<trp->lp; trp->tp++) {
  2458.         if (trp->tp->type==DSHARP1)
  2459.             trp->tp->type = DSHARP;
  2460.         else if (trp->tp->type==DSHARP) {
  2461.             char tt[128];
  2462.             ltp = trp->tp-1;
  2463.             ntp = trp->tp+1;
  2464.             if (ltp<trp->bp || ntp>=trp->lp) {
  2465.                 error(CPPERROR, "## occurs at border of replacement");
  2466.                 continue;
  2467.             }
  2468.             len = ltp->len + ntp->len;
  2469.             strncpy((char*)tt, (char*)ltp->t, ltp->len);
  2470.             strncpy((char*)tt+ltp->len, (char*)ntp->t, ntp->len);
  2471.             tt[len] = '\0';
  2472.             setsource((unsigned char *)"<##>", -1, tt);
  2473.             maketokenrow(3, &ntr);
  2474.             gettokens(&ntr, 1);
  2475.             unsetsource();
  2476.             if (ntr.lp-ntr.bp!=2 || ntr.bp->type==UNCLASS)
  2477.                 error(CPPWARNING, "Bad token %r produced by ##", &ntr);
  2478.             ntr.lp = ntr.bp+1;
  2479.             trp->tp = ltp;
  2480.             makespace(&ntr);
  2481.             insertrow(trp, (ntp-ltp)+1, &ntr);
  2482.             dofree(ntr.bp);
  2483.             trp->tp--;
  2484.         }
  2485.     }
  2486. }
  2487.  
  2488. /*
  2489.  * tp is a potential parameter name of macro mac;
  2490.  * look it up in mac's arglist, and if found, return the
  2491.  * corresponding index in the argname array.  Return -1 if not found.
  2492.  */
  2493. static int lookuparg(Nlist *mac, Token *tp)
  2494. {
  2495.     Token *ap;
  2496.  
  2497.     if (tp->type!=NAME || mac->ap==NULL)
  2498.         return -1;
  2499.     for (ap=mac->ap->bp; ap<mac->ap->lp; ap++) {
  2500.         if (ap->len==tp->len && strncmp((char*)ap->t,(char*)tp->t,ap->len)==0)
  2501.             return ap - mac->ap->bp;
  2502.     }
  2503.     return -1;
  2504. }
  2505.  
  2506. /*
  2507.  * Return a quoted version of the tokenrow (from # arg)
  2508.  */
  2509. #define    STRLEN    512
  2510. static Tokenrow *stringify(Tokenrow *vp)
  2511. {
  2512.     static Token t = { STRING };
  2513.     static Tokenrow tr = { &t, &t, &t+1, 1 };
  2514.     Token *tp;
  2515.     uchar s[STRLEN];
  2516.     uchar *sp = s, *cp;
  2517.     unsigned int i;
  2518.     int instring;
  2519.  
  2520.     *sp++ = '"';
  2521.     for (tp = vp->bp; tp < vp->lp; tp++) {
  2522.         instring = tp->type==STRING || tp->type==CCON;
  2523.         if (sp+2*tp->len >= &s[STRLEN-10]) {
  2524.             error(CPPERROR, "Stringified macro arg is too long");
  2525.             break;
  2526.         }
  2527.         if (tp->wslen && (tp->flag&XPWS)==0)
  2528.             *sp++ = ' ';
  2529.         for (i=0, cp=tp->t; i<tp->len; i++) {
  2530.             if (instring && (*cp=='"' || *cp=='\\'))
  2531.                 *sp++ = '\\';
  2532.             *sp++ = *cp++;
  2533.         }
  2534.     }
  2535.     *sp++ = '"';
  2536.     *sp = '\0';
  2537.     sp = s;
  2538.     t.len = strlen((char*)sp);
  2539.     t.t = newstring(sp, t.len, 0);
  2540.     return &tr;
  2541. }
  2542.  
  2543. /* double the backslashs when outputting strings */
  2544. static int filestrcpy(char *op,char *src)
  2545. {
  2546.     int i,c;
  2547.  
  2548.     i = 0;
  2549.     while ((c=*src++) != 0) {
  2550.         if (c == '\\') {
  2551.             *op++ = (char)c;
  2552.             i++;
  2553.         }
  2554.         *op++ = (char)c;
  2555.         i++;
  2556.     }
  2557.     return(i);
  2558. }
  2559. #ifndef LRC
  2560. static void dodeclspec(Tokenrow *trp)
  2561. {
  2562.     if (trp->tp[1].type != LP) {
  2563. declspecerr:
  2564.         error(CPPERROR,"bad __declspec syntax!");
  2565.         return;
  2566.     }
  2567.     if (trp->tp[3].type != RP) goto declspecerr;
  2568. }
  2569. #endif
  2570. /*
  2571.  * expand a builtin name
  2572.  */
  2573. static void builtin(Tokenrow *trp, int biname)
  2574. {
  2575.     char *op;
  2576.     Token *tp;
  2577.     Source *s;
  2578.  
  2579.     tp = trp->tp;
  2580.     trp->tp++;
  2581.     /* need to find the real source */
  2582.     s = cursource;
  2583.     while (s && s->fd==-1)
  2584.         s = s->next;
  2585.     if (s==NULL)
  2586.         s = cursource;
  2587.     /* most are strings */
  2588.     tp->type = STRING;
  2589.     if (tp->wslen) {
  2590.         *OutputPtr++ = ' ';
  2591.         tp->wslen = 1;
  2592.     }
  2593.     op = OutputPtr;
  2594.     *op++ = '"';
  2595.     switch (biname) {
  2596.  
  2597.     case KLINENO:
  2598.         tp->type = NUMBER;
  2599.         op = outnum(op-1, s->line);
  2600.         break;
  2601.  
  2602.     case KFILE:
  2603.         op += filestrcpy(op, s->filename);
  2604.         break;
  2605.  
  2606.     case KDATE:
  2607.         strncpy(op, curtime+4, 7);
  2608.         strncpy(op+7, curtime+20, 4);
  2609.         op += 11;
  2610.         break;
  2611.  
  2612.     case KTIME:
  2613.         strncpy(op, curtime+11, 8);
  2614.         op += 8;
  2615.         break;
  2616.  
  2617.     default:
  2618.         error(CPPERROR, "cpp botch: unknown internal macro");
  2619.         return;
  2620.     }
  2621.     if (tp->type==STRING)
  2622.         *op++ = '"';
  2623.     tp->t = (uchar*)OutputPtr;
  2624.     tp->len = op - OutputPtr;
  2625.     OutputPtr = op;
  2626. }
  2627.  
  2628.  
  2629.  
  2630. static void setup_kwtab(void)
  2631. {
  2632.     struct kwtab *kp;
  2633.     Nlist *np;
  2634.     Token t;
  2635.     static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }};
  2636.     static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 };
  2637.  
  2638.     for (kp=kwtab; kp->kw; kp++) {
  2639.         t.t = (uchar*)kp->kw;
  2640.         t.len = strlen(kp->kw);
  2641.         np = InstallToken(&t);
  2642.         np->flag = (char)kp->flag;
  2643.         np->val = (char)kp->val;
  2644.         if (np->val == KDEFINED) {
  2645.             kwdefined = np;
  2646.             np->val = NAME;
  2647.             np->vp = &deftr;
  2648.             np->ap = 0;
  2649.         }
  2650.     }
  2651. }
  2652. #ifdef ASM_LIB
  2653. extern int DoHash(int,char*);
  2654. extern Nlist *cpplookup(Token *);
  2655. #else
  2656. static int DoHash(int s,char *cp)
  2657. {
  2658.     int r = 0;
  2659.  
  2660.     while (s--)
  2661.         r += *cp++;
  2662.     return(r);
  2663. }
  2664.  
  2665. static Nlist *cpplookup(Token *tp)
  2666. {
  2667.     unsigned int h;
  2668.     Nlist *np;
  2669.     uchar *cp, *start;
  2670.     register s;
  2671. #ifdef TIMEIT
  2672.     DATETIME dt1,dt2;
  2673.     long ss,m;
  2674.  
  2675.     DosGetDateTime(&dt1);
  2676. #endif
  2677.  
  2678.     start = cp = tp->t;
  2679.     s = tp->len;
  2680.     if (s <= 0) {
  2681.             fprintf(stderr,"Token of length 0?\n");
  2682.             exit(1);
  2683.     }
  2684.     h = DoHash(s,cp);
  2685.     s = tp->len;
  2686.     np = nlist[h & 0x3FF];
  2687.     while (np) {
  2688.         if (s == np->len) {
  2689.          if (strncmp((char*)start, (char*)np->name, s)==0)
  2690.             break;
  2691.         }
  2692.         np = np->next;
  2693.     }
  2694.     return np;
  2695. }
  2696. #endif /* ASM_LIB */
  2697. static Nlist *InstallToken(Token *tp)
  2698. {
  2699.     Nlist *np;
  2700.     uchar *cp;
  2701.     register s;
  2702.     unsigned int h;
  2703.  
  2704.     np = cpplookup(tp);
  2705.     if (np) return(np);
  2706.     cp = tp->t;
  2707.     s = tp->len;
  2708.     h = DoHash(s,cp);
  2709.     np = domalloc(sizeof(Nlist));
  2710.     np->vp = NULL;
  2711.     np->ap = NULL;
  2712.     np->flag = 0;
  2713.     np->val = 0;
  2714.     np->len = tp->len;
  2715.     np->h = h;
  2716.     np->name = newstring(tp->t, tp->len, 0);
  2717.     np->next = nlist[h&0x3FF];
  2718.     nlist[h&0x3FF] = np;
  2719.     quickset(tp->t[0], tp->len>1? tp->t[1]:0);
  2720.     return np;
  2721. }
  2722.  
  2723.  
  2724. /*
  2725.  * 1 for tokens that don't need whitespace when they get inserted
  2726.  * by macro expansion
  2727.  */
  2728. static const char wstab[] = {
  2729.     0,    /* END */
  2730.     0,    /* UNCLASS */
  2731.     0,    /* NAME */
  2732.     0,    /* NUMBER */
  2733.     0,    /* STRING */
  2734.     0,    /* CCON */
  2735.     1,    /* NL */
  2736.     0,    /* WS */
  2737.     0,    /* DSHARP */
  2738.     0,    /* EQ */
  2739.     0,    /* NEQ */
  2740.     0,    /* LEQ */
  2741.     0,    /* GEQ */
  2742.     0,    /* LSH */
  2743.     0,    /* RSH */
  2744.     0,    /* LAND */
  2745.     0,    /* LOR */
  2746.     0,    /* PPLUS */
  2747.     0,    /* MMINUS */
  2748.     0,    /* ARROW */
  2749.     1,    /* SBRA */
  2750.     1,    /* SKET */
  2751.     1,    /* LP */
  2752.     1,    /* RP */
  2753.     0,    /* DOT */
  2754.     0,    /* AND */
  2755.     0,    /* STAR */
  2756.     0,    /* PLUS */
  2757.     0,    /* MINUS */
  2758.     0,    /* TILDE */
  2759.     0,    /* NOT */
  2760.     0,    /* SLASH */
  2761.     0,    /* PCT */
  2762.     0,    /* LT */
  2763.     0,    /* GT */
  2764.     0,    /* CIRC */
  2765.     0,    /* OR */
  2766.     0,    /* QUEST */
  2767.     0,    /* COLON */
  2768.     0,    /* ASGN */
  2769.     1,    /* COMMA */
  2770.     0,    /* SHARP */
  2771.     1,    /* SEMIC */
  2772.     1,    /* CBRA */
  2773.     1,    /* CKET */
  2774.     0,    /* ASPLUS */
  2775.      0,    /* ASMINUS */
  2776.      0,    /* ASSTAR */
  2777.      0,    /* ASSLASH */
  2778.      0,    /* ASPCT */
  2779.      0,    /* ASCIRC */
  2780.      0,    /* ASLSH */
  2781.     0,    /* ASRSH */
  2782.      0,    /* ASOR */
  2783.      0,    /* ASAND */
  2784.     0,    /* ELLIPS */
  2785.     0,    /* DSHARP1 */
  2786.     0,    /* NAME1 */
  2787.     0,    /* DEFINED */
  2788.     0,    /* UMINUS */
  2789. };
  2790.  
  2791. static void maketokenrow(int size, Tokenrow *trp)
  2792. {
  2793.     if (size>0) {
  2794.         trp->bp = (Token *)domalloc((size+1)*sizeof(Token));
  2795.     }
  2796.     else
  2797.         trp->bp = NULL;
  2798.     trp->max = size;
  2799.     trp->tp = trp->bp;
  2800.     trp->lp = trp->bp;
  2801. }
  2802.  
  2803. static Token *growtokenrow(Tokenrow *trp)
  2804. {
  2805.     int ncur = trp->tp - trp->bp;
  2806.     int nlast = trp->lp - trp->bp;
  2807.  
  2808. /*    trp->max = 3*trp->max/2 + 1;*/
  2809.     trp->max = 3*trp->max + 1;
  2810.     trp->bp = (Token *)realloc(trp->bp, trp->max*sizeof(Token));
  2811.     trp->lp = &trp->bp[nlast];
  2812.     trp->tp = &trp->bp[ncur];
  2813.     return trp->lp;
  2814. }
  2815.  
  2816. /*
  2817.  * Compare a row of tokens, ignoring the content of WS; return !=0 if different
  2818.  */
  2819. static int comparetokens(Tokenrow *tr1, Tokenrow *tr2)
  2820. {
  2821.     Token *tp1, *tp2;
  2822.  
  2823.     tp1 = tr1->tp;
  2824.     tp2 = tr2->tp;
  2825.     if (tr1->lp-tp1 != tr2->lp-tp2)
  2826.         return 1;
  2827.     for (; tp1<tr1->lp ; tp1++, tp2++) {
  2828.         if (tp1->type != tp2->type
  2829.          || (tp1->wslen==0) != (tp2->wslen==0)
  2830.          || tp1->len != tp2->len
  2831.          || strncmp((char*)tp1->t, (char*)tp2->t, tp1->len)!=0)
  2832.             return 1;
  2833.     }
  2834.     return 0;
  2835. }
  2836.  
  2837. /*
  2838.  * replace ntok tokens starting at dtr->tp with the contents of str.
  2839.  * tp ends up pointing just beyond the replacement.
  2840.  * Canonical whitespace is assured on each side.
  2841.  */
  2842. static void insertrow(Tokenrow *dtr, int ntok, Tokenrow *str)
  2843. {
  2844.     int nrtok = rowlen(str);
  2845.  
  2846.     dtr->tp += ntok;
  2847.     adjustrow(dtr, nrtok-ntok);
  2848.     dtr->tp -= ntok;
  2849.     movetokenrow(dtr, str);
  2850.     makespace(dtr);
  2851.     dtr->tp += nrtok;
  2852.     makespace(dtr);
  2853. }
  2854.  
  2855. /*
  2856.  * make sure there is WS before trp->tp, if tokens might merge in the output
  2857.  */
  2858. static void makespace(Tokenrow *trp)
  2859. {
  2860.     uchar *tt;
  2861.     Token *tp = trp->tp;
  2862.  
  2863.     if (tp >= trp->lp)
  2864.         return;
  2865.     if (tp->wslen) {
  2866.         if (tp->flag&XPWS
  2867.          && (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])) {
  2868.             tp->wslen = 0;
  2869.             return;
  2870.         }
  2871.         tp->t[-1] = ' ';
  2872.         return;
  2873.     }
  2874.     if (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])
  2875.         return;
  2876.     tt = newstring(tp->t, tp->len, 1);
  2877.     *tt++ = ' ';
  2878.     tp->t = tt;
  2879.     tp->wslen = 1;
  2880.     tp->flag |= XPWS;
  2881. }
  2882.  
  2883. /*
  2884.  * Move the tokens in a row, starting at tr->tp, rightward by nt tokens;
  2885.  * nt may be negative (left move).
  2886.  * The row may need to be grown.
  2887.  * Non-strictly conforming because of the (char *), but easily fixed
  2888.  */
  2889. static void adjustrow(Tokenrow *trp, int nt)
  2890. {
  2891.     int nby, size;
  2892.  
  2893.     if (nt==0)
  2894.         return;
  2895.     size = (trp->lp - trp->bp) + nt;
  2896.     while (size > trp->max)
  2897.         growtokenrow(trp);
  2898.     /* nby = sizeof(Token) * (trp->lp - trp->tp); */
  2899.     nby = (char *)trp->lp - (char *)trp->tp;
  2900.     if (nby)
  2901.         memmove(trp->tp+nt, trp->tp, nby);
  2902.     trp->lp += nt;
  2903. }
  2904.  
  2905. /*
  2906.  * Copy a row of tokens into the destination holder, allocating
  2907.  * the space for the contents.  Return the destination.
  2908.  */
  2909. static Tokenrow *copytokenrow(Tokenrow *dtr, Tokenrow *str)
  2910. {
  2911.     int len = rowlen(str);
  2912.  
  2913.     maketokenrow(len, dtr);
  2914.     movetokenrow(dtr, str);
  2915.     dtr->lp += len;
  2916.     return dtr;
  2917. }
  2918.  
  2919. /*
  2920.  * Produce a copy of a row of tokens.  Start at trp->tp.
  2921.  * The value strings are copied as well.  The first token
  2922.  * has WS available.
  2923.  */
  2924. static Tokenrow *normtokenrow(Tokenrow *trp)
  2925. {
  2926.     Token *tp;
  2927.     Tokenrow *ntrp = malloc(sizeof(Tokenrow));
  2928.     int len;
  2929.  
  2930.     len = trp->lp - trp->tp;
  2931.     if (len<=0)
  2932.         len = 1;
  2933.     maketokenrow(len, ntrp);
  2934.     for (tp=trp->tp; tp < trp->lp; tp++) {
  2935.         *ntrp->lp = *tp;
  2936.         if (tp->len) {
  2937.             ntrp->lp->t = newstring(tp->t, tp->len, 1);
  2938.             *ntrp->lp->t++ = ' ';
  2939.             if (tp->wslen)
  2940.                 ntrp->lp->wslen = 1;
  2941.         }
  2942.         ntrp->lp++;
  2943.     }
  2944.     if (ntrp->lp > ntrp->bp)
  2945.         ntrp->bp->wslen = 0;
  2946.     return ntrp;
  2947. }
  2948. #if 0
  2949. /*
  2950.  * Debugging
  2951.  */
  2952. static void peektokens(Tokenrow *trp, char *str)
  2953. {
  2954.     Token *tp;
  2955.  
  2956.     tp = trp->tp;
  2957.     flushout();
  2958.     if (str)
  2959.         fprintf(stderr, "%s ", str);
  2960.     if (tp<trp->bp || tp>trp->lp)
  2961.         fprintf(stderr, "(tp offset %d) ", tp-trp->bp);
  2962.     for (tp=trp->bp; tp<trp->lp && tp<trp->bp+32; tp++) {
  2963.         if (tp->type!=NL) {
  2964.             int c = tp->t[tp->len];
  2965.             tp->t[tp->len] = 0;
  2966.             fprintf(stderr, "%s", tp->t);
  2967.             tp->t[tp->len] = c;
  2968.         }
  2969.         if (tp->type==NAME) {
  2970.             fprintf(stderr, tp==trp->tp?"{*":"{");
  2971.             prhideset(tp->hideset);
  2972.             fprintf(stderr, "} ");
  2973.         } else
  2974.             fprintf(stderr, tp==trp->tp?"{%x*} ":"{%x} ", tp->type);
  2975.     }
  2976.     fprintf(stderr, "\n");
  2977.     fflush(stderr);
  2978. }
  2979. #endif
  2980. #ifndef LRC
  2981. int isCKeyword(Token *tp)
  2982. {
  2983.     int result = 0;
  2984.     char *t = (char *)tp->t;
  2985.  
  2986.     switch (tp->len) {
  2987.         case 2: /* if do */
  2988.             if (t[0] == 'i' && t[1] == 'f') result = IF;
  2989.             else if (t[0] == 'd' && t[1] == 'o') result = DO;
  2990.             break;
  2991.         case 3: /* int for */
  2992.             if (!strncmp(t,"for",3)) result = FOR;
  2993.             else if (!strncmp(t,"int",3)) result = INTK;
  2994.             break;
  2995.         case 4: /* char void auto case else goto long enum */
  2996.             switch (t[0]) {
  2997.                 case 'c':
  2998.                     if (!strncmp(t,"char",4)) result = CHARK;
  2999.                     if (!strncmp(t,"case",4)) result = CASE;
  3000.                     break;
  3001.                 case 'v':
  3002.                     if (!strncmp(t,"void",4)) result = VOIDK;
  3003.                     break;
  3004.                 case 'a':
  3005.                     if (!strncmp(t,"auto",4)) result = AUTOK;
  3006.                     break;
  3007.                 case 'e':
  3008.                     if (!strncmp(t,"else",4)) result = ELSE;
  3009.                     if (!strncmp(t,"enum",4)) result = ENUM;
  3010.                     break;
  3011.                 case 'g':
  3012.                     if (!strncmp(t,"goto",4)) result = ELSE;
  3013.                     break;
  3014.                 case 'l':
  3015.                     if (!strncmp(t,"long",4)) result = LONGK;
  3016.                     break;                                    
  3017.             }
  3018.             break;
  3019.         case 5: /* float short union const break while */
  3020.             switch (t[0]) {
  3021.                 case 'f':
  3022.                     if (!strncmp(t,"float",5)) result = FLOATK;
  3023.                     break;
  3024.                 case 's':
  3025.                     if (!strncmp(t,"short",5)) result = SHORTK;
  3026.                     break;
  3027.                 case 'u':
  3028.                     if (!strncmp(t,"union",5)) result = UNION;
  3029.                     break;
  3030.                 case 'c':
  3031.                     if (!strncmp(t,"const",5)) result = CONSTK;
  3032.                     break;
  3033.                 case 'b':
  3034.                     if (!strncmp(t,"break",5)) result = BREAK;
  3035.                     break;
  3036.                 case 'w':
  3037.                     if (!strncmp(t,"while",5)) result = WHILE;
  3038.                     break;                    
  3039.             }
  3040.             break;
  3041.         case 6: /* double struct sizeof signed switch static extern return */
  3042.             switch (t[2]) {
  3043.                 case 'u':
  3044.                     if (!strncmp(t,"double",6)) result = DOUBLEK;
  3045.                     break;                    
  3046.                 case 'r':
  3047.                     if (!strncmp(t,"struct",6)) result = STRUCTK;
  3048.                     break;                    
  3049.                 case 'z':
  3050.                     if (!strncmp(t,"sizeof",6)) result = SIZEOFK;
  3051.                     break;                    
  3052.                 case 'g':
  3053.                     if (!strncmp(t,"signed",6)) result = SIGNED;
  3054.                     break;                    
  3055.                 case 'i':
  3056.                     if (!strncmp(t,"switch",6)) result = SWITCH;
  3057.                     break;                    
  3058.                 case 'a':
  3059.                     if (!strncmp(t,"static",6)) result = STATICK;
  3060.                     break;                    
  3061.                 case 't':
  3062.                     if (!strncmp(t,"extern",6)) result = EXTERNK;
  3063.                     if (!strncmp(t,"return",6)) result = RETURN;
  3064.                     break;                    
  3065.             }
  3066.             break;
  3067.         case 7: /* default typedef */
  3068.             switch (t[2]) {
  3069.                 case 'f':
  3070.                     if (!strncmp(t,"default",7)) result = DEFAULT;
  3071.                     break;
  3072.                 case 'p':
  3073.                     if (!strncmp(t,"typedef",7)) result = TYPEDEF;
  3074.                     break;
  3075.                 case 'a':
  3076.                     if (!strncmp(t,"_pascal",7)) result = PASCALKEYW;
  3077.                     break;
  3078.             }
  3079.             break;
  3080.         case 8: /* UNSIGNED,FUNCTION,VOLATILE,CONTINUE,REGISTER */
  3081.             switch (t[0]) {
  3082.                 case 'u':
  3083.                     if (!strncmp(t,"unsigned",8)) result = UNSIGNEDK;
  3084.                     break;
  3085.                 case 'v':
  3086.                     if (!strncmp(t,"volatile",8)) result = VOLATILEK;
  3087.                     break;
  3088.                 case 'c':
  3089.                     if (!strncmp(t,"continue",8)) result = CONTINUE;
  3090.                     break;
  3091.                 case 'r':
  3092.                     if (!strncmp(t,"register",8)) result = REGISTER;
  3093.                     break;
  3094.             }
  3095.     }
  3096.     return(result);
  3097. }
  3098.  
  3099.  
  3100. void writeToken(Token *tp)
  3101. {
  3102.     unsigned short *pus;
  3103.     unsigned char *pbuf,*pt;
  3104.     int i,len;
  3105.  
  3106.     pbuf = (unsigned char *)tbuf;
  3107.     *pbuf++ = tp->type;
  3108.     switch (tp->type) {
  3109.         case NL:
  3110.         case EQ:
  3111.         case NEQ:
  3112.         case LEQ:
  3113.         case GEQ:
  3114.         case LSH:
  3115.         case RSH:
  3116.         case LAND:
  3117.         case LOR:
  3118.         case PPLUS:
  3119.         case MMINUS:
  3120.         case ARROW:
  3121.         case SBRA:
  3122.         case SKET:
  3123.         case LP:
  3124.         case RP:
  3125.         case DOT:
  3126.         case AND:
  3127.         case STAR:
  3128.         case PLUS:
  3129.         case MINUS:
  3130.         case TILDE:
  3131.         case NOT:
  3132.         case SLASH:
  3133.         case PCT:
  3134.         case LT:
  3135.         case GT:
  3136.         case CIRC:
  3137.         case OR:
  3138.         case QUEST:
  3139.         case COLON:
  3140.         case ASGN:
  3141.         case COMMA:
  3142.         case SHARP:
  3143.         case SEMIC:
  3144.         case CBRA:
  3145.         case CKET:
  3146.         case ASPLUS:
  3147.         case ASMINUS:
  3148.         case ASSTAR:
  3149.         case ASSLASH:
  3150.         case ASPCT:
  3151.         case ASCIRC:
  3152.         case ASLSH:
  3153.         case ASRSH:
  3154.         case ASOR:
  3155.         case ASAND:
  3156.         case ELLIPS:
  3157.         case UMINUS:
  3158.             break;
  3159.         default:
  3160.             i = isCKeyword(tp);
  3161.             if (!i) {
  3162.                 len = tp->len;
  3163.                 if (len < 50) {
  3164.                     len += 200;
  3165.                     tbuf[0] = (char)len;
  3166.                 }
  3167.                 else if (len > 254) {
  3168.                     tbuf[1] = 255;
  3169.                     pus = (unsigned short *)&tbuf[2];
  3170.                     *pus = (unsigned short)len;
  3171.                     pbuf = (unsigned char *)(tbuf+4);
  3172.                 }
  3173.                 else {
  3174.                     tbuf[1] = (char)len;
  3175.                     pbuf = (unsigned char *)(tbuf+2);
  3176.                 }
  3177.                 pt = tp->t;    
  3178.                 for (i=0; i<(int)(tp->len);i++) *pbuf++ = *pt++;
  3179.             }
  3180.             else tbuf[0] = (char)i;
  3181.         break;
  3182.     }
  3183.     fwrite(tbuf,1,(unsigned long)pbuf - (unsigned long)tbuf,tokfile);
  3184. }
  3185. #endif // LRC
  3186.  
  3187. static int puttokens(Tokenrow *trp)
  3188. {
  3189.     Token *tp;
  3190.     int len;
  3191.     unsigned char *p,*stop,*hardstop;
  3192.  
  3193.     tp = trp->bp;
  3194.     hardstop = &wbuf[3*OBS];
  3195.     stop = &wbuf[OBS];
  3196.     PartialSize = 0;
  3197.     for (; tp<trp->lp; tp++) {
  3198.         len = tp->len+tp->wslen;
  3199. #ifndef LRC
  3200.         if (dotokfile)
  3201.             writeToken(tp);
  3202. #endif
  3203.         p = tp->t-tp->wslen;
  3204.         while (tp<trp->lp-1 && p+len == (tp+1)->t - (tp+1)->wslen) {
  3205.             tp++;
  3206. #ifndef LRC
  3207.             if (dotokfile)
  3208.                 writeToken(tp);
  3209. #endif
  3210.             len += tp->wslen+tp->len;
  3211.         }
  3212.         memcpy(wbp, p, len);
  3213.         wbp += len;
  3214.         if (wbp >= hardstop) {
  3215.             fprintf(stderr,"Cpp: Input buffer overflow!!!\n");
  3216.             exit(1);
  3217.         }
  3218.     }
  3219.     trp->tp = tp;
  3220.     return(wbp < stop);
  3221. }
  3222. #if 0
  3223. static void flushout(void)
  3224. {
  3225. }
  3226. #endif
  3227. /*
  3228.  * turn a row into just a newline
  3229.  */
  3230. static void setempty(Tokenrow *trp)
  3231. {
  3232.     trp->tp = trp->bp;
  3233.     trp->lp = trp->bp+1;
  3234.     *trp->bp = nltoken;
  3235. }
  3236.  
  3237. /*
  3238.  * generate a number
  3239.  */
  3240. static char *outnum(char *p, int n)
  3241. {
  3242.     if (n>=10)
  3243.         p = outnum(p, n/10);
  3244.     *p++ = (char)(n%10 + '0');
  3245.     return p;
  3246. }
  3247.  
  3248. /*
  3249.  * allocate and initialize a new string from s, of length l, at offset o
  3250.  * Null terminated.
  3251.  */
  3252. static uchar *newstring(uchar *s, int l, int o)
  3253. {
  3254.     uchar *ns = (uchar *)domalloc(l+o+1);
  3255.  
  3256.     ns[l+o] = '\0';
  3257.     return (uchar*)strncpy((char*)ns+o, (char*)s, l) - o;
  3258. }
  3259. static char *ReadIncludePathFromRegistry(char *buf)
  3260. {
  3261.     HKEY hkeyP,hkey,hkeylink;
  3262.     unsigned long siz = 512;
  3263.     char *r=NULL;
  3264.     unsigned long dwType;
  3265.  
  3266.     if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"Software",0,KEY_QUERY_VALUE,&hkeyP) != ERROR_SUCCESS)
  3267.         return(NULL);
  3268.     if (RegOpenKeyExA(hkeyP,"lcc",0,KEY_QUERY_VALUE,&hkey) != ERROR_SUCCESS) {
  3269.         RegCloseKey(hkeyP);
  3270.         return(NULL);
  3271.     }
  3272.     if (RegOpenKeyExA(hkey,"Compiler",0,KEY_QUERY_VALUE,&hkeylink) != ERROR_SUCCESS) {
  3273.         RegCloseKey(hkeyP);
  3274.         RegCloseKey(hkey);
  3275.         return(NULL);
  3276.     }
  3277.     dwType = REG_SZ;
  3278.     if (RegQueryValueExA(hkeylink,"includepath",0,&dwType,buf,&siz) == ERROR_SUCCESS) {
  3279.         r = buf;
  3280.     }
  3281.     RegCloseKey(hkeyP);
  3282.     RegCloseKey(hkey);
  3283.     RegCloseKey(hkeylink);
  3284.     return(r);
  3285. }
  3286.  
  3287. static int WriteIncludePathToRegistry(char *buf)
  3288. {
  3289.     HKEY hkeyP,hkey,hkeylink;
  3290.     unsigned long dwType,result,disp;
  3291.  
  3292.     if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"Software",0,KEY_CREATE_SUB_KEY,&hkeyP) != ERROR_SUCCESS)
  3293.         return(0);
  3294.     if (RegCreateKeyExA(hkeyP,"lcc",0,
  3295.             NULL,0,KEY_ALL_ACCESS,NULL,&hkey,&disp) != ERROR_SUCCESS)
  3296.         return 0;
  3297.     if (RegCreateKeyExA(hkey,"Compiler",0,
  3298.             NULL,0,KEY_ALL_ACCESS,NULL,&hkeylink,&disp) != ERROR_SUCCESS) {
  3299.         RegCloseKey(hkeyP);
  3300.         RegCloseKey(hkey);
  3301.         return 0;
  3302.     }
  3303.     dwType = REG_SZ;
  3304.     if (RegSetValueExA(hkeylink,"includepath",0,dwType,buf,strlen(buf)+1) !=
  3305.         ERROR_SUCCESS) {
  3306.         result = 0;
  3307.     }
  3308.     else result = 1;
  3309.     RegCloseKey(hkeylink);
  3310.     RegCloseKey(hkey);
  3311.     RegCloseKey(hkeyP);
  3312.     return(result);
  3313. }
  3314.  
  3315. static void setInclude(void)
  3316. {
  3317.     int i;
  3318.     char *p,*q;
  3319.     DWORD fa;
  3320.     char buf[512];
  3321.  
  3322.     p = ReadIncludePathFromRegistry(buf);
  3323.     if (p == NULL) {
  3324.         printf("Installation problem\n");
  3325.         printf("Please enter the path for the <include> header files (for example c:\\lcc\\include)\n");
  3326.         gets(buf);
  3327.         fa = GetFileAttributes(buf);
  3328.         if ((fa & FILE_ATTRIBUTE_DIRECTORY) == 0) {
  3329.             printf("%s is not a directory. Exiting\n");
  3330.             exit(-1);
  3331.         }
  3332.         WriteIncludePathToRegistry(buf);
  3333.         p = buf;
  3334.     }
  3335.     IncPath = domalloc(strlen(p)+1);
  3336.     strcpy(IncPath,p);
  3337.     p = IncPath;
  3338.     q = p;
  3339.     do {
  3340.         while (*p && *p != ';') p++;
  3341.         if (*p == ';') *p++ = 0;
  3342.         for (i=NINCLUDE-2; i>=0; i--) {
  3343.             if (includelist[i].file==NULL) {
  3344.                 includelist[i].always = 1;
  3345.                 includelist[i].file = q;
  3346.                 break;
  3347.             }
  3348.         }
  3349.         q = p;
  3350.     } while (*p);
  3351. }
  3352.  
  3353. static char *iccCpps[] = {
  3354.     "__LCC__=",
  3355.     "__STDC__=1",
  3356.     "WIN32=1",
  3357.     "_WIN32=1",
  3358.     "_X86_=",
  3359.     "_Seg16=",
  3360.     "_Far16=",
  3361.     "_huge=",
  3362.     "_M_IX86=300",
  3363. /*    "_Pascal=",*/
  3364.     "_Builtin=",
  3365.     "_cdecl=",
  3366.     "__cdecl=",
  3367.     "__inline=",
  3368.     "_stdcall=_stdcall",
  3369.     "__stdcall=_stdcall",
  3370.     "__int64=long long",
  3371.     "_STDCALL_SUPPORTED=",
  3372. /*    "WIN32_LEAN_AND_MEAN=", */
  3373.     NULL
  3374. };
  3375.  
  3376. static void setIcc(void)
  3377. {
  3378.     char **p;
  3379.     Tokenrow tr;
  3380.     Nlist *np;
  3381.  
  3382.     p = iccCpps;
  3383.     while (*p) {
  3384.         setsource((unsigned char *)"<cmdarg>", -1, *p);
  3385.         maketokenrow(3, &tr);
  3386.         gettokens(&tr, 1);
  3387.         doadefine(&tr, '_');
  3388.         unsetsource();
  3389.         p++;
  3390.     }
  3391.     setsource((unsigned char *)"<cmdarg>",-1,(unsigned char *)"define __declspec(a)");
  3392.     maketokenrow(4,&tr);
  3393.     gettokens(&tr,1);
  3394.     np = dodefine(&tr);
  3395.     if (np) np->flag |= ISMAC;
  3396.     unsetsource();
  3397. }
  3398.  
  3399. #define EPR                 fprintf(stderr,
  3400. #define ERR(str, chr)       if(opterr){EPR "%s%c\n", str, chr);}
  3401.  
  3402. void DoCmdLineDirective(char *optarg,int type)
  3403. {
  3404.     Tokenrow tr;
  3405.  
  3406.     setsource((unsigned char *)"<cmdarg>", -1, optarg);
  3407.     maketokenrow(3, &tr);
  3408.     gettokens(&tr, 1);
  3409.     doadefine(&tr, type);
  3410.     unsetsource();
  3411. }
  3412.  
  3413. void CmdLineAddInclude(unsigned char *optarg)
  3414. {
  3415.     int i;
  3416.  
  3417.     for (i=NINCLUDE-2; i>=0; i--) {
  3418.         if (includelist[i].file==NULL) {
  3419.             includelist[i].always = 1;
  3420.             includelist[i].file = optarg;
  3421.             break;
  3422.         }
  3423.     }
  3424.     if (i<0)
  3425.         error(CPPFATAL, "Too many -I directives");
  3426. }
  3427.  
  3428. static void setup(unsigned char *filename)
  3429. {
  3430.     int fd;
  3431.     unsigned char *fp, *dp;
  3432.  
  3433.     setup_kwtab();
  3434. #ifndef LRC
  3435.     TokFileName = NULL;
  3436.     dotokfile = 0;
  3437. #endif
  3438.     dp = (unsigned char *)".";
  3439.     fp = (unsigned char *)"<stdin>";
  3440.     fd = 0;
  3441.     if ((fp = strrchr(filename, PATH_SEPARATOR)) != NULL) {
  3442.         int len = fp - filename;
  3443.         dp = newstring(filename, len+1, 0);
  3444.         dp[len] = '\0';
  3445.     }
  3446.     fp = newstring(filename, strlen(filename), 0);
  3447.     if ((fd = DoOpen(fp)) <= 0)
  3448.         error(CPPFATAL, "Can't open input file %s", fp);
  3449. #ifndef LRC
  3450.     if (dotokfile) {
  3451.         char *p;
  3452.         TokFileName= newstring(filename, strlen(filename)+5, 0);
  3453.         strcpy(TokFileName,fp);
  3454.         p = strrchr(TokFileName,'.');
  3455.         if (p == NULL) p = TokFileName;
  3456.         else *p = 0;
  3457.         strcat(p,".tok");
  3458.         if (!strcmp(TokFileName,fp)) {
  3459.             fprintf(stderr,"Clobbering input file? %s\n",filename);
  3460.             exit(1);
  3461.         }
  3462.     }
  3463. #endif
  3464.     setobjname(fp);
  3465.     setInclude();
  3466.     setIcc();
  3467.     includelist[NINCLUDE-1].always = 0;
  3468.     includelist[NINCLUDE-1].file = dp;
  3469.     setsource(fp, fd, NULL);
  3470. }
  3471. #ifndef LRC
  3472. void DumpDefines(void)
  3473. {
  3474.     int i,n;
  3475.     Nlist *np;
  3476.     char *p;
  3477.  
  3478.     for (i=0; i<NLSIZE;i++) {
  3479.         np = nlist[i];
  3480.         while (np) {
  3481.             int j;
  3482.  
  3483.             if ((np->flag & ISKW) || (np->flag &ISUNCHANGE)) {
  3484.                 np = np->next;
  3485.                 continue;
  3486.             }
  3487.             if ((np->flag & ISUSED) == 0) {
  3488.                 np = np->next;
  3489.                 continue;
  3490.             }
  3491.  
  3492.             fprintf(xrefFile,"# ");
  3493.             for (j=0; j<np->len;j++) {
  3494.                 fprintf(xrefFile,"%c",np->name[j]);
  3495.             }
  3496.             p = np->filename;
  3497.             if (p == NULL) p = "<builtin>";
  3498.             n = GetFileNumber(p);
  3499.             fprintf(xrefFile," %d %d\n",n,np->srcline);
  3500.             np = np->next;
  3501.         }
  3502.     }
  3503. }
  3504. #endif
  3505.