Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libpp/pplex.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1986-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Research
24
*
25
* preprocessor lexical analyzer
26
* standalone and tokenizing lexer combined in one source
27
* define CPP=1 for standalone
28
*/
29
30
#include "pplib.h"
31
#include "ppfsm.h"
32
33
#if CPP
34
35
/*
36
* standalone entry point
37
*/
38
39
#define PPCPP_T void
40
41
#define START QUICK
42
#define INMACRO(x) INQMACRO(x)
43
#define DOSTRIP() (st&STRIP)
44
45
#if DEBUG & TRACE_debug
46
static int hit[LAST-TERMINAL+2];
47
#endif
48
49
#define BACKIN() (ip--)
50
#define BACKOUT() (op=tp)
51
#define CACHE() do{CACHEINX();CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
52
#define CACHEIN() do{CACHEINX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
53
#define CACHEINX() do{ip=pp.in->nextchr;}while(0)
54
#define CACHEOUT() do{CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
55
#define CACHEOUTX() do{tp=op=pp.outp;xp=pp.oute;if(sp)sp=op;}while(0)
56
#define GETCHR() (*(unsigned char*)ip++)
57
#define LASTCHR() (*(ip-1))
58
#define LASTOUT() ((op>pp.outbuf)?*(op-1):pp.lastout)
59
#define SKIPIN() (ip++)
60
#define PUTCHR(c) (*op++=(c))
61
#define SETCHR(c) (*op=(c))
62
#define SYNC() do{SYNCINX();SYNCOUTX();pp.state=st;}while(0)
63
#define SYNCIN() do{SYNCINX();pp.state=st;}while(0)
64
#define SYNCINX() do{pp.in->nextchr=ip;}while(0)
65
#define SYNCOUT() do{SYNCOUTX();pp.state=st;}while(0)
66
#define SYNCOUTX() do{if(sp)op=tp=sp;pp.outp=op;}while(0)
67
#define UNGETCHR(c) (*--ip=(c))
68
69
#define PPCHECKOUT() do{if(op>xp){{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}}}while(0)
70
#define PPCHECKOUTSP() do{if(op>xp){if(sp)op=sp;else{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}}}while(0)
71
#define PPCHECKOUTTP() do{if(op>xp){{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}tp=op;}}while(0)
72
73
#define PPSYNCLINE() do { \
74
if ((st & (ADD|HIDDEN)) && !(*pp.control & SKIP)) \
75
{ \
76
if (spliced) \
77
{ \
78
error_info.line += spliced; \
79
spliced = 0; \
80
} \
81
else \
82
{ \
83
if (st & ADD) \
84
{ \
85
st &= ~ADD; \
86
m = pp.addp - pp.addbuf; \
87
pp.addp = pp.addbuf; \
88
memcpy(op, pp.addbuf, m); \
89
op += m; \
90
PPCHECKOUT(); \
91
} \
92
if (pp.linesync) \
93
{ \
94
if ((st & SYNCLINE) || pp.hidden >= MAXHIDDEN) \
95
{ \
96
pp.hidden = 0; \
97
st &= ~(HIDDEN|SYNCLINE); \
98
if (error_info.line) \
99
{ \
100
if (LASTOUT() != '\n') \
101
PUTCHR('\n'); \
102
SYNCOUT(); \
103
(*pp.linesync)(error_info.line, error_info.file); \
104
CACHEOUT(); \
105
} \
106
} \
107
else \
108
{ \
109
m = pp.hidden; \
110
pp.hidden = 0; \
111
st &= ~HIDDEN; \
112
while (m-- > 0) \
113
PUTCHR('\n'); \
114
} \
115
} \
116
else \
117
{ \
118
pp.hidden = 0; \
119
st &= ~HIDDEN; \
120
PUTCHR('\n'); \
121
} \
122
} \
123
} \
124
} while (0)
125
126
#if POOL
127
128
/*
129
* <wait.h> is poison here so pool moved to the end
130
*/
131
132
static void poolstatus(void);
133
static void pool(void);
134
135
#endif
136
137
#else
138
139
/*
140
* return next pp token
141
*
142
* NOTE: pp.token points to at least MAXTOKEN*2 chars and is
143
* truncated back to MAXTOKEN on EOB
144
*/
145
146
#define PPCPP_T int
147
#define ppcpp pplex
148
149
#define START TOKEN
150
#define INMACRO(x) INTMACRO(x)
151
#define DOSTRIP() ((st&STRIP)||pp.level==1&&(st&(COMPILE|JOINING))==COMPILE&&!(pp.option&PRESERVE))
152
153
#define st pp.state
154
#define tp pp.token
155
#define xp &pp.token[MAXTOKEN]
156
157
#define BACKIN() (ip--)
158
#define BACKOUT() (op=pp.token)
159
#define CACHE() do{CACHEIN();CACHEOUT();}while(0)
160
#define CACHEIN() (ip=pp.in->nextchr)
161
#define CACHEOUT() (op=pp.token)
162
#define GETCHR() (*(unsigned char*)ip++)
163
#define LASTCHR() (*(ip-1))
164
#define PUTCHR(c) (*op++=(c))
165
#define SETCHR(c) (*op=(c))
166
#define SKIPIN() (ip++)
167
#define SYNC() do{SYNCIN();SYNCOUT();}while(0)
168
#define SYNCIN() (pp.in->nextchr=ip)
169
#define SYNCOUT() (pp.toknxt=op)
170
#define UNGETCHR(c) (*--ip=(c))
171
172
#endif
173
174
PPCPP_T
175
ppcpp(void)
176
{
177
register short* rp;
178
register char* ip;
179
register int state;
180
register int c;
181
register char* op;
182
char* bp;
183
int n;
184
int m;
185
int quot;
186
int quotquot;
187
int comdelim = 0;
188
int comstart = 0;
189
int comwarn = 0;
190
char* s;
191
struct ppsymbol* sym;
192
#if CPP
193
register long st;
194
char* tp;
195
char* xp;
196
char* sp = 0;
197
int qual = 0;
198
int spliced = 0;
199
#else
200
int qual;
201
#endif
202
203
#if CPP
204
#if POOL
205
fsm_pool:
206
#endif
207
#else
208
count(pplex);
209
#endif
210
error_info.indent++;
211
pp.level++;
212
CACHE();
213
#if !CPP
214
fsm_top:
215
qual = 0;
216
#endif
217
fsm_start:
218
#if CPP
219
PPCHECKOUTSP();
220
tp = op;
221
#endif
222
state = START;
223
fsm_begin:
224
bp = ip;
225
do
226
{
227
rp = fsm[state];
228
fsm_get:
229
while (!(state = rp[c = GETCHR()]));
230
fsm_next:
231
;
232
} while (state > 0);
233
if (((state = ~state) != S_COMMENT || pp.comment || c == '/' && !INCOMMENT(rp)) && (n = ip - bp - 1) > 0)
234
{
235
ip = bp;
236
#if CPP
237
if (op == tp && (st & (ADD|HIDDEN)) && !(st & PASSTHROUGH) && !(pp.option & PRESERVE))
238
switch (TERM(state))
239
{
240
case S_SHARP:
241
break;
242
case S_CHRB:
243
case S_NL:
244
if (*ip == '\n')
245
break;
246
/*FALLTHROUGH*/
247
default:
248
if ((pp.option & PRESERVE) && !(st & NEWLINE) && c != '\n')
249
break;
250
PPSYNCLINE();
251
tp = op;
252
break;
253
}
254
#endif
255
MEMCPY(op, ip, n);
256
ip++;
257
}
258
count(terminal);
259
#if CPP && (DEBUG & TRACE_debug)
260
hit[(state & SPLICE) ? (elementsof(hit) - 1) : (TERM(state) - TERMINAL)]++;
261
#endif
262
fsm_terminal:
263
debug((-9, "TERM %s > %s%s%s |%-*.*s|%s|", pplexstr(INDEX(rp)), pplexstr(state), (st & NEWLINE) ? "|NEWLINE" : "", (st & SKIPCONTROL) ? "|SKIP" : "", op - tp, op - tp, tp, pptokchr(c)));
264
switch (TERM(state))
265
{
266
267
#if !CPP
268
case S_CHR:
269
PUTCHR(c);
270
break;
271
#endif
272
273
case S_CHRB:
274
BACKIN();
275
#if CPP
276
st &= ~NEWLINE;
277
pp.in->flags |= IN_tokens;
278
count(token);
279
goto fsm_start;
280
#else
281
c = *tp;
282
break;
283
#endif
284
285
case S_COMMENT:
286
switch (c)
287
{
288
case '\n':
289
if (!INCOMMENTXX(rp))
290
{
291
qual = 0;
292
if (!comstart) comstart = comdelim = error_info.line;
293
error_info.line++;
294
if (pp.comment) PUTCHR(c);
295
else BACKOUT();
296
#if CPP
297
rp = fsm[COM2];
298
bp = ip;
299
goto fsm_get;
300
#else
301
state = COM2;
302
goto fsm_begin;
303
#endif
304
}
305
else if (comwarn < 0 && !(pp.mode & HOSTED))
306
error(1, "/* appears in // comment");
307
break;
308
case '*':
309
if (!comwarn && !(pp.mode & HOSTED))
310
{
311
if (INCOMMENTXX(rp)) comwarn = -1;
312
else if (comstart && comstart != error_info.line)
313
{
314
if (qual || comdelim < error_info.line - 1)
315
{
316
error(1, "/* appears in /* ... */ comment starting at line %d", comstart);
317
comwarn = 1;
318
}
319
else comdelim = error_info.line;
320
}
321
}
322
fsm_comment:
323
PUTCHR(c);
324
#if CPP
325
rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
326
bp = ip;
327
goto fsm_get;
328
#else
329
state = INCOMMENTXX(rp) ? COM5 : COM3;
330
goto fsm_begin;
331
#endif
332
case '/':
333
if (!INCOMMENT(rp))
334
{
335
if (!(pp.mode & HOSTED))
336
error(1, "*/ appears outside of comment");
337
BACKIN();
338
#if CPP
339
st &= ~NEWLINE;
340
pp.in->flags |= IN_tokens;
341
count(token);
342
goto fsm_start;
343
#else
344
c = '*';
345
if (!pp.comment) PUTCHR(c);
346
goto fsm_token;
347
#endif
348
}
349
else if (INCOMMENTXX(rp))
350
{
351
if (!(pp.mode & HOSTED))
352
{
353
if (comwarn < 0) comwarn = 0;
354
else if (!comwarn)
355
{
356
comwarn = 1;
357
error(1, "*/ appears in // comment");
358
}
359
}
360
goto fsm_comment;
361
}
362
break;
363
case EOF:
364
BACKIN();
365
if (!(pp.mode & HOSTED))
366
{
367
if (comstart) error(2, "unterminated /* ... */ comment starting at line %d", comstart);
368
else if (INCOMMENTXX(rp)) error(2, "unterminated // ... comment");
369
else error(2, "unterminated /* ... */ comment");
370
}
371
break;
372
}
373
#if CPP
374
if (!pp.comment || sp)
375
{
376
#if COMPATIBLE
377
if (!(pp.state & COMPATIBILITY) || *bp == ' ' || *bp == '\t')
378
#endif
379
{
380
BACKOUT();
381
PUTCHR(' ');
382
tp = op;
383
}
384
}
385
else if (pp.in->type & IN_TOP)
386
#else
387
if (pp.comment && !(st & (COLLECTING|DIRECTIVE|JOINING)) && !(*pp.control & SKIP) && (pp.in->type & IN_TOP))
388
#endif
389
{
390
st &= ~HIDDEN;
391
pp.hidden = 0;
392
*(op - (c != '\n')) = 0;
393
m = (op - (c != '\n') - tp > MAXTOKEN - 6) ? (error_info.line - MAXHIDDEN) : 0;
394
BACKOUT();
395
SYNC();
396
while (*tp != '/') tp++;
397
(*pp.comment)(c == '\n' ? "//" : "/*", tp + 2, c == '\n' ? "" : (st & HEADER) ? "*/\n" : "*/", comstart ? comstart : error_info.line);
398
CACHE();
399
comstart = m;
400
}
401
if (comstart)
402
{
403
st |= HIDDEN;
404
pp.hidden += error_info.line - comstart;
405
comstart = 0;
406
}
407
qual = comwarn = comdelim = 0;
408
BACKOUT();
409
if (c == '\n') goto fsm_newline;
410
if ((st & PASSTHROUGH) && ((st & (HIDDEN|NEWLINE)) || *ip == '\n'))
411
{
412
if (*ip == '\n')
413
ip++;
414
goto fsm_newline;
415
}
416
#if COMPATIBLE
417
if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
418
#endif
419
#if !CPP
420
if (pp.level > 1 && !(st & (NOSPACE|SKIPCONTROL)))
421
{
422
#if COMPATIBLE
423
c = ((st & (COMPATIBILITY|DEFINITION)) == ((COMPATIBILITY|DEFINITION))) ? '\t' : ' ';
424
#else
425
c = ' ';
426
#endif
427
goto fsm_return;
428
}
429
#endif
430
goto fsm_start;
431
432
case S_EOB:
433
if (c)
434
{
435
if (state = fsm[TERMINAL][INDEX(rp)+1])
436
goto fsm_terminal;
437
#if CPP
438
#if POOL
439
if (pp.pool.input)
440
{
441
BACKIN();
442
SYNC();
443
pool();
444
CACHE();
445
goto fsm_pool;
446
}
447
#endif
448
SYNCOUT();
449
return;
450
#else
451
BACKIN();
452
c = 0;
453
goto fsm_return;
454
#endif
455
}
456
{
457
register struct ppinstk* cur = pp.in;
458
register struct ppinstk* prv = pp.in->prev;
459
460
#if CPP
461
if (sp) op = sp;
462
#endif
463
switch (cur->type)
464
{
465
case IN_BUFFER:
466
case IN_INIT:
467
case IN_RESCAN:
468
#if CPP
469
if (prv)
470
#else
471
if (!(st & PASSEOF) && prv)
472
#endif
473
{
474
if (cur->type == IN_RESCAN || cur->type == IN_BUFFER)
475
{
476
fsm_pop:
477
#if PROTOTYPE
478
if (cur->flags & IN_prototype)
479
pppclose(cur->buffer + PPBAKSIZ);
480
else
481
#endif
482
if (!(cur->flags & IN_static))
483
free(cur->buffer);
484
}
485
while (pp.control-- != cur->control)
486
error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
487
st |= NEWLINE;
488
error_info.file = cur->file;
489
error_info.line = cur->line;
490
pp.hidden = 0;
491
#if CPP
492
spliced = 0;
493
#endif
494
if (cur->flags & IN_hosted)
495
{
496
pp.mode |= HOSTED;
497
pp.flags |= PP_hosted;
498
}
499
else
500
{
501
pp.mode &= ~HOSTED;
502
pp.flags &= ~PP_hosted;
503
}
504
#if !CPP && CATSTRINGS
505
if (st & JOINING) st |= HIDDEN|SYNCLINE;
506
else
507
#endif
508
{
509
st &= ~(HIDDEN|SYNCLINE);
510
switch (cur->type)
511
{
512
case IN_BUFFER:
513
case IN_INIT:
514
if (!prv->prev) break;
515
/*FALLTHROUGH*/
516
case IN_FILE:
517
case IN_RESCAN:
518
if (prv->type == IN_FILE || cur->type == IN_FILE && (prv->type == IN_RESCAN || prv->type == IN_MULTILINE))
519
{
520
if (pp.linesync && (cur->type != IN_RESCAN || (cur->flags & IN_sync)))
521
{
522
POP();
523
SYNCOUT();
524
(*pp.linesync)(error_info.line, error_info.file);
525
CACHEOUT();
526
prv = pp.in;
527
}
528
}
529
#if DEBUG
530
else if (!prv->prev)
531
{
532
/*UNDENT*/
533
c = 0;
534
#if DEBUG & TRACE_count
535
if (pp.test & TEST_count)
536
{
537
c = 1;
538
sfprintf(sfstderr, "\n");
539
sfprintf(sfstderr, "%7d: pplex calls\n", pp.counter.pplex);
540
sfprintf(sfstderr, "%7d: terminal states\n", pp.counter.terminal);
541
sfprintf(sfstderr, "%7d: emitted tokens\n", pp.counter.token);
542
sfprintf(sfstderr, "%7d: input stream pushes\n", pp.counter.push);
543
sfprintf(sfstderr, "%7d: macro candidates\n", pp.counter.candidate);
544
sfprintf(sfstderr, "%7d: macro expansions\n", pp.counter.macro);
545
sfprintf(sfstderr, "%7d: function macros\n", pp.counter.function);
546
}
547
#endif
548
#if CPP && (DEBUG & TRACE_debug)
549
if (pp.test & TEST_hit)
550
{
551
c = 1;
552
sfprintf(sfstderr, "\n");
553
if (hit[elementsof(hit) - 1])
554
sfprintf(sfstderr, "%7d: SPLICE\n", hit[elementsof(hit) - 1]);
555
for (n = 0; n < elementsof(hit) - 1; n++)
556
if (hit[n])
557
sfprintf(sfstderr, "%7d: %s\n", hit[n], pplexstr(TERMINAL + n));
558
}
559
#endif
560
if (pp.test & (TEST_hashcount|TEST_hashdump))
561
{
562
c = 1;
563
sfprintf(sfstderr, "\n");
564
hashdump(NiL, (pp.test & TEST_hashdump) ? HASH_BUCKET : 0);
565
}
566
if (c) sfprintf(sfstderr, "\n");
567
/*INDENT*/
568
}
569
#endif
570
break;
571
}
572
}
573
#if CHECKPOINT
574
if (cur->index)
575
{
576
SYNCOUT();
577
cur->index->end = ppoffset();
578
cur->index = 0;
579
CACHEOUT();
580
}
581
#endif
582
POP();
583
bp = ip;
584
tp = op;
585
goto fsm_get;
586
}
587
c = EOF;
588
break;
589
case IN_COPY:
590
if (prv)
591
{
592
error_info.line = cur->line;
593
if (!(prv->symbol->flags & SYM_MULTILINE))
594
prv->symbol->flags |= SYM_DISABLED;
595
POP();
596
bp = ip;
597
goto fsm_get;
598
}
599
c = EOF;
600
break;
601
case IN_EXPAND:
602
if (prv)
603
{
604
error_info.line = cur->line;
605
free(cur->buffer);
606
POP();
607
bp = ip;
608
goto fsm_get;
609
}
610
c = EOF;
611
break;
612
case IN_FILE:
613
FGET(c, c, tp, xp);
614
if (c == EOB)
615
{
616
#if CPP
617
if ((st & (NOTEXT|HIDDEN)) == HIDDEN && LASTOUT() != '\n')
618
PUTCHR('\n');
619
if (prv)
620
#else
621
if (st & EOF2NL)
622
{
623
st &= ~EOF2NL;
624
*(ip - 1) = c = '\n';
625
}
626
else if (!(st & (FILEPOP|PASSEOF)) && prv)
627
#endif
628
{
629
if (!(cur->flags & IN_newline))
630
{
631
cur->flags |= IN_newline;
632
if ((pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC && LASTCHR() != '\f' && LASTCHR() != CC_sub)
633
error(1, "file does not end with %s", pptokchr('\n'));
634
*(ip - 1) = c = '\n';
635
}
636
else
637
{
638
if (!(cur->flags & (IN_noguard|IN_tokens)) && cur->symbol)
639
ppmultiple(ppsetfile(error_info.file), cur->symbol);
640
if (cur->fd >= 0)
641
close(cur->fd);
642
if (pp.incref && !(pp.mode & INIT))
643
{
644
SYNCOUT();
645
(*pp.incref)(error_info.file, cur->file, error_info.line - 1, PP_SYNC_POP);
646
CACHEOUT();
647
}
648
goto fsm_pop;
649
}
650
}
651
else
652
c = EOF;
653
}
654
break;
655
case IN_MACRO:
656
case IN_MULTILINE:
657
#if !CPP
658
if (!(st & PASSEOF))
659
#endif
660
#if COMPATIBLE
661
if (prv && (!INMACRO(rp) || (st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && ppismac(*prv->nextchr)))
662
#else
663
if (prv && !INMACRO(rp))
664
#endif
665
{
666
if (cur->type == IN_MULTILINE)
667
{
668
while (pp.control-- != cur->control)
669
error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
670
free(cur->buffer);
671
error_info.file = cur->file;
672
error_info.line = cur->line;
673
if (pp.linesync)
674
{
675
SYNCOUT();
676
(*pp.linesync)(error_info.line, error_info.file);
677
CACHEOUT();
678
}
679
}
680
cur->symbol->flags &= ~SYM_DISABLED;
681
if (cur->symbol->flags & SYM_FUNCTION)
682
popframe(pp.macp);
683
POP();
684
#if CPP
685
if (!(st & COMPATIBILITY) && ppisidig(*(op - 1)) && ppisidig(*ip)) UNGETCHR(' ');
686
#endif
687
bp = ip;
688
goto fsm_get;
689
}
690
c = EOF;
691
break;
692
case IN_QUOTE:
693
if (prv)
694
{
695
error_info.line = cur->line;
696
st &= ~(ESCAPE|QUOTE);
697
POP();
698
c = '"';
699
}
700
else c = EOF;
701
break;
702
case IN_SQUOTE:
703
if (prv)
704
{
705
error_info.line = cur->line;
706
st &= ~(ESCAPE|SQUOTE);
707
POP();
708
c = '\'';
709
}
710
else c = EOF;
711
break;
712
case IN_STRING:
713
#if CPP
714
if (prv)
715
#else
716
if (!(st & PASSEOF) && !(cur->flags & IN_expand) && prv)
717
#endif
718
{
719
if (cur->flags & IN_disable) st |= DISABLE;
720
else st &= ~DISABLE;
721
POP();
722
bp = ip;
723
goto fsm_get;
724
}
725
c = EOF;
726
break;
727
default:
728
c = EOF;
729
break;
730
}
731
}
732
bp = ip - 1;
733
if (state = rp[c]) goto fsm_next;
734
goto fsm_get;
735
736
#if !CPP
737
case S_HUH:
738
if (INOPSPACE(rp))
739
{
740
if (c == '=')
741
{
742
#if PROTOTYPE
743
if (pp.in->flags & IN_prototype) PUTCHR(c);
744
else
745
{
746
#endif
747
while (*(op - 1) == ' ' || *(op - 1) == '\t') op--;
748
PUTCHR(c);
749
if (st & (STRICT|WARN)) error(1, "%-*.*s: space ignored in operator", op - tp, op - tp, tp);
750
#if PROTOTYPE
751
}
752
#endif
753
switch (*tp)
754
{
755
case '/':
756
c = T_DIVEQ;
757
break;
758
case '%':
759
c = T_MODEQ;
760
break;
761
case '&':
762
c = T_ANDEQ;
763
break;
764
case '*':
765
c = T_MPYEQ;
766
break;
767
case '+':
768
c = T_ADDEQ;
769
break;
770
case '-':
771
c = T_SUBEQ;
772
break;
773
case '^':
774
c = T_XOREQ;
775
break;
776
case '|':
777
c = T_OREQ;
778
break;
779
case '<':
780
c = T_LSHIFTEQ;
781
break;
782
case '>':
783
c = T_RSHIFTEQ;
784
break;
785
}
786
}
787
else
788
{
789
BACKIN();
790
switch (c = *tp)
791
{
792
case '<':
793
c = T_LSHIFT;
794
break;
795
case '>':
796
c = T_RSHIFT;
797
break;
798
}
799
}
800
}
801
else if (pp.level > 1 || (pp.option & PRESERVE)) PUTCHR(c);
802
else if (tp == op)
803
{
804
if (pp.in->type != IN_BUFFER)
805
{
806
if (!(pp.option & ALLPOSSIBLE))
807
error(1, "%s: invalid character ignored", pptokchr(c));
808
goto fsm_top;
809
}
810
PUTCHR(c);
811
}
812
else if (*tp == ':')
813
{
814
PUTCHR(c);
815
if (c == '=') error(2, "real programmers use =");
816
else c = '+';
817
}
818
else
819
{
820
BACKIN();
821
c = *tp;
822
}
823
break;
824
#endif
825
826
case S_QUAL:
827
if ((state = NEXT(state)) != LIT1)
828
{
829
rp = fsm[state];
830
bp = ip;
831
#if CPP
832
qual = 1;
833
#if COMPATIBLE
834
if (!(st & COMPATIBILITY) || c != 'u' && c != 'U')
835
#endif
836
PUTCHR(c);
837
#else
838
switch (c)
839
{
840
case 'f':
841
case 'F':
842
qual |= N_FLOAT;
843
#if COMPATIBLE
844
if (!(st & COMPATIBILITY))
845
#endif
846
PUTCHR(c);
847
break;
848
case 'l':
849
case 'L':
850
qual |= N_LONG;
851
PUTCHR(c);
852
break;
853
case 'u':
854
case 'U':
855
qual |= N_UNSIGNED;
856
#if COMPATIBLE
857
if (!(st & COMPATIBILITY))
858
#endif
859
PUTCHR(c);
860
break;
861
default:
862
PUTCHR(c);
863
break;
864
}
865
#endif
866
goto fsm_get;
867
}
868
#if !CPP
869
qual |= N_WIDE;
870
if (DOSTRIP()) BACKOUT();
871
#endif
872
/*FALLTHROUGH*/
873
874
case S_LITBEG:
875
#if CPP
876
quot = c;
877
rp = fsm[LIT1];
878
if (op == tp)
879
{
880
PPSYNCLINE();
881
tp = op;
882
}
883
#else
884
if ((quot = c) == '<')
885
{
886
if (!(st & HEADER) || (pp.option & (HEADEREXPAND|HEADEREXPANDALL)) && pp.in->type != IN_FILE && pp.in->type != IN_BUFFER && pp.in->type != IN_INIT && pp.in->type != IN_RESCAN)
887
{
888
PUTCHR(c);
889
bp = ip;
890
rp = fsm[LT1];
891
goto fsm_get;
892
}
893
quot = '>';
894
rp = fsm[HDR1];
895
}
896
else rp = fsm[LIT1];
897
if (!DOSTRIP())
898
#endif
899
PUTCHR(c);
900
bp = ip;
901
goto fsm_get;
902
903
case S_LITEND:
904
n = 1;
905
if (c != quot)
906
{
907
if (c != '\n' && c != EOF)
908
{
909
if (st & (QUOTE|SQUOTE))
910
{
911
if (!(st & ESCAPE))
912
{
913
st |= ESCAPE;
914
quotquot = c;
915
}
916
else if (c == quotquot) st &= ~ESCAPE;
917
}
918
PUTCHR(c);
919
bp = ip;
920
goto fsm_get;
921
}
922
#if CPP
923
if ((st & PASSTHROUGH) || (pp.option & PRESERVE))
924
{
925
if (c == '\n') goto fsm_newline;
926
bp = ip;
927
goto fsm_start;
928
}
929
#endif
930
m = (st & SKIPCONTROL) && (pp.mode & HOSTED) ? -1 : 1;
931
if (c == '\n' && quot == '\'' && (pp.option & STRINGSPAN)) n = 0;
932
else
933
#if COMPATIBLE && !CPP
934
if ((st & (COMPATIBILITY|DEFINITION)) != (COMPATIBILITY|DEFINITION))
935
#endif
936
{
937
switch (quot)
938
{
939
case '"':
940
if (c == '\n')
941
{
942
if (!(pp.option & STRINGSPAN) || (st & (COMPATIBILITY|STRICT)) == STRICT)
943
error(m, "%s in string", pptokchr(c));
944
error_info.line++;
945
if (!(pp.option & STRINGSPAN))
946
{
947
PUTCHR('\\');
948
c = 'n';
949
}
950
else if (pp.option & STRINGSPLIT)
951
{
952
PUTCHR('\\');
953
PUTCHR('n');
954
PUTCHR('"');
955
PUTCHR('\n');
956
c = '"';
957
}
958
PUTCHR(c);
959
bp = ip;
960
goto fsm_get;
961
}
962
error(m, "%s in string", pptokchr(c));
963
c = '\n';
964
break;
965
case '\'':
966
if (!(st & DIRECTIVE) || !(pp.mode & (HOSTED|RELAX)))
967
error(m, "%s in character constant", pptokchr(c));
968
break;
969
case '>':
970
error(m, "%s in header constant", pptokchr(c));
971
break;
972
default:
973
error(m, "%s in %c quote", pptokchr(c), quot);
974
break;
975
}
976
#if !CPP
977
if (!DOSTRIP())
978
#endif
979
PUTCHR(quot);
980
}
981
if (c == '\n')
982
{
983
UNGETCHR(c);
984
c = quot;
985
}
986
}
987
else if (st & (SQUOTE|QUOTE))
988
{
989
if (!(st & ESCAPE))
990
{
991
st |= ESCAPE;
992
quotquot = c;
993
}
994
else if (c == quotquot) st &= ~ESCAPE;
995
PUTCHR('\\');
996
PUTCHR(c);
997
bp = ip;
998
goto fsm_get;
999
}
1000
#if CPP
1001
else PUTCHR(c);
1002
#else
1003
else if (!DOSTRIP()) PUTCHR(c);
1004
#endif
1005
#if CATSTRINGS
1006
#if CPP
1007
if (c == '"' && !(st & (COLLECTING|NOTEXT|PASSTHROUGH|SKIPCONTROL)) && (pp.mode & CATLITERAL))
1008
#else
1009
if (c == '"' && pp.level == 1 && !(st & (COLLECTING|JOINING|NOTEXT|SKIPCONTROL)) && (pp.mode & CATLITERAL))
1010
#endif
1011
{
1012
char* pptoken;
1013
long ppstate;
1014
1015
pptoken = pp.token;
1016
pp.token = pp.catbuf;
1017
*pp.token++ = 0;
1018
ppstate = (st & STRIP);
1019
if (DOSTRIP())
1020
ppstate |= ADD|QUOTE;
1021
st |= JOINING;
1022
st &= ~(NEWLINE|STRIP);
1023
1024
/*
1025
* revert to the top level since string
1026
* concatenation crosses file boundaries
1027
* (allowing intervening directives)
1028
*/
1029
1030
pp.level = 0;
1031
SYNCIN();
1032
m = n = 0;
1033
for (;;)
1034
{
1035
switch (c = pplex())
1036
{
1037
case '\n':
1038
m++;
1039
continue;
1040
case ' ':
1041
*pp.catbuf = ' ';
1042
continue;
1043
case T_WSTRING:
1044
#if !CPP
1045
qual = N_WIDE;
1046
#endif
1047
if (ppstate & ADD)
1048
ppstate &= ~ADD;
1049
else if (m == n || !(st & SPACEOUT))
1050
op--;
1051
else
1052
{
1053
n = m;
1054
*(op - 1) = '\\';
1055
*op++ = '\n';
1056
}
1057
STRCOPY(op, pp.token + 2 + (*pp.token == ' '), s);
1058
continue;
1059
case T_STRING:
1060
if (ppstate & ADD)
1061
ppstate &= ~ADD;
1062
else if (m == n || !(st & SPACEOUT))
1063
op--;
1064
else
1065
{
1066
n = m;
1067
*(op - 1) = '\\';
1068
*op++ = '\n';
1069
}
1070
STRCOPY(op, pp.token + 1 + (*pp.token == ' '), s);
1071
continue;
1072
case 0:
1073
m = error_info.line ? (error_info.line - 1) : 0;
1074
*pp.token = 0;
1075
/*FALLTHROUGH*/
1076
default:
1077
if (m)
1078
{
1079
if (--m)
1080
{
1081
pp.state |= HIDDEN|SYNCLINE;
1082
pp.hidden += m;
1083
}
1084
#if COMPATIBLE
1085
if ((st & COMPATIBILITY) && c == '#' && *(pp.token - 1))
1086
{
1087
*(pp.token + 3) = *(pp.token + 2);
1088
*(pp.token + 2) = *(pp.token + 1);
1089
*(pp.token + 1) = *pp.token;
1090
*pp.token = *(pp.token - 1);
1091
}
1092
error_info.line--;
1093
*--pp.token = '\n';
1094
#endif
1095
}
1096
else if (*(pp.token - 1))
1097
pp.token--;
1098
if (ppisidig(*pp.token))
1099
*op++ = ' ';
1100
if (pp.in->type == IN_MACRO && (s = strchr(pp.token, MARK)) && !*(s + 1))
1101
{
1102
*(s + 1) = MARK;
1103
*(s + 2) = 0;
1104
}
1105
PUSH_STRING(pp.token);
1106
pp.state &= ~(JOINING|NEWLINE);
1107
pp.state |= ppstate & ~(ADD|QUOTE);
1108
if ((ppstate & (ADD|QUOTE)) == QUOTE)
1109
op--;
1110
break;
1111
}
1112
break;
1113
}
1114
pp.token = pptoken;
1115
CACHEIN();
1116
pp.level = 1;
1117
#if !CPP
1118
c = T_STRING | qual;
1119
break;
1120
#endif
1121
}
1122
#endif
1123
#if CPP
1124
if (n && !(st & (PASSTHROUGH|SKIPCONTROL|NOTEXT)) && c == '\'' && (op - tp) <= 2 && !(pp.mode & (HOSTED|RELAX)))
1125
error(1, "empty character constant");
1126
if (pp.option & PRESERVE)
1127
st &= ~ESCAPE;
1128
else
1129
st &= ~(ESCAPE|NEWLINE);
1130
pp.in->flags |= IN_tokens;
1131
count(token);
1132
goto fsm_start;
1133
#else
1134
st &= ~ESCAPE;
1135
switch (quot)
1136
{
1137
case '\'':
1138
if (n && !(st & NOTEXT) && (op - tp) <= (DOSTRIP() ? 0 : 2) && !(pp.mode & (HOSTED|RELAX)))
1139
error(1, "empty character constant");
1140
c = T_CHARCONST | qual;
1141
break;
1142
case '>':
1143
c = T_HEADER;
1144
break;
1145
default:
1146
if (c == quot)
1147
c = T_STRING | qual;
1148
break;
1149
}
1150
break;
1151
#endif
1152
1153
case S_LITESC:
1154
if (st & (COLLECTING|DIRECTIVE|QUOTE|SQUOTE))
1155
{
1156
if (st & ESCAPE)
1157
{
1158
PUTCHR('\\');
1159
if (c == quot) PUTCHR('\\');
1160
}
1161
PUTCHR(c);
1162
}
1163
#if CPP
1164
else if (st & PASSTHROUGH) PUTCHR(c);
1165
#endif
1166
else if (pp.option & PRESERVE) PUTCHR(c);
1167
else switch (c)
1168
{
1169
case 'b':
1170
case 'f':
1171
case 'n':
1172
case 'r':
1173
case 't':
1174
case '\\':
1175
case '\'':
1176
case '"':
1177
case '?':
1178
PUTCHR(c);
1179
break;
1180
#if COMPATIBLE
1181
case '8':
1182
case '9':
1183
if (!(st & COMPATIBILITY)) goto unknown;
1184
if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
1185
/*FALLTHROUGH*/
1186
#endif
1187
case '0':
1188
case '1':
1189
case '2':
1190
case '3':
1191
case '4':
1192
case '5':
1193
case '6':
1194
case '7':
1195
n = c - '0';
1196
for (m = 0; m < 2; m++)
1197
{
1198
GET(c, c, tp, xp);
1199
switch (c)
1200
{
1201
#if COMPATIBLE
1202
case '8':
1203
case '9':
1204
if (!(st & COMPATIBILITY))
1205
{
1206
UNGETCHR(c);
1207
break;
1208
}
1209
if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
1210
/*FALLTHROUGH*/
1211
#endif
1212
case '0':
1213
case '1':
1214
case '2':
1215
case '3':
1216
case '4':
1217
case '5':
1218
case '6':
1219
case '7':
1220
n = (n << 3) + c - '0';
1221
continue;
1222
default:
1223
UNGETCHR(c);
1224
break;
1225
}
1226
break;
1227
}
1228
if (n & ~0777) error(1, "octal character constant too large");
1229
goto octal;
1230
case 'a':
1231
if (pp.option & MODERN)
1232
{
1233
PUTCHR(c);
1234
break;
1235
}
1236
#if COMPATIBLE
1237
if (st & COMPATIBILITY) goto unknown;
1238
#endif
1239
n = CC_bel;
1240
goto octal;
1241
case 'v':
1242
if (pp.option & MODERN)
1243
{
1244
PUTCHR(c);
1245
break;
1246
}
1247
n = CC_vt;
1248
goto octal;
1249
case 'E':
1250
if (st & (COMPATIBILITY|STRICT)) goto unknown;
1251
n = CC_esc;
1252
goto octal;
1253
case 'x':
1254
#if COMPATIBLE
1255
if (st & COMPATIBILITY) goto unknown;
1256
#endif
1257
n = 0;
1258
for (m = 0; m < 3; m++)
1259
{
1260
GET(c, c, tp, xp);
1261
switch (c)
1262
{
1263
case '0':
1264
case '1':
1265
case '2':
1266
case '3':
1267
case '4':
1268
case '5':
1269
case '6':
1270
case '7':
1271
case '8':
1272
case '9':
1273
n = (n << 4) + c - '0';
1274
continue;
1275
case 'a':
1276
case 'b':
1277
case 'c':
1278
case 'd':
1279
case 'e':
1280
case 'f':
1281
n = (n << 4) + c - 'a' + 10;
1282
continue;
1283
case 'A':
1284
case 'B':
1285
case 'C':
1286
case 'D':
1287
case 'E':
1288
case 'F':
1289
n = (n << 4) + c - 'A' + 10;
1290
continue;
1291
default:
1292
if (!m) error(1, "\\x%c: invalid character in hexadecimal character constant", c);
1293
UNGETCHR(c);
1294
break;
1295
}
1296
break;
1297
}
1298
if (n & ~0777) error(1, "hexadecimal character constant too large");
1299
octal:
1300
PUTCHR(((n >> 6) & 07) + '0');
1301
PUTCHR(((n >> 3) & 07) + '0');
1302
PUTCHR((n & 07) + '0');
1303
break;
1304
default:
1305
unknown:
1306
if (st & (STRICT|WARN)) error(1, "\\%c: non-standard character constant", c);
1307
PUTCHR(c);
1308
break;
1309
}
1310
state = LIT1;
1311
goto fsm_begin;
1312
1313
case S_MACRO:
1314
BACKIN();
1315
#if CPP
1316
if (st & (DISABLE|SKIPCONTROL|SKIPMACRO))
1317
{
1318
if (st & SKIPMACRO)
1319
pp.mode |= MARKMACRO;
1320
st &= ~(NEWLINE|SKIPMACRO);
1321
pp.in->flags |= IN_tokens;
1322
count(token);
1323
goto fsm_start;
1324
}
1325
count(candidate);
1326
SETCHR(0);
1327
switch (state = INDEX(rp))
1328
{
1329
case HIT0:
1330
tp = op - 1;
1331
break;
1332
case HITN:
1333
bp = tp;
1334
tp = op - ((pp.truncate && pp.truncate < (HITN - HIT0)) ? (pp.truncate - 1) : (HITN - HIT0));
1335
while (tp > bp && ppisidig(*(tp - 1))) tp--;
1336
break;
1337
default:
1338
bp = tp;
1339
if ((tp = op - (state - HIT0)) > bp && *(tp - 1) == 'L') tp--;
1340
break;
1341
}
1342
if (sym = ppsymref(pp.symtab, tp))
1343
{
1344
SYNCIN();
1345
n = ppcall(sym, 0);
1346
CACHEIN();
1347
if (n >= 0)
1348
{
1349
BACKOUT();
1350
if (!n)
1351
{
1352
if (sp) op = sp;
1353
else
1354
{
1355
s = ip;
1356
ip = sym->macro->value;
1357
c = sym->macro->size;
1358
while (c > 0)
1359
{
1360
if (op + c < xp + PPBUFSIZ) n = c;
1361
else n = xp + PPBUFSIZ - op;
1362
MEMCPY(op, ip, n);
1363
c -= n;
1364
PPCHECKOUT();
1365
}
1366
ip = s;
1367
}
1368
}
1369
else if ((sym->flags & SYM_MULTILINE) && pp.linesync)
1370
{
1371
SYNCOUT();
1372
if (!(state & NEWLINE))
1373
ppputchar('\n');
1374
(*pp.linesync)(error_info.line, error_info.file);
1375
CACHEOUT();
1376
}
1377
}
1378
}
1379
pp.in->flags |= IN_tokens;
1380
goto fsm_start;
1381
#else
1382
if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL|SKIPMACRO))
1383
{
1384
if (st & SKIPMACRO)
1385
pp.mode |= MARKMACRO;
1386
st &= ~(NEWLINE|NOEXPAND|SKIPMACRO);
1387
c = T_ID;
1388
if (pp.level == 1)
1389
{
1390
pp.in->flags |= IN_tokens;
1391
if (st & NOTEXT)
1392
{
1393
BACKOUT();
1394
goto fsm_top;
1395
}
1396
if (st & COMPILE)
1397
{
1398
SETCHR(0);
1399
if (pp.truncate && (op - tp) > pp.truncate) tp[pp.truncate] = 0;
1400
sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp);
1401
fsm_noise:
1402
if (pp.symbol = sym)
1403
{
1404
if ((sym->flags & SYM_KEYWORD) && (!pp.truncate || (op - tp) <= pp.truncate || (tp[pp.truncate] = '_', tp[pp.truncate + 1] = 0, pp.symbol = sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp), 0)))
1405
{
1406
c = ((struct ppsymkey*)sym)->lex;
1407
/*UNDENT*/
1408
1409
#define ADVANCE() do{if(pp.toknxt<op)pp.token=pp.toknxt;}while(0)
1410
1411
#define NOISE_BRACE 01
1412
#define NOISE_NOSPACEOUT 02
1413
#define NOISE_PAREN 04
1414
1415
if ((pp.option & NOISE) && ppisnoise(c))
1416
{
1417
if (c != T_NOISE)
1418
{
1419
int p;
1420
int f;
1421
char* pptoken;
1422
PPCOMMENT ppcomment;
1423
1424
SYNCIN();
1425
pp.toknxt = op;
1426
f = 0;
1427
if (!(pp.state & SPACEOUT))
1428
{
1429
pp.state |= SPACEOUT;
1430
f |= NOISE_NOSPACEOUT;
1431
}
1432
ppcomment = pp.comment;
1433
pp.comment = 0;
1434
op = (pptoken = tp) + MAXTOKEN;
1435
switch (c)
1436
{
1437
case T_X_GROUP:
1438
m = p = 0;
1439
quot = 1;
1440
for (;;)
1441
{
1442
ADVANCE();
1443
switch (c = pplex())
1444
{
1445
case '(':
1446
case '{':
1447
if (!p)
1448
{
1449
if (c == '(')
1450
{
1451
if (f & NOISE_PAREN)
1452
{
1453
ungetchr(c);
1454
*--pp.toknxt = 0;
1455
break;
1456
}
1457
f |= NOISE_PAREN;
1458
p = ')';
1459
}
1460
else
1461
{
1462
f |= NOISE_BRACE|NOISE_PAREN;
1463
p = '}';
1464
}
1465
n = 1;
1466
m = c;
1467
}
1468
else if (c == m) n++;
1469
quot = 0;
1470
continue;
1471
case ')':
1472
case '}':
1473
if (c == p && --n <= 0)
1474
{
1475
if (c == '}') break;
1476
m = '\n';
1477
p = 0;
1478
}
1479
quot = 0;
1480
continue;
1481
case ' ':
1482
continue;
1483
case '\n':
1484
error_info.line++;
1485
if (!m) m = '\n';
1486
continue;
1487
case 0:
1488
break;
1489
case T_ID:
1490
if (quot) continue;
1491
/*FALLTHROUGH*/
1492
default:
1493
if (m == '\n')
1494
{
1495
/*
1496
* NOTE: token expanded again
1497
*/
1498
1499
s = pp.toknxt;
1500
while (s > pp.token) ungetchr(*--s);
1501
*(pp.toknxt = s) = 0;
1502
break;
1503
}
1504
continue;
1505
}
1506
break;
1507
}
1508
break;
1509
case T_X_LINE:
1510
for (;;)
1511
{
1512
ADVANCE();
1513
switch (pplex())
1514
{
1515
case 0:
1516
break;
1517
case '\n':
1518
error_info.line++;
1519
break;
1520
default:
1521
continue;
1522
}
1523
break;
1524
}
1525
break;
1526
case T_X_STATEMENT:
1527
for (;;)
1528
{
1529
ADVANCE();
1530
switch (pplex())
1531
{
1532
case 0:
1533
break;
1534
case ';':
1535
ungetchr(';');
1536
*(pp.toknxt = pp.token) = 0;
1537
break;
1538
default:
1539
continue;
1540
}
1541
break;
1542
}
1543
break;
1544
}
1545
pp.comment = ppcomment;
1546
if (f & NOISE_NOSPACEOUT)
1547
pp.state &= ~SPACEOUT;
1548
CACHEIN();
1549
tp = pptoken;
1550
op = pp.toknxt;
1551
c = T_NOISES;
1552
}
1553
if (pp.option & NOISEFILTER)
1554
{
1555
BACKOUT();
1556
goto fsm_top;
1557
}
1558
}
1559
1560
/*INDENT*/
1561
}
1562
else if ((pp.option & NOISE) && c == T_ID && strneq(tp, "__builtin_", 10))
1563
{
1564
hashlook(pp.symtab, tp, HASH_DELETE, NiL);
1565
pp.symbol = sym = (struct ppsymbol*)ppkeyset(pp.symtab, tp);
1566
sym->flags |= SYM_KEYWORD;
1567
c = ((struct ppsymkey*)sym)->lex = T_BUILTIN;
1568
}
1569
}
1570
}
1571
goto fsm_symbol;
1572
}
1573
goto fsm_check;
1574
}
1575
if (pp.level == 1)
1576
{
1577
st &= ~(NEWLINE|PASSEOF);
1578
pp.in->flags |= IN_tokens;
1579
}
1580
else st &= ~PASSEOF;
1581
count(candidate);
1582
SETCHR(0);
1583
if (sym = ppsymref(pp.symtab, tp))
1584
{
1585
SYNCIN();
1586
c = ppcall(sym, 1);
1587
CACHEIN();
1588
if (c >= 0)
1589
{
1590
BACKOUT();
1591
if ((sym->flags & SYM_MULTILINE) && pp.linesync)
1592
{
1593
SYNCOUT();
1594
(*pp.linesync)(error_info.line, error_info.file);
1595
CACHEOUT();
1596
}
1597
goto fsm_top;
1598
}
1599
}
1600
c = T_ID;
1601
if (pp.level == 1)
1602
{
1603
if (st & NOTEXT)
1604
{
1605
BACKOUT();
1606
goto fsm_top;
1607
}
1608
if (st & COMPILE)
1609
{
1610
if (pp.truncate && (op - tp) > pp.truncate)
1611
{
1612
tp[pp.truncate] = 0;
1613
sym = 0;
1614
}
1615
if (!sym)
1616
{
1617
if (!(pp.option & NOHASH)) sym = ppsymset(pp.symtab, tp);
1618
else if (!(sym = ppsymref(pp.symtab, tp))) goto fsm_symbol;
1619
}
1620
goto fsm_noise;
1621
}
1622
goto fsm_symbol;
1623
}
1624
goto fsm_check;
1625
#endif
1626
1627
case S_SHARP:
1628
if (c == '(')
1629
{
1630
pp.in->flags |= IN_tokens;
1631
if ((st & STRICT) && pp.in->type != IN_MACRO && pp.in->type != IN_MULTILINE)
1632
{
1633
if (!(pp.mode & HOSTED)) error(1, "non-standard reference to #(...)");
1634
if (st & STRICT)
1635
{
1636
PUTCHR(c);
1637
#if CPP
1638
st &= ~NEWLINE;
1639
count(token);
1640
goto fsm_start;
1641
#else
1642
break;
1643
#endif
1644
}
1645
}
1646
if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL))
1647
{
1648
PUTCHR(c);
1649
#if CPP
1650
st &= ~NEWLINE;
1651
count(token);
1652
goto fsm_start;
1653
#else
1654
st &= ~NOEXPAND;
1655
break;
1656
#endif
1657
}
1658
op--;
1659
SYNC();
1660
ppbuiltin();
1661
CACHE();
1662
#if CPP
1663
count(token);
1664
goto fsm_start;
1665
#else
1666
goto fsm_top;
1667
#endif
1668
}
1669
BACKIN();
1670
#if CPP
1671
if (!(st & NEWLINE) || !(pp.in->type & IN_TOP))
1672
{
1673
fsm_nondirective:
1674
st &= ~NEWLINE;
1675
pp.in->flags |= IN_tokens;
1676
count(token);
1677
goto fsm_start;
1678
}
1679
if (*(s = tp) != '#')
1680
{
1681
#if COMPATIBLE
1682
if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) goto fsm_nondirective;
1683
#endif
1684
while (*s == ' ' || *s == '\t') s++;
1685
if (*s != '#') goto fsm_nondirective;
1686
}
1687
BACKOUT();
1688
#else
1689
if (!(st & NEWLINE) || (st & DEFINITION) || !(pp.in->type & IN_TOP))
1690
{
1691
if (c == '#')
1692
{
1693
SKIPIN();
1694
if (!(st & DEFINITION))
1695
PUTCHR(c);
1696
c = T_TOKCAT;
1697
}
1698
else if (pp.level == 1 && !(st & (JOINING|SPACEOUT)) && !(pp.option & PRESERVE))
1699
{
1700
char* pptoken;
1701
char* oop;
1702
PPCOMMENT ppcomment;
1703
1704
SYNCIN();
1705
pp.toknxt = oop = op;
1706
pp.state |= SPACEOUT;
1707
ppcomment = pp.comment;
1708
pp.comment = 0;
1709
op = (pptoken = tp) + MAXTOKEN;
1710
for (;;)
1711
{
1712
ADVANCE();
1713
switch (pplex())
1714
{
1715
case 0:
1716
break;
1717
case '\n':
1718
error_info.line++;
1719
break;
1720
default:
1721
continue;
1722
}
1723
break;
1724
}
1725
pp.comment = ppcomment;
1726
pp.state &= ~SPACEOUT;
1727
CACHEIN();
1728
tp = pptoken;
1729
*--op = 0;
1730
op = oop;
1731
if (pp.pragma && !(st & NOTEXT))
1732
{
1733
*s = 0;
1734
SYNC();
1735
(*pp.pragma)(NiL, NiL, NiL, tp, 1);
1736
CACHE();
1737
}
1738
if (!c) BACKIN();
1739
goto fsm_top;
1740
}
1741
else c = '#';
1742
break;
1743
}
1744
if ((st & (COLLECTING|STRICT)) == (COLLECTING|STRICT))
1745
error(1, "directives in macro call arguments are not portable");
1746
#endif
1747
if (c == '#' && pp.in->type == IN_RESCAN)
1748
{
1749
/*
1750
* pass line to pp.pragma VERBATIM
1751
*/
1752
1753
SKIPIN();
1754
s = pp.valbuf;
1755
while ((c = GETCHR()) && c != '\n')
1756
if ((*s++ = c) == MARK) SKIPIN();
1757
if (pp.pragma && !(st & NOTEXT))
1758
{
1759
*s = 0;
1760
SYNC();
1761
(*pp.pragma)(NiL, NiL, NiL, pp.valbuf, 1);
1762
CACHE();
1763
}
1764
if (!c) BACKIN();
1765
#if CPP
1766
goto fsm_start;
1767
#else
1768
goto fsm_top;
1769
#endif
1770
}
1771
SYNC();
1772
ppcontrol();
1773
CACHE();
1774
#if CPP
1775
if (st & (NOTEXT|SKIPCONTROL))
1776
{
1777
if (!sp)
1778
{
1779
PPCHECKOUTTP();
1780
sp = tp;
1781
}
1782
}
1783
else if (sp)
1784
{
1785
tp = op = sp;
1786
sp = 0;
1787
}
1788
goto fsm_start;
1789
#else
1790
goto fsm_top;
1791
#endif
1792
1793
case S_NL:
1794
#if CPP
1795
if (op == tp && !(st & JOINING) && pp.in->type == IN_FILE && !(pp.option & PRESERVE))
1796
{
1797
st |= NEWLINE|HIDDEN;
1798
pp.hidden++;
1799
error_info.line++;
1800
goto fsm_start;
1801
}
1802
#endif
1803
fsm_newline:
1804
#if CPP
1805
if (sp)
1806
op = sp;
1807
else if (!(pp.in->flags & IN_noguard))
1808
{
1809
while (tp < op)
1810
if ((c = *tp++) != ' ' && c != '\t')
1811
{
1812
pp.in->flags |= IN_tokens;
1813
break;
1814
}
1815
c = '\n';
1816
}
1817
st |= NEWLINE;
1818
error_info.line++;
1819
if (*ip == '\n' && *(ip + 1) != '\n' && !pp.macref && !(st & (ADD|HIDDEN)))
1820
{
1821
ip++;
1822
PUTCHR('\n');
1823
error_info.line++;
1824
}
1825
if ((st & NOTEXT) && ((pp.mode & FILEDEPS) || (pp.option & (DEFINITIONS|PREDEFINITIONS))))
1826
BACKOUT();
1827
else
1828
{
1829
debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
1830
PUTCHR('\n');
1831
PPSYNCLINE();
1832
if (sp)
1833
{
1834
PPCHECKOUT();
1835
sp = op;
1836
}
1837
}
1838
goto fsm_start;
1839
#else
1840
st |= NEWLINE;
1841
if (pp.level == 1)
1842
{
1843
error_info.line++;
1844
if (!(st & (JOINING|SPACEOUT)))
1845
{
1846
debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
1847
BACKOUT();
1848
goto fsm_top;
1849
}
1850
}
1851
BACKOUT();
1852
if (st & SKIPCONTROL)
1853
{
1854
error_info.line++;
1855
st |= HIDDEN;
1856
pp.hidden++;
1857
goto fsm_start;
1858
}
1859
PUTCHR(c = '\n');
1860
goto fsm_return;
1861
#endif
1862
1863
#if !CPP
1864
case S_TOK:
1865
PUTCHR(c);
1866
c = TYPE(state) | qual;
1867
break;
1868
1869
case S_TOKB:
1870
BACKIN();
1871
c = TYPE(state) | qual;
1872
break;
1873
#endif
1874
1875
case S_VS:
1876
PUTCHR(c);
1877
#if !CPP
1878
if (st & NOVERTICAL)
1879
{
1880
error(1, "%s invalid in directives", pptokchr(c));
1881
st &= ~NOVERTICAL;
1882
}
1883
#endif
1884
#if COMPATIBLE
1885
if (st & COMPATIBILITY) st |= NEWLINE;
1886
#endif
1887
#if CPP
1888
if (!(pp.in->flags & IN_noguard))
1889
while (tp < op)
1890
if ((c = *tp++) != ' ' && c != '\t')
1891
{
1892
pp.in->flags |= IN_tokens;
1893
break;
1894
}
1895
goto fsm_start;
1896
#else
1897
bp = ip;
1898
rp = fsm[WS1];
1899
goto fsm_get;
1900
#endif
1901
1902
#if !CPP
1903
case S_WS:
1904
#if COMPATIBLE
1905
if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
1906
#endif
1907
if (pp.level == 1)
1908
{
1909
if ((st & (COMPATIBILITY|SPACEOUT)) && !(st & TRANSITION))
1910
{
1911
if (st & (COMPILE|NOTEXT))
1912
{
1913
#if CATSTRINGS
1914
if ((st & (JOINING|NOTEXT|SPACEOUT)) != SPACEOUT)
1915
#else
1916
if ((st & (NOTEXT|SPACEOUT)) != SPACEOUT)
1917
#endif
1918
{
1919
BACKOUT();
1920
bp = ip - 1;
1921
rp = fsm[START];
1922
if (state = rp[c]) goto fsm_next;
1923
goto fsm_get;
1924
}
1925
}
1926
else
1927
#if CATSTRINGS
1928
if (!(st & JOINING))
1929
#endif
1930
{
1931
tp = op;
1932
bp = ip - 1;
1933
rp = fsm[START];
1934
if (state = rp[c]) goto fsm_next;
1935
goto fsm_get;
1936
}
1937
BACKIN();
1938
c = ' ';
1939
goto fsm_return;
1940
}
1941
BACKOUT();
1942
bp = ip - 1;
1943
rp = fsm[START];
1944
if (state = rp[c]) goto fsm_next;
1945
goto fsm_get;
1946
}
1947
if (st & (NOSPACE|SKIPCONTROL))
1948
{
1949
BACKOUT();
1950
bp = ip - 1;
1951
rp = fsm[START];
1952
if (state = rp[c]) goto fsm_next;
1953
goto fsm_get;
1954
}
1955
if (c != '\n')
1956
{
1957
BACKIN();
1958
c = ' ';
1959
}
1960
if (!(pp.option & PRESERVE))
1961
{
1962
BACKOUT();
1963
PUTCHR(c);
1964
}
1965
goto fsm_return;
1966
#endif
1967
1968
default:
1969
if (state & SPLICE)
1970
{
1971
switch (c)
1972
{
1973
case MARK:
1974
/*
1975
* internal mark
1976
*/
1977
1978
switch (pp.in->type)
1979
{
1980
case IN_BUFFER:
1981
case IN_FILE:
1982
#if !CPP
1983
case IN_INIT:
1984
#if CATSTRINGS
1985
if ((st & JOINING) && (!INQUOTE(rp) || quot != '"') || pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
1986
#else
1987
if (pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
1988
#endif
1989
PUTCHR(c);
1990
#endif
1991
break;
1992
default:
1993
switch (GETCHR())
1994
{
1995
case 'A':
1996
if (!(st & (DEFINITION|DISABLE)))
1997
{
1998
c = GETCHR();
1999
SYNCIN();
2000
if (pp.macp->arg[c - ARGOFFSET][-1])
2001
PUSH_EXPAND(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
2002
else
2003
PUSH_COPY(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
2004
CACHEIN();
2005
bp = ip;
2006
goto fsm_get;
2007
}
2008
/*FALLTHROUGH*/
2009
case 'C':
2010
c = GETCHR() - ARGOFFSET;
2011
if (!*(s = pp.macp->arg[c]) && (pp.in->symbol->flags & SYM_VARIADIC) && pp.in->symbol->macro->arity == (c + 1))
2012
{
2013
s = ip - 3;
2014
while (--op > tp && --s > bp && ppisidig(*s));
2015
}
2016
else
2017
{
2018
SYNCIN();
2019
PUSH_COPY(s, pp.macp->line);
2020
CACHEIN();
2021
}
2022
bp = ip;
2023
goto fsm_get;
2024
case 'F':
2025
error_info.file = (char*)strtoul(ip, &s, 16);
2026
debug((-6, "actual sync: file = \"%s\"", error_info.file));
2027
bp = ip = s + 1;
2028
goto fsm_get;
2029
case 'L':
2030
error_info.line = strtoul(ip, &s, 16);
2031
debug((-6, "actual sync: line = %d", error_info.line));
2032
bp = ip = s + 1;
2033
goto fsm_get;
2034
case 'Q':
2035
c = GETCHR();
2036
SYNCIN();
2037
PUSH_QUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
2038
CACHEIN();
2039
*(bp = ip - 1) = '"';
2040
if (st & (COLLECTING|EOF2NL|JOINING)) rp = fsm[START];
2041
if (state = rp[c = '"']) goto fsm_next;
2042
goto fsm_get;
2043
case 'S':
2044
c = GETCHR();
2045
SYNCIN();
2046
PUSH_SQUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
2047
CACHEIN();
2048
bp = ip - 1;
2049
if (st & COLLECTING) rp = fsm[START];
2050
if (state = rp[c = '\'']) goto fsm_next;
2051
goto fsm_get;
2052
case 'X':
2053
if (pp.in->type != IN_COPY)
2054
st |= SKIPMACRO;
2055
if (pp.level <= 1)
2056
{
2057
bp = ip;
2058
goto fsm_get;
2059
}
2060
if (pp.in->type == IN_EXPAND)
2061
{
2062
st &= ~SKIPMACRO;
2063
PUTCHR(c);
2064
PUTCHR('X');
2065
}
2066
c = GETCHR();
2067
break;
2068
case 0:
2069
if ((state &= ~SPLICE) >= TERMINAL) goto fsm_terminal;
2070
goto fsm_begin;
2071
default:
2072
#if DEBUG
2073
error(PANIC, "invalid mark op `%c'", LASTCHR());
2074
/*FALLTHROUGH*/
2075
case MARK:
2076
#endif
2077
#if CATSTRINGS
2078
if ((st & (JOINING|QUOTE)) == JOINING)
2079
{
2080
if (!INQUOTE(rp))
2081
PUTCHR(c);
2082
}
2083
else
2084
#endif
2085
#if CPP
2086
if (rp != fsm[START] && !INQUOTE(rp))
2087
UNGETCHR(c);
2088
#else
2089
if (rp != fsm[START] && !INQUOTE(rp))
2090
UNGETCHR(c);
2091
else if (pp.level > 1)
2092
PUTCHR(c);
2093
#endif
2094
break;
2095
}
2096
break;
2097
}
2098
break;
2099
case '?':
2100
/*
2101
* trigraph
2102
*/
2103
2104
if (pp.in->type == IN_FILE)
2105
{
2106
GET(c, n, tp, xp);
2107
if (n == '?')
2108
{
2109
GET(c, n, tp, xp);
2110
if (c = trigraph[n])
2111
{
2112
if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
2113
error(1, "trigraph conversion %c%c%c -> %c%s", '?', '?', n, c, (st & TRANSITION) ? "" : " inhibited");
2114
#if COMPATIBLE
2115
if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
2116
{
2117
#endif
2118
*(bp = ip - 1) = c;
2119
if (state = rp[c]) goto fsm_next;
2120
goto fsm_get;
2121
#if COMPATIBLE
2122
}
2123
#endif
2124
}
2125
if (n != EOB) BACKIN();
2126
UNGETCHR(c = '?');
2127
}
2128
else if (n != EOB) BACKIN();
2129
}
2130
break;
2131
case '%':
2132
case '<':
2133
case ':':
2134
/*
2135
* digraph = --trigraph
2136
*/
2137
2138
if (pp.in->type == IN_FILE && (pp.option & PLUSPLUS))
2139
{
2140
m = 0;
2141
GET(c, n, tp, xp);
2142
switch (n)
2143
{
2144
case '%':
2145
if (c == '<') m = '{';
2146
break;
2147
case '>':
2148
if (c == '%') m = '}';
2149
else if (c == ':') m = ']';
2150
break;
2151
case ':':
2152
if (c == '%') m = '#';
2153
else if (c == '<') m = '[';
2154
break;
2155
}
2156
if (m)
2157
{
2158
if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
2159
error(1, "digraph conversion %c%c -> %c%s", c, n, m, (st & TRANSITION) ? "" : " inhibited");
2160
#if COMPATIBLE
2161
if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
2162
{
2163
#endif
2164
*(bp = ip - 1) = c = m;
2165
if (state = rp[c]) goto fsm_next;
2166
goto fsm_get;
2167
#if COMPATIBLE
2168
}
2169
#endif
2170
}
2171
if (n != EOB) BACKIN();
2172
}
2173
break;
2174
case '\\':
2175
/*
2176
* line splice
2177
*/
2178
2179
if (pp.in->type == IN_FILE && (!(pp.option & PLUSSPLICE) || !INCOMMENTXX(rp)))
2180
{
2181
m = 0;
2182
GET(c, n, tp, xp);
2183
if ((pp.option & SPLICESPACE) && !INQUOTE(rp))
2184
while (n == ' ')
2185
{
2186
GET(c, n, tp, xp);
2187
m = 1;
2188
}
2189
if (n == '\r')
2190
{
2191
GET(c, n, tp, xp);
2192
if (n != '\n' && n != EOB)
2193
BACKIN();
2194
}
2195
if (n == '\n')
2196
{
2197
#if CPP
2198
if (INQUOTE(rp))
2199
{
2200
if ((pp.option & STRINGSPLIT) && quot == '"')
2201
{
2202
PUTCHR(quot);
2203
PUTCHR(n);
2204
PUTCHR(quot);
2205
}
2206
else if (*pp.lineid)
2207
{
2208
PUTCHR(c);
2209
PUTCHR(n);
2210
}
2211
else
2212
{
2213
st |= HIDDEN;
2214
pp.hidden++;
2215
}
2216
}
2217
else
2218
#else
2219
#if COMPATIBLE
2220
if (!INQUOTE(rp) && (st & (COMPATIBILITY|DEFINITION|TRANSITION)) == (COMPATIBILITY|DEFINITION))
2221
{
2222
if (op == tp)
2223
{
2224
st |= HIDDEN;
2225
pp.hidden++;
2226
error_info.line++;
2227
if (st & SPACEOUT)
2228
goto fsm_start;
2229
c = (pp.option & SPLICECAT) ? '\t' : ' ';
2230
PUTCHR(c);
2231
goto fsm_check;
2232
}
2233
UNGETCHR(n);
2234
state &= ~SPLICE;
2235
goto fsm_terminal;
2236
}
2237
#endif
2238
#endif
2239
{
2240
st |= HIDDEN;
2241
pp.hidden++;
2242
}
2243
#if CPP
2244
spliced++;
2245
#else
2246
error_info.line++;
2247
#endif
2248
bp = ip;
2249
goto fsm_get;
2250
}
2251
else if ((n == 'u' || n == 'U') && !INQUOTE(rp))
2252
{
2253
PUTCHR(c);
2254
PUTCHR(n);
2255
bp = ip;
2256
goto fsm_get;
2257
}
2258
#if COMPATIBLE
2259
else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && (n == '"' || n == '\'') && !INQUOTE(rp))
2260
{
2261
PUTCHR(c);
2262
PUTCHR(n);
2263
bp = ip;
2264
goto fsm_get;
2265
}
2266
#endif
2267
else if (n != EOB)
2268
BACKIN();
2269
if (m && INSPACE(rp))
2270
UNGETCHR(c);
2271
}
2272
#if COMPATIBLE
2273
else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && !INQUOTE(rp))
2274
{
2275
GET(c, n, tp, xp);
2276
if (n == '"' || n == '\'')
2277
{
2278
PUTCHR(c);
2279
PUTCHR(n);
2280
bp = ip;
2281
goto fsm_get;
2282
}
2283
if (n != EOB)
2284
BACKIN();
2285
}
2286
#endif
2287
break;
2288
case '\r':
2289
/*
2290
* barf
2291
*/
2292
2293
if (pp.in->type == IN_FILE)
2294
{
2295
GET(c, n, tp, xp);
2296
if (n == '\n')
2297
{
2298
*(bp = ip - 1) = c = n;
2299
if (state = rp[c]) goto fsm_next;
2300
goto fsm_get;
2301
}
2302
if (n != EOB) BACKIN();
2303
}
2304
break;
2305
case CC_sub:
2306
/*
2307
* barf & puke
2308
*/
2309
2310
if ((pp.option & ZEOF) && pp.in->type == IN_FILE)
2311
{
2312
pp.in->flags |= IN_eof;
2313
c = 0;
2314
state = S_EOB;
2315
goto fsm_terminal;
2316
}
2317
break;
2318
}
2319
if ((state &= ~SPLICE) >= TERMINAL)
2320
goto fsm_terminal;
2321
PUTCHR(c);
2322
goto fsm_begin;
2323
}
2324
#if CPP
2325
if (INOPSPACE(rp))
2326
{
2327
BACKIN();
2328
goto fsm_start;
2329
}
2330
#endif
2331
PUTCHR(c);
2332
bp = ip;
2333
goto fsm_get;
2334
}
2335
#if !CPP
2336
fsm_token:
2337
st &= ~NEWLINE;
2338
if (pp.level == 1)
2339
{
2340
pp.in->flags |= IN_tokens;
2341
if (st & NOTEXT)
2342
{
2343
BACKOUT();
2344
goto fsm_top;
2345
}
2346
fsm_symbol:
2347
count(token);
2348
}
2349
fsm_check:
2350
if (st & SKIPCONTROL)
2351
{
2352
BACKOUT();
2353
goto fsm_start;
2354
}
2355
fsm_return:
2356
#if CPP
2357
error_info.line += spliced;
2358
#endif
2359
SETCHR(0);
2360
debug((-5, "token[%d] %03o = %s", pp.level, c, pptokstr(tp, 0)));
2361
SYNC();
2362
pp.level--;
2363
error_info.indent--;
2364
return c;
2365
#endif
2366
}
2367
2368
#if CPP && POOL
2369
2370
#include <ls.h>
2371
#include <wait.h>
2372
2373
/*
2374
* output pool status on exit
2375
*/
2376
2377
static void
2378
poolstatus(void)
2379
{
2380
error(ERROR_OUTPUT|0, pp.pool.output, "%d", error_info.errors != 0);
2381
}
2382
2383
/*
2384
* loop on < input output >
2385
*/
2386
2387
static void
2388
pool(void)
2389
{
2390
char* ifile;
2391
char* ofile;
2392
2393
ppflushout();
2394
if (!sfnew(sfstdin, NiL, SF_UNBOUND, pp.pool.input, SF_READ))
2395
error(ERROR_SYSTEM|3, "cannot dup pool input");
2396
2397
/*
2398
* kick the -I cache
2399
*/
2400
2401
ppsearch(".", T_STRING, SEARCH_EXISTS);
2402
2403
/*
2404
* loop on < input output >
2405
*/
2406
2407
pp.pool.input = 0;
2408
while (ifile = sfgetr(sfstdin, '\n', 1))
2409
{
2410
if (!(ofile = strchr(ifile, ' ')))
2411
error(3, "%s: pool output file expected", ifile);
2412
*ofile++ = 0;
2413
waitpid(0, NiL, WNOHANG);
2414
switch (fork())
2415
{
2416
case -1:
2417
error(ERROR_SYSTEM|3, "cannot fork pool");
2418
case 0:
2419
atexit(poolstatus);
2420
error_info.errors = 0;
2421
error_info.warnings = 0;
2422
close(0);
2423
if (open(ifile, O_RDONLY))
2424
error(ERROR_SYSTEM|3, "%s: cannot read", ifile);
2425
close(1);
2426
if (open(ofile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1)
2427
error(ERROR_SYSTEM|3, "%s: cannot create", ofile);
2428
pp.outfile = ofile;
2429
pathcanon(ifile, 0, 0);
2430
ifile = ppsetfile(ifile)->name;
2431
#if CHECKPOINT
2432
if (pp.mode & DUMP)
2433
{
2434
if (!pp.pragma)
2435
error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA));
2436
(*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1);
2437
}
2438
#endif
2439
PUSH_FILE(ifile, 0);
2440
return;
2441
}
2442
}
2443
while (wait(NiL) != -1);
2444
}
2445
2446
#endif
2447
2448