Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20160501082013

Diff

Diff from 1.275 to:

Annotations

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

Annotated File View

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