Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20160206093921

Diff

Diff from 1.252 to:

Annotations

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

Annotated File View

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