Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20150720081406

Diff

Diff from 1.230 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/cpp/cpp.c

Annotated File View

ragge
1.230
1 /*      $Id: cpp.c,v 1.230 2015/07/20 08:14:06 ragge Exp $      */
ragge
1.1
2
3 /*
ragge
1.109
4  * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se).
ragge
1.1
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /*
29  * The C preprocessor.
30  * This code originates from the V6 preprocessor with some additions
31  * from V7 cpp, and at last ansi/c99 support.
ragge
1.215
32  *
33  *      - kfind() expands the input buffer onto XXX
34  *      - exparg() expand one buffer into another.
35  *              Recurses into submac() for fun-like macros.
36  *      - submac() replaces the given macro.
37  *              Recurses into subarg() for fun-like macros.
38  *      - subarg() expands fun-like macros.
39  *              Create strings, concats args, recurses into exparg.
ragge
1.1
40  */
pj
1.23
41
ragge
1.74
42 #include "config.h"
pj
1.23
43
ragge
1.108
44 #include <sys/stat.h>
ragge
1.1
45
46 #include <fcntl.h>
gmcgarry
1.81
47 #ifdef HAVE_UNISTD_H
ragge
1.1
48 #include <unistd.h>
gmcgarry
1.81
49 #endif
ragge
1.1
50 #include <stdio.h>
51 #include <stdarg.h>
52 #include <stdlib.h>
53 #include <string.h>
ragge
1.9
54 #include <time.h>
ragge
1.1
55
ragge
1.74
56 #include "compat.h"
ragge
1.1
57 #include "cpp.h"
58
gmcgarry
1.130
59 #ifndef S_ISDIR
60 #define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
61 #endif
62
ragge
1.126
63 #define SBSIZE  1000000
ragge
1.1
64
65 static usch     sbf[SBSIZE];
66 /* C command */
67
68 int tflag;      /* traditional cpp syntax */
plunky
1.134
69 #ifdef PCC_DEBUG
ragge
1.1
70 int dflag;      /* debug printouts */
ragge
1.215
71 //static void imp(const char *);
plunky
1.135
72 static void prline(const usch *s);
73 static void prrep(const usch *s);
ragge
1.36
74 #define DPRINT(x) if (dflag) printf x
75 #define DDPRINT(x) if (dflag > 1) printf x
plunky
1.135
76 #define IMP(x) if (dflag > 1) imp(x)
ragge
1.36
77 #else
78 #define DPRINT(x)
79 #define DDPRINT(x)
plunky
1.135
80 #define IMP(x)
ragge
1.1
81 #endif
ragge
1.36
82
ragge
1.195
83 int AflagCflagEflagMflagdMflagPflagMPflagMMDflag;
ragge
1.151
84 usch *Mfile, *MPfile, *Mxfile;
ragge
1.53
85 struct initar *initar;
plunky
1.187
86 int warnings;
ragge
1.197
87 FILE *of;
ragge
1.1
88
ragge
1.10
89 /* include dirs */
90 struct incs {
91         struct incs *next;
ragge
1.39
92         usch *dir;
ragge
1.108
93         dev_t dev;
94         ino_t ino;
ragge
1.20
95 } *incdir[2];
ragge
1.10
96
ragge
1.1
97 static struct symtab *filloc;
98 static struct symtab *linloc;
ragge
1.65
99 static struct symtab *pragloc;
ragge
1.224
100 static struct symtab *defloc;
ragge
1.10
101 int     trulvl;
102 int     flslvl;
103 int     elflvl;
104 int     elslvl;
105 usch *stringbuf = sbf;
ragge
1.1
106
107 /*
108  * Macro replacement list syntax:
109  * - For object-type macros, replacement strings are stored as-is.
110  * - For function-type macros, macro args are substituted for the
111  *   character WARN followed by the argument number.
ragge
1.214
112  * - The value element points to the beginning of the string.
plunky
1.191
113  *
ragge
1.213
114  * The first character in the replacement list is the number of arguments:
ragge
1.37
115  *   VARG  - ends with ellipsis, next char is argcount without ellips.
ragge
1.1
116  *   OBJCT - object-type macro
plunky
1.191
117  *   0     - empty parenthesis, foo()
ragge
1.1
118  *   1->   - number of args.
ragge
1.109
119  *
120  * WARN is used:
121  *      - in stored replacement lists to tell that an argument comes
122  *      - When expanding replacement lists to tell that the list ended.
ragge
1.116
123  *
124  * To ensure that an already expanded identifier won't get expanded
plunky
1.191
125  * again a EBLOCK char + its number is stored directly before any
ragge
1.116
126  * expanded identifier.
ragge
1.1
127  */
128
129 /* args for lookup() */
130 #define FIND    0
131 #define ENTER   1
132
plunky
1.166
133 /*
134  * No-replacement array.  If a macro is found and exists in this array
ragge
1.216
135  * then no replacement shall occur.
plunky
1.166
136  */
ragge
1.215
137 struct blocker {
138         struct blocker *next;
139         struct symtab *sp;
140 };
141 struct blocker *blkidx[RECMAX];
142 int blkidp;
143
144 static int readargs2(usch **, struct symtab *spconst usch **args);
145 static int readargs1(struct symtab *spconst usch **args);
146 static struct iobuf *exparg(intstruct iobuf *, struct iobuf *, struct blocker *);
147 static struct iobuf *subarg(struct symtab *spconst usch **argsintstruct blocker *);
plunky
1.143
148 static void usage(void);
149 static usch *xstrdup(const usch *str);
ragge
1.108
150 static void addidir(char *idirstruct incs **ww);
plunky
1.178
151 static void vsheap(const char *, va_list);
ragge
1.215
152 static int skipws(struct iobuf *ib);
153 static int getyp(usch *s);
ragge
1.218
154 static void *xrealloc(void *pint sz);
155 static void *xmalloc(int sz);
ragge
1.1
156
157 int
158 main(int argcchar **argv)
159 {
ragge
1.53
160         struct initar *it;
ragge
1.26
161         struct symtab *nl;
162         register int ch;
ragge
1.103
163         const usch *fn1, *fn2;
ragge
1.15
164
ragge
1.94
165 #ifdef TIMING
166         struct timeval t1t2;
167
168         (void)gettimeofday(&t1NULL);
169 #endif
170
plunky
1.188
171         while ((ch = getopt(argcargv"ACD:d:EI:i:MPS:tU:Vvx:")) != -1) {
ragge
1.1
172                 switch (ch) {
plunky
1.188
173                 case 'A'/* assembler input */
174                         Aflag++;
175                         break;
plunky
1.191
176
ragge
1.22
177                 case 'C'/* Do not discard comments */
178                         Cflag++;
179                         break;
180
plunky
1.187
181                 case 'E'/* treat warnings as errors */
182                         Eflag++;
183                         break;
184
plunky
1.142
185                 case 'D'/* define something */
ragge
1.53
186                 case 'i'/* include */
187                 case 'U'/* undef */
ragge
1.58
188                         /* XXX should not need malloc() here */
ragge
1.218
189                         if ((it = xmalloc(sizeof(struct initar))) == NULL)
ragge
1.58
190                                 error("couldn't apply -%c %s"choptarg);
ragge
1.53
191                         it->type = ch;
192                         it->str = optarg;
193                         it->next = initar;
194                         initar = it;
ragge
1.7
195                         break;
196
plunky
1.142
197                 case 'd':
plunky
1.144
198                         while (*optarg) {
199                                 switch(*optarg) {
200                                 case 'M'/* display macro definitions */
201                                         dMflag = 1;
202                                         Mflag = 1;
203                                         break;
204
205                                 default/* ignore others */
206                                         break;
207                                 }
208                                 optarg++;
plunky
1.142
209                         }
210                         break;
211
212                 case 'I':
213                 case 'S':
214                         addidir(optarg, &incdir[ch == 'I' ? INCINC : SYSINC]);
215                         break;
216
ragge
1.51
217                 case 'M'/* Generate dependencies for make */
218                         Mflag++;
219                         break;
220
gmcgarry
1.85
221                 case 'P'/* Inhibit generation of line numbers */
222                         Pflag++;
223                         break;
224
plunky
1.142
225                 case 't':
226                         tflag = 1;
ragge
1.7
227                         break;
228
plunky
1.134
229 #ifdef PCC_DEBUG
ragge
1.64
230                 case 'V':
ragge
1.18
231                         dflag++;
ragge
1.1
232                         break;
233 #endif
ragge
1.64
234                 case 'v':
plunky
1.200
235                         fprintf(stderr"PCC preprocessor version "VERSSTR"\n");
ragge
1.64
236                         break;
ragge
1.1
237
ragge
1.151
238                 case 'x':
ragge
1.195
239                         if (strcmp(optarg"MMD") == 0) {
240                                 MMDflag++;
241                         } else if (strcmp(optarg"MP") == 0) {
ragge
1.151
242                                 MPflag++;
243                         } else if (strncmp(optarg"MT,"3) == 0 ||
244                             strncmp(optarg"MQ,"3) == 0) {
245                                 usch *cp, *fn;
246                                 fn = stringbuf;
247                                 for (cp = (usch *)&optarg[3]; *cpcp++) {
248                                         if (*cp == '$' && optarg[1] == 'Q')
249                                                 savch('$');
250                                         savch(*cp);
251                                 }
plunky
1.191
252                                 savstr((const usch *)"");
ragge
1.151
253                                 if (Mxfile) { savch(' '); savstr(Mxfile); }
254                                 savch(0);
255                                 Mxfile = fn;
256                         } else
257                                 usage();
258                         break;
259
ragge
1.37
260                 case '?':
plunky
1.142
261                 default:
ragge
1.37
262                         usage();
ragge
1.1
263                 }
plunky
1.142
264         }
265
ragge
1.1
266         argc -= optind;
267         argv += optind;
268
ragge
1.103
269         filloc = lookup((const usch *)"__FILE__"ENTER);
270         linloc = lookup((const usch *)"__LINE__"ENTER);
271         pragloc = lookup((const usch *)"_Pragma"ENTER);
ragge
1.224
272         defloc = lookup((const usch *)"defined"ENTER);
ragge
1.215
273         filloc->value = stringbuf;
274         *stringbuf++ = FILLOC;
275         linloc->value = stringbuf;
276         *stringbuf++ = LINLOC;
ragge
1.213
277         pragloc->value = stringbuf;
ragge
1.215
278         *stringbuf++ = PRAGLOC;
ragge
1.224
279         defloc->value = stringbuf;
280         *stringbuf++ = DEFLOCsavstr((usch *)"defined"); savch(0);
ragge
1.15
281
ragge
1.12
282         if (tflag == 0) {
283                 time_t t = time(NULL);
ragge
1.39
284                 usch *n = (usch *)ctime(&t);
ragge
1.12
285
286                 /*
287                  * Manually move in the predefined macros.
288                  */
ragge
1.103
289                 nl = lookup((const usch *)"__TIME__"ENTER);
ragge
1.213
290                 nl->value = stringbuf;
ragge
1.12
291                 savch(OBJCT);
ragge
1.215
292                 n[19] = 0;
293                 (void)sheap("\"%s\""n+11); savch(0);
ragge
1.12
294
ragge
1.103
295                 nl = lookup((const usch *)"__DATE__"ENTER);
ragge
1.213
296                 nl->value = stringbuf;
297                 savch(OBJCT);
ragge
1.215
298                 n[24] = n[11] = 0;
299                 (void)sheap("\"%s%s\""n+4n+20); savch(0);
ragge
1.12
300
ragge
1.103
301                 nl = lookup((const usch *)"__STDC__"ENTER);
ragge
1.213
302                 nl->value = stringbuf;
303                 savch(OBJCT); savch('1');savch(0);
ragge
1.73
304
ragge
1.103
305                 nl = lookup((const usch *)"__STDC_VERSION__"ENTER);
ragge
1.213
306                 nl->value = stringbuf;
ragge
1.229
307                 savch(OBJCT); savstr((const usch *)"201112L"); savch(0);
ragge
1.12
308         }
ragge
1.1
309
ragge
1.60
310         if (Mflag && !dMflag) {
ragge
1.51
311                 usch *c;
312
313                 if (argc < 1)
314                         error("-M and no infile");
315                 if ((c = (usch *)strrchr(argv[0], '/')) == NULL)
316                         c = (usch *)argv[0];
317                 else
318                         c++;
319                 Mfile = stringbuf;
320                 savstr(c); savch(0);
ragge
1.151
321                 if (MPflag) {
322                         MPfile = stringbuf;
323                         savstr(c); savch(0);
324                 }
325                 if (Mxfile)
326                         Mfile = Mxfile;
ragge
1.51
327                 if ((c = (usch *)strrchr((char *)Mfile'.')) == NULL)
328                         error("-M and no extension: ");
329                 c[1] = 'o';
330                 c[2] = 0;
331         }
332
ragge
1.26
333         if (argc == 2) {
ragge
1.197
334                 if ((of = freopen(argv[1], "w"stdout)) == NULL)
ragge
1.37
335                         error("Can't creat %s"argv[1]);
ragge
1.26
336         } else
ragge
1.197
337                 of = stdout;
ragge
1.26
338
ragge
1.102
339         if (argc && strcmp(argv[0], "-")) {
340                 fn1 = fn2 = (usch *)argv[0];
341         } else {
342                 fn1 = NULL;
ragge
1.103
343                 fn2 = (const usch *)"";
ragge
1.102
344         }
345         if (pushfile(fn1fn20NULL))
ragge
1.26
346                 error("cannot open %s"argv[0]);
347
ragge
1.197
348         fclose(of);
ragge
1.94
349 #ifdef TIMING
350         (void)gettimeofday(&t2NULL);
351         t2.tv_sec -= t1.tv_sec;
352         t2.tv_usec -= t1.tv_usec;
353         if (t2.tv_usec < 0) {
354                 t2.tv_usec += 1000000;
355                 t2.tv_sec -= 1;
356         }
357         fprintf(stderr"cpp total time: %ld s %ld us\n",
plunky
1.159
358              (long)t2.tv_sec, (long)t2.tv_usec);
ragge
1.94
359 #endif
plunky
1.187
360         if (Eflag && warnings > 0)
361                 return 2;
362
ragge
1.37
363         return 0;
ragge
1.26
364 }
365
ragge
1.215
366 /*
367  * Write a character to an out buffer.
368  */
369 static void
370 putob(struct iobuf *obint ch)
371 {
372         if (ob->cptr == ob->bsz) {
373                 int sz = ob->bsz - ob->buf;
ragge
1.218
374                 ob->buf = xrealloc(ob->bufsz + BUFSIZ);
ragge
1.215
375                 ob->cptr = ob->buf + sz;
376                 ob->bsz = ob->buf + sz + BUFSIZ;
377         }
378 //      DDPRINT(("putob: iob %p pos %p ch %c (%d)\n", ob, ob->cptr, ch, ch));
379         *ob->cptr++ = ch;
380 }
381
ragge
1.218
382 static int nbufused;
ragge
1.215
383 /*
384  * Write a character to an out buffer.
385  */
386 static struct iobuf *
387 getobuf(void)
388 {
ragge
1.218
389         struct iobuf *iob = xmalloc(sizeof(struct iobuf));
ragge
1.215
390
ragge
1.218
391         nbufused++;
392         iob->buf = iob->cptr = xmalloc(BUFSIZ);
ragge
1.215
393         iob->bsz = iob->buf + BUFSIZ;
394         iob->ro = 0;
395         return iob;
396 }
397
398 /*
ragge
1.216
399  * Create a read-only input buffer.
ragge
1.215
400  */
401 static struct iobuf *
402 mkrobuf(const usch *s)
403 {
ragge
1.218
404         struct iobuf *iob = xmalloc(sizeof(struct iobuf));
ragge
1.214
405
ragge
1.218
406         nbufused++;
ragge
1.215
407         DPRINT(("mkrobuf %s\n"s));
408         iob->buf = iob->cptr = (usch *)s;
409         iob->bsz = iob->buf + strlen((char *)iob->buf);
410         iob->ro = 1;
411         return iob;
412 }
ragge
1.214
413
414 /*
ragge
1.215
415  * Copy a string to a buffer.
ragge
1.214
416  */
ragge
1.215
417 static struct iobuf *
418 strtobuf(usch *strstruct iobuf *iob)
419 {
420         DPRINT(("strtobuf iob %p buf %p str %s\n"iobiob->bufstr));
421         if (iob == NULL)
422                 iob = getobuf();
423         do {
424                 putob(iob, *str);
425         } while (*str++);
426         iob->cptr--;
427         return iob;
428 }
429
430 static void
431 bufree(struct iobuf *iob)
ragge
1.214
432 {
ragge
1.218
433         nbufused--;
ragge
1.215
434         if (iob->ro == 0)
435                 free(iob->buf);
436         free(iob);
ragge
1.214
437 }
438
ragge
1.108
439 static void
440 addidir(char *idirstruct incs **ww)
441 {
442         struct incs *w;
443         struct stat st;
444
plunky
1.163
445         if (stat(idir, &st) == -1 || !S_ISDIR(st.st_mode))
ragge
1.108
446                 return/* ignore */
447         if (*ww != NULL) {
448                 for (w = *www->nextw = w->next) {
plunky
1.203
449 #ifdef _WIN32
gmcgarry
1.131
450                         if (strcmp(w->diridir) == 0)
451                                 return;
452 #else
ragge
1.108
453                         if (w->dev == st.st_dev && w->ino == st.st_ino)
454                                 return;
gmcgarry
1.131
455 #endif
ragge
1.108
456                 }
plunky
1.203
457 #ifdef _WIN32
gmcgarry
1.131
458                 if (strcmp(w->diridir) == 0)
459                         return;
460 #else
ragge
1.108
461                 if (w->dev == st.st_dev && w->ino == st.st_ino)
462                         return;
gmcgarry
1.131
463 #endif
ragge
1.108
464                 ww = &w->next;
465         }
466         if ((w = calloc(sizeof(struct incs), 1)) == NULL)
467                 error("couldn't add path %s"idir);
468         w->dir = (usch *)idir;
469         w->dev = st.st_dev;
470         w->ino = st.st_ino;
471         *ww = w;
472 }
473
ragge
1.1
474 void
plunky
1.143
475 line(void)
ragge
1.9
476 {
ragge
1.216
477         int cn;
ragge
1.9
478
ragge
1.216
479         if (!ISDIGIT(c = skipws(0)))
ragge
1.9
480                 goto bad;
ragge
1.216
481         n = 0;
482         do {
483                 n = n * 10 + c - '0';
484         } while (ISDIGIT(c = cinput()));
485
ragge
1.209
486         /* Can only be decimal number here between 1-2147483647 */
ragge
1.216
487         if (n < 1 || n > 2147483647)
ragge
1.209
488                 goto bad;
489
ragge
1.219
490         ifiles->lineno = n;
plunky
1.185
491         ifiles->escln = 0;
ragge
1.230
492         if ((c = skipws(NULL)) != '\n') {
ragge
1.216
493                 if (c == 'L')
494                         c = cinput();
495                 if (c != '\"')
496                         goto bad;
497                 /* loses space on heap... does it matter? */
498                 ifiles->fname = stringbuf+1;
499                 faststr(csavch);
500                 stringbuf--;
501                 savch(0);
ragge
1.97
502
ragge
1.216
503                 c = skipws(0);
ragge
1.37
504         }
ragge
1.216
505         if (c != '\n')
plunky
1.181
506                 goto bad;
507
ragge
1.219
508         prtline(0);
509         cunput('\n');
plunky
1.181
510         return;
ragge
1.9
511
plunky
1.182
512 bad:    error("bad #line");
ragge
1.9
513 }
514
gmcgarry
1.189
515 #ifdef MACHOABI
516
517 /*
518  * Search for framework header file.
519  * Return 1 on success.
520  */
521
522 static int
523 fsrch_macos_framework(const usch *fnconst usch *dir)
524 {
525         usch *saved_stringbuf = stringbuf;
526         usch *s = (usch *)strchr((const char*)fn'/');
gmcgarry
1.194
527         usch *nm;
528         usch *p;
529         int len  = s - fn;
530
531         if (s == NULL)
532                 return 0;
533
534 //      fprintf(stderr, "searching for %s in %s\n", (const char *)fn, (const char *)dir);
gmcgarry
1.189
535
gmcgarry
1.194
536         nm = savstr(dir);
537         savch(0);
538         p = savstr(fn);
539         stringbuf = p + len;
540         savch(0);
541 //      fprintf(stderr, "comparing \"%s\" against \"%.*s\"\n", nm, len, fn);
542         p = (usch *)strstr((const char *)nm, (const char *)p);
543 //      fprintf(stderr, "p = %s\n", (const char *)p);
544         if (p != NULL) {
545                 stringbuf = p;
gmcgarry
1.189
546                 savch(0);
gmcgarry
1.194
547                 return fsrch_macos_framework(fnnm);
548         }
gmcgarry
1.189
549
gmcgarry
1.194
550         p = nm + strlen((char *)nm) - 1;
551         while (*p == '/')
552                 p--;
553         while (*p != '/')
554                 p--;
555         stringbuf = ++p;
556         savstr((const usch *)"Frameworks/");
557         stringbuf = savstr(fn) + len;
558         savstr((const usch*)".framework/Headers");
559         savstr(s);
560         savch(0);
gmcgarry
1.189
561
gmcgarry
1.194
562 //      fprintf(stderr, "nm: %s\n", nm);
gmcgarry
1.189
563
gmcgarry
1.194
564         if (pushfile(nmfnSYSINCNULL) == 0)
565                 return 1;
566 //      fprintf(stderr, "not found %s, continuing...\n", nm);
gmcgarry
1.189
567
568         stringbuf = saved_stringbuf;
569
570         return 0;
571 }
572
573 #endif
574
ragge
1.10
575 /*
ragge
1.102
576  * Search for and include next file.
577  * Return 1 on success.
578  */
579 static int
ragge
1.103
580 fsrch(const usch *fnint idxstruct incs *w)
ragge
1.102
581 {
582         int i;
583
584         for (i = idxi < 2i++) {
585                 if (i > idx)
586                         w = incdir[i];
587                 for (; ww = w->next) {
588                         usch *nm = stringbuf;
589
590                         savstr(w->dir); savch('/');
591                         savstr(fn); savch(0);
592                         if (pushfile(nmfniw->next) == 0)
593                                 return 1;
594                         stringbuf = nm;
595                 }
596         }
gmcgarry
1.189
597
598 #ifdef MACHOABI
599         /*
600          * On MacOS, we may have to do some clever stuff
601          * to resolve framework headers.
plunky
1.191
602          */
gmcgarry
1.194
603         {
604                 usch *dir = stringbuf;
605                 savstr(ifiles->orgfn);
606                 stringbuf = (usch *)strrchr((char *)dir'/');
607                 if (stringbuf != NULL) {
608                         stringbuf++;
609                         savch(0);
610                         if (fsrch_macos_framework(fndir) == 1)
611                                 return 1;
612                 }
613                 stringbuf = dir;
614
615                 if (fsrch_macos_framework(fn, (const usch *)"/Library/Frameworks/") == 1)
616                         return 1;
617
618                 if (fsrch_macos_framework(fn, (const usch *)"/System/Library/Frameworks/") == 1)
619                         return 1;
620         }
gmcgarry
1.189
621 #endif
622
ragge
1.102
623         return 0;
624 }
625
ragge
1.132
626 static void
627 prem(void)
628 {
629         error("premature EOF");
630 }
631
ragge
1.221
632 static struct iobuf *
633 incfn(void)
plunky
1.193
634 {
ragge
1.221
635         struct iobuf *ob;
636         struct symtab *nl;
637         usch *sb;
plunky
1.193
638         int c;
639
ragge
1.221
640         sb = stringbuf;
641         if (spechr[c = skipws(NULL)] & C_ID0) {
642                 heapid(c);
643                 if ((nl = lookup(sbFIND)) == NULL)
644                         return NULL;
645
646                 stringbuf = sb;
647                 if (kfind(nl) == 0)
648                         return NULL;
649                 ob = strtobuf(sbNULL);
650         } else {
651                 ob = getobuf();
652                 putob(obc);
653                 while ((c = cinput()) && c != '\n')
654                         putob(obc);
655                 if (c != '\n')
656                         return NULL;
657                 cunput(c);
plunky
1.193
658         }
ragge
1.221
659         putob(ob0);
660         ob->cptr--;
661
662         /* now we have an (expanded?) filename in obuf */
663         while (ob->buf < ob->cptr && ISWS(ob->cptr[-1]))
664                 ob->cptr--;
665
666         if (ob->buf[0] != '\"' && ob->buf[0] != '<')
667                 return NULL;
668         if (ob->cptr[-1] != '\"' && ob->cptr[-1] != '>')
669                 return NULL;
670         ob->cptr[-1] = 0;
671         return ob;
plunky
1.193
672 }
673
ragge
1.102
674 /*
ragge
1.10
675  * Include a file. Include order:
ragge
1.20
676  * - For <...> files, first search -I directories, then system directories.
677  * - For "..." files, first search "current" dir, then as <...> files.
ragge
1.10
678  */
ragge
1.9
679 void
plunky
1.143
680 include(void)
ragge
1.3
681 {
ragge
1.221
682         struct iobuf *ob;
683         usch *fn, *nm;
ragge
1.3
684
ragge
1.37
685         if (flslvl)
686                 return;
ragge
1.97
687
ragge
1.221
688         if ((ob = incfn()) == NULL/* get include file name in obuf */
689                 error("bad #include");
plunky
1.193
690
ragge
1.221
691         fn = xstrdup(ob->buf) + 1;      /* Save on string heap? */
692         bufree(ob);
693         if (fn[-1] == '\"') {
694                 /* local includes. first try directly. */
695                 if (pushfile(fnfn0NULL) == 0)
696                         goto okret;
697                 /* nope, failed, try to create a path for it */
698                 if ((nm = (usch *)strrchr((char *)ifiles->orgfn'/'))) {
699                         ob = strtobuf((usch *)ifiles->orgfnNULL);
700                         ob->cptr = ob->buf + (nm - ifiles->orgfn) + 1;
701                         strtobuf(fnob);
702                         putob(ob0);
703                         nm = xstrdup(ob->buf);
704                         bufree(ob);
705                         if (pushfile(nmnm0NULL) == 0) {
706                                 free(fn);
707                                 goto okret;
708                         }
ragge
1.53
709                 }
ragge
1.221
710         }
plunky
1.193
711         if (fsrch(fn0incdir[0]))
ragge
1.102
712                 goto okret;
ragge
1.10
713
plunky
1.193
714         error("cannot find '%s'"fn);
ragge
1.37
715         /* error() do not return */
ragge
1.3
716
ragge
1.97
717 okret:
ragge
1.219
718         prtline(1);
ragge
1.37
719 }
720
ragge
1.102
721 void
plunky
1.143
722 include_next(void)
ragge
1.102
723 {
ragge
1.221
724         struct iobuf *ob;
725         usch *nm;
ragge
1.105
726
ragge
1.107
727         if (flslvl)
728                 return;
plunky
1.193
729
ragge
1.221
730         if ((ob = incfn()) == NULL/* get include file name in obuf */
731                 error("bad #include_next");
plunky
1.193
732
ragge
1.221
733         nm = xstrdup(ob->buf+1);
734         bufree(ob);
plunky
1.193
735
ragge
1.221
736         if (fsrch(nmifiles->idxifiles->incs) == 0)
737                 error("cannot find '%s'"nm);
ragge
1.219
738         prtline(1);
ragge
1.102
739 }
740
ragge
1.79
741 /*
742  * Compare two replacement lists, taking in account comments etc.
743  */
744 static int
ragge
1.103
745 cmprepl(const usch *oconst usch *n)
ragge
1.79
746 {
ragge
1.213
747         for (; *oo++, n++) {
ragge
1.79
748                 /* comment skip */
ragge
1.213
749                 if (*o == '/' && o[1] == '*') {
750                         while (*o != '*' || o[1] != '/')
751                                 o++;
752                         o += 2;
753                 }
754                 if (*n == '/' && n[1] == '*') {
755                         while (*n != '*' || n[1] != '/')
756                                 n++;
757                         n += 2;
ragge
1.79
758                 }
759                 while (*o == ' ' || *o == '\t')
ragge
1.213
760                         o++;
ragge
1.79
761                 while (*n == ' ' || *n == '\t')
ragge
1.213
762                         n++;
ragge
1.79
763                 if (*o != *n)
764                         return 1;
765         }
766         return 0;
767 }
768
ragge
1.97
769 static int
770 isell(void)
771 {
ragge
1.215
772         if (cinput() != '.' || cinput() != '.')
ragge
1.97
773                 return 0;
774         return 1;
775 }
776
ragge
1.215
777 static int
778 skipwscmnt(struct iobuf *ib)
779 {
780         /* XXX comment */
781         return skipws(ib);
782 }
783
784 static int
785 findarg(usch *susch **argsint narg)
786 {
787         int i;
788
789         for (i = 0i < nargi++)
790                 if (strcmp((char *)s, (char *)args[i]) == 0)
791                         return i;
792         return -1;
793 }
794
795 /*
796  * gcc extensions:
797  * #define e(a...) f(s, a) ->  a works as __VA_ARGS__
798  * #define e(fmt, ...) f(s, fmt , ##__VA_ARGS__) -> remove , if no args
799  */
ragge
1.3
800 void
plunky
1.143
801 define(void)
ragge
1.1
802 {
803         struct symtab *np;
ragge
1.215
804         usch *args[MAXARGS+1], *ubuf, *sbeg, *bpcc[2], *vararg;
805         int ciredefoCflagt;
806         int narg = -1;
ragge
1.91
807         int wascon;
ragge
1.1
808
ragge
1.37
809         if (flslvl)
810                 return;
ragge
1.215
811
812         oCflag = CflagCflag = 0/* Ignore comments here */
813         if (!ISID0(c = skipws(0)))
ragge
1.37
814                 goto bad;
ragge
1.36
815
ragge
1.215
816         bp = heapid(c);
817         np = lookup(bpENTER);
818         if (np->value) {
819                 stringbuf = bp;
820                 redef = 1;
821         } else
822                 redef = 0;
ragge
1.1
823
ragge
1.215
824         vararg = NULL;
ragge
1.213
825         sbeg = stringbuf++;
ragge
1.215
826         if ((c = cinput()) == '(') {
ragge
1.1
827                 narg = 0;
828                 /* function-like macros, deal with identifiers */
ragge
1.215
829                 c = skipws(0);
ragge
1.37
830                 for (;;) {
ragge
1.215
831                         switch (c) {
832                         case ')':
ragge
1.1
833                                 break;
ragge
1.215
834                         case '.':
835                                 if (isell() == 0 || (c = skipws(0)) != ')')
ragge
1.37
836                                         goto bad;
ragge
1.215
837                                 vararg = (usch *)"__VA_ARGS__";
ragge
1.37
838                                 break;
ragge
1.215
839                         default:
840                                 if (!ISID0(c))
841                                         goto bad;
842
843                                 bp = heapid(c);
ragge
1.72
844                                 /* make sure there is no arg of same name */
ragge
1.215
845                                 if (findarg(bpargsnarg) >= 0)
846                                         error("Duplicate parameter \"%s\""bp);
ragge
1.112
847                                 if (narg == MAXARGS)
848                                         error("Too many macro args");
ragge
1.215
849                                 args[narg++] = xstrdup(bp);
850                                 stringbuf = bp;
851                                 switch ((c = skipws(0))) {
852                                 case ','break;
853                                 case ')'continue;
854                                 case '.':
855                                         if (isell() == 0 || skipws(0) != ')')
ragge
1.86
856                                                 goto bad;
ragge
1.215
857                                         vararg = args[--narg];
ragge
1.225
858                                         c = ')';
859                                         continue;
ragge
1.215
860                                 default:
861                                         goto bad;
ragge
1.86
862                                 }
ragge
1.215
863                                 c = skipws(0);
ragge
1.37
864                         }
ragge
1.215
865                         if (c == ')')
866                                 break;
ragge
1.1
867                 }
ragge
1.215
868                 c = skipws(0);
ragge
1.36
869         } else if (c == '\n') {
ragge
1.8
870                 /* #define foo */
ragge
1.36
871                 ;
ragge
1.132
872         } else if (c == 0) {
873                 prem();
ragge
1.215
874         } else if (!ISWS(c))
ragge
1.37
875                 goto bad;
ragge
1.1
876
ragge
1.215
877         Cflag = oCflag/* Enable comments again */
ragge
1.1
878
ragge
1.215
879         if (vararg)
ragge
1.213
880                 stringbuf++;
881
ragge
1.215
882         if (ISWS(c))
883                 c = skipwscmnt(0);
884
ragge
1.226
885 #define DELEWS() while (stringbuf > sbeg+1+(vararg!=NULL) && ISWS(stringbuf[-1])) stringbuf--
ragge
1.72
886
ragge
1.1
887         /* parse replacement-list, substituting arguments */
ragge
1.215
888         wascon = 0;
ragge
1.36
889         while (c != '\n') {
ragge
1.222
890                 cc[0] = ccc[1] = inc2();
ragge
1.215
891                 t = getyp(cc);
892                 cunput(cc[1]);
893
894                 switch (t) {
895                 case ' ':
896                 case '\t':
ragge
1.2
897                         ubuf = stringbuf;
ragge
1.215
898                         savch(' '); /* save only one space */
899                         while ((c = cinput()) == ' ' || c == '\t')
900                                 ;
ragge
1.1
901                         continue;
902
ragge
1.97
903                 case '#':
ragge
1.215
904                         if (cc[1] == '#') {
ragge
1.97
905                                 /* concat op */
ragge
1.215
906                                 (void)cinput(); /* eat # */
907                                 DELEWS();
ragge
1.97
908                                 savch(CONC);
ragge
1.215
909                                 if (ISID0(c = skipws(0)) && narg >= 0)
910                                         wascon = 1;
ragge
1.97
911                                 if (c == '\n')
ragge
1.215
912                                        &nbs