1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1986-2012 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 <gsf@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22 * Glenn Fowler
23 * AT&T Research
24 *
25 * convert C prototypes to ANSI, K&R and C++ styles or K&R to ANSI
26 * slips into the pp block read
27 *
28 * define PROTOMAIN for standalone proto
29 * PROTOMAIN is coded for minimal library support
30 */
31
32 static const char id[] = "\n@(#)$Id: proto (AT&T Research) 2008-05-11 $\0\n";
33
34 #if PROTOMAIN
35
36 #include "ppfsm.c"
37
38 #include <hashkey.h>
39
40 #if PROTO_STANDALONE
41 #undef O_RDONLY
42 #endif
43
44 #else
45
46 #include "pplib.h"
47 #include "ppfsm.h"
48
49 #endif
50
51 #define GENERATED "/* : : generated by proto : : */\n"
52
53 #define PRAGMADIR "pragma" /* pragma directive */
54 #define MAGICTOP 80 /* must be in these top lines */
55
56 #ifndef elementsof
57 #define elementsof(x) (sizeof(x)/sizeof(x[0]))
58 #endif
59
60 typedef struct Key_s
61 {
62 const char* name;
63 size_t size;
64 int hit;
65 int val;
66 } Key_t;
67
68 typedef struct Proto_s /* proto buffer state */
69 {
70 int brace; /* {..} level */
71 int call; /* call level */
72 int fd; /* input file descriptor */
73 char* file; /* input file name */
74 long flags; /* coupled flags */
75 long options; /* uncoupled flags */
76 char* package; /* header package */
77 int line; /* input line count */
78 int test; /* testing */
79
80 char* tp; /* input token base */
81
82 int iz; /* input buffer size */
83 char* ib; /* input buffer base */
84 char* ip; /* input buffer pointer */
85
86 int oz; /* output buffer size */
87 char* ob; /* output buffer base */
88 char* op; /* output buffer pointer */
89 char* ox; /* output buffer externalize */
90
91 char cc[3]; /* beg mid end comment char */
92 char pushback[4]; /* pushback area for caller */
93
94 char variadic[256]; /* variadic args buffer */
95
96 /* output buffer */
97 /* slide buffer */
98 /* input buffer */
99 } Proto_t;
100
101 /*
102 * proto is separate from pp so these undef's are ok
103 */
104
105 #undef CLASSIC
106 #define CLASSIC (1L<<0)
107 #undef DECLARE
108 #define DECLARE (1L<<1)
109 #undef DEFINE
110 #define DEFINE (1L<<2)
111 #undef DIRECTIVE
112 #define DIRECTIVE (1L<<3)
113 #undef ERROR
114 #define ERROR (1L<<4)
115 #undef EXTERN
116 #define EXTERN (1L<<5)
117 #undef EXTERNALIZE
118 #define EXTERNALIZE (1L<<6)
119 #undef IDID
120 #define IDID (1L<<7)
121 #undef INDIRECT
122 #define INDIRECT (1L<<8)
123 #undef INIT
124 #define INIT (1L<<9)
125 #undef INIT_DEFINE
126 #define INIT_DEFINE (1L<<10)
127 #undef INIT_INCLUDE
128 #define INIT_INCLUDE (1L<<11)
129 #undef JUNK
130 #define JUNK (1L<<12)
131 #undef LINESYNC
132 #define LINESYNC (1L<<13)
133 #undef MANGLE
134 #define MANGLE (1L<<14)
135 #undef MATCH
136 #define MATCH (1L<<15)
137 #undef MORE
138 #define MORE (1L<<16)
139 #undef OTHER
140 #define OTHER (1L<<17)
141 #undef PASS
142 #define PASS (1L<<18)
143 #undef PLUSONLY
144 #define PLUSONLY (1L<<19)
145 #undef PLUSPLUS
146 #define PLUSPLUS (1L<<20)
147 #undef RECURSIVE
148 #define RECURSIVE (1L<<21)
149 #undef SHARP
150 #define SHARP (1L<<22)
151 #undef SKIP
152 #define SKIP (1L<<23)
153 #undef SLIDE
154 #define SLIDE (1L<<24)
155 #undef TOKENS
156 #define TOKENS (1L<<25)
157 #undef TYPEDEF
158 #define TYPEDEF (1L<<26)
159 #undef VARIADIC
160 #define VARIADIC (1L<<27)
161 #undef VARIADIC2
162 #define VARIADIC2 (1L<<28)
163 #undef YACC
164 #define YACC (1L<<29)
165 #undef YACCSPLIT
166 #define YACCSPLIT (1L<<30)
167 #undef YACC2
168 #define YACC2 (1L<<31)
169
170 #undef GLOBAL
171 #define GLOBAL (MORE)
172
173 #undef REGULAR
174 #define REGULAR (1L<<0)
175
176 #ifndef CHUNK
177 #define CHUNK 1024
178 #endif
179 #define BLOCK (16*CHUNK)
180
181 #define T_VA_START (N_TOKEN+1)
182
183 #define RESERVED(b,e,n) ((((long)(b))<<16)|(((long)(e))<<8)|((long)(n)))
184
185 #define KEYENT(s,m,v) {s,sizeof(s)-1,m,v}
186
187 #define HIT_prototyped 0x01
188 #define HIT_noticed 0x02
189
190 static const Key_t pragmas[] =
191 {
192 KEYENT("prototyped", HIT_prototyped, 1), /* NOTE: first entry */
193 KEYENT("noprototyped", HIT_prototyped, 0),
194 KEYENT("noticed", HIT_noticed, 1),
195 KEYENT("nonoticed", HIT_noticed, 0),
196 };
197
198 #if PROTOMAIN
199 static const Key_t notices[] =
200 {
201 KEYENT("Copyright", HIT_noticed, 1),
202 KEYENT("COPYRIGHT", HIT_noticed, 1),
203 KEYENT("copyright", HIT_noticed, 1),
204 KEYENT("Public Domain", HIT_noticed, 0),
205 KEYENT("PUBLIC DOMAIN", HIT_noticed, 0),
206 };
207 #endif
208
209 /*
210 * generate integer
211 * pointer to end returned
212 */
213
214 static char*
number(register char * p,register long n)215 number(register char* p, register long n)
216 {
217 register long d;
218
219 for (d = 1000000; d > 1; d /= 10)
220 if (n >= d) *p++ = '0' + (n / d) % 10;
221 *p++ = '0' + n % 10;
222 return p;
223 }
224
225 #if PROTOMAIN
226
227 static int errors;
228
229 #if PROTO_STANDALONE
230
231 /*
232 * namespace pollution forces us to claim parts of libc
233 */
234
235 #undef memcpy
236 #define memcpy(t,f,n) memcopy(t,f,n)
237 #undef strcpy
238 #define strcpy(t,f) strcopy(t,f)
239 #undef strlen
240 #define strlen(s) sstrlen(s)
241 #undef strncmp
242 #define strncmp(s,t,n) sstrncmp(s,t,n)
243
244 /*
245 * environmentally safe strlen()
246 */
247
248 static int
sstrlen(register const char * s)249 sstrlen(register const char* s)
250 {
251 register const char* b;
252
253 for (b = s; *s; s++);
254 return s - b;
255 }
256
257 /*
258 * environmentally safe strncmp()
259 */
260
261 static int
sstrncmp(register const char * s,register const char * t,register int n)262 sstrncmp(register const char* s, register const char* t, register int n)
263 {
264 register const char* e = s + n;
265
266 while (s < e)
267 {
268 if (*s != *t || !*s)
269 return *s - *t;
270 s++;
271 t++;
272 }
273 return 0;
274 }
275
276 /*
277 * strcpy() except pointer to end returned
278 */
279
280 static char*
strcopy(register char * s,register const char * t)281 strcopy(register char* s, register const char* t)
282 {
283 while (*s++ = *t++);
284 return s - 1;
285 }
286
287 #endif
288
289 static void
proto_error(char * iob,int level,char * msg,char * arg)290 proto_error(char* iob, int level, char* msg, char* arg)
291 {
292 register char* p;
293 char buf[1024];
294
295 p = strcopy(buf, "proto: ");
296 if (iob)
297 {
298 register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
299
300 if (proto->line)
301 {
302 if (proto->file)
303 {
304 *p++ = '"';
305 p = strcopy(p, proto->file);
306 *p++ = '"';
307 *p++ = ',';
308 *p++ = ' ';
309 }
310 p = strcopy(p, "line ");
311 p = number(p, proto->line);
312 }
313 else if (proto->file)
314 p = strcopy(p, proto->file);
315 }
316 else
317 {
318 p = strcopy(p, msg);
319 msg = arg;
320 arg = 0;
321 }
322 if (*(p - 1) != ' ')
323 {
324 *p++ = ':';
325 *p++ = ' ';
326 }
327 if (level == 1)
328 p = strcopy(p, "warning: ");
329 p = strcopy(p, msg);
330 if (arg)
331 {
332 *p++ = ' ';
333 p = strcopy(p, arg);
334 }
335 *p++ = '\n';
336 write(2, buf, p - buf);
337 if (level >= 3)
338 exit(level - 2);
339 if (level >= 2)
340 errors++;
341 }
342
343 /*
344 * memcpy() but pointer to end returned
345 */
346
347 static char*
memcopy(register char * s,register char * t,int n)348 memcopy(register char* s, register char* t, int n)
349 {
350 register char* e = t + n;
351
352 while (t < e) *s++ = *t++;
353 return s;
354 }
355
356 #include "../libast/port/astlicense.c"
357
358 #else
359
360 #define memcopy(s,t,n) (((char*)memcpy(s,t,n))+(n))
361
362 #endif
363
364 /*
365 * generate line sync
366 * pointer to end returned
367 */
368
369 static char*
linesync(register Proto_t * proto,register char * p,register long n)370 linesync(register Proto_t* proto, register char* p, register long n)
371 {
372 #if PROTOMAIN
373 if (proto->flags & LINESYNC)
374 #endif
375 {
376 #if PROTOMAIN
377 p = strcopy(p, "\n#line ");
378 #else
379 p = strcopy(p, "\n# ");
380 #endif
381 p = number(p, n);
382 *p++ = '\n';
383 }
384 return p;
385 }
386
387 /*
388 * output init header
389 * pointer to end returned
390 */
391
392 static char*
init(Proto_t * proto,char * op,int flags)393 init(Proto_t* proto, char* op, int flags)
394 {
395 register char* s;
396
397 if (flags & INIT_DEFINE)
398 {
399 op = strcopy(op, "\
400 \n\
401 #if !defined(__PROTO__)\n\
402 # if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\
403 # if defined(__cplusplus)\n\
404 # define __LINKAGE__ \"C\"\n\
405 # else\n\
406 # define __LINKAGE__\n\
407 # endif\n\
408 # define __STDARG__\n\
409 # define __PROTO__(x) x\n\
410 # define __OTORP__(x)\n\
411 # define __PARAM__(n,o) n\n\
412 # if !defined(__STDC__) && !defined(__cplusplus)\n\
413 # if !defined(c_plusplus)\n\
414 # define const\n\
415 # endif\n\
416 # define signed\n\
417 # define void int\n\
418 # define volatile\n\
419 # define __V_ char\n\
420 # else\n\
421 # define __V_ void\n\
422 # endif\n\
423 # else\n\
424 # define __PROTO__(x) ()\n\
425 # define __OTORP__(x) x\n\
426 # define __PARAM__(n,o) o\n\
427 # define __LINKAGE__\n\
428 # define __V_ char\n\
429 # define const\n\
430 # define signed\n\
431 # define void int\n\
432 # define volatile\n\
433 # endif\n\
434 # define __MANGLE__ __LINKAGE__\n\
435 # if defined(__cplusplus) || defined(c_plusplus)\n\
436 # define __VARARG__ ...\n\
437 # else\n\
438 # define __VARARG__\n\
439 # endif\n\
440 # if defined(__STDARG__)\n\
441 # define __VA_START__(p,a) va_start(p,a)\n\
442 # else\n\
443 # define __VA_START__(p,a) va_start(p)\n\
444 # endif\n\
445 # if !defined(__INLINE__)\n\
446 # if defined(__cplusplus)\n\
447 # define __INLINE__ extern __MANGLE__ inline\n\
448 # else\n\
449 # if defined(_WIN32) && !defined(__GNUC__)\n\
450 # define __INLINE__ __inline\n\
451 # endif\n\
452 # endif\n\
453 # endif\n\
454 #endif\n\
455 #if !defined(__LINKAGE__)\n\
456 #define __LINKAGE__ /* 2004-08-11 transition */\n\
457 #endif\n\
458 ");
459 }
460 else
461 op = strcopy(op, "\
462 \n\
463 #if !defined(__PROTO__)\n\
464 #include <prototyped.h>\n\
465 #endif\n\
466 #if !defined(__LINKAGE__)\n\
467 #define __LINKAGE__ /* 2004-08-11 transition */\n\
468 #endif\n\
469 ");
470 if (proto->package)
471 {
472 s = "\
473 #ifndef __MANGLE_%_DATA__\n\
474 # ifdef _BLD_%\n\
475 # ifdef __EXPORT__\n\
476 # define __MANGLE_%_DATA__ __MANGLE__ __EXPORT__\n\
477 # else\n\
478 # define __MANGLE_%_DATA__ __MANGLE__\n\
479 # endif\n\
480 # define __MANGLE_%_FUNC__ __MANGLE__\n\
481 # else\n\
482 # ifdef __IMPORT__\n\
483 # define __MANGLE_%_DATA__ __MANGLE__ __IMPORT__\n\
484 # else\n\
485 # define __MANGLE_%_DATA__ __MANGLE__\n\
486 # endif\n\
487 # define __MANGLE_%_FUNC__ __MANGLE__\n\
488 # endif\n\
489 #endif\n\
490 ";
491 for (;;)
492 {
493 switch (*op++ = *s++)
494 {
495 case 0:
496 op--;
497 break;
498 case '%':
499 op = strcopy(op - 1, proto->package);
500 continue;
501 default:
502 continue;
503 }
504 break;
505 }
506 }
507 return op;
508 }
509
510 #define BACKOUT() (op=ko)
511 #define CACHE() do{CACHEIN();CACHEOUT();call=proto->call;}while(0)
512 #define CACHEIN() (ip=proto->ip)
513 #define CACHEOUT() (op=proto->op)
514 #define GETCHR() (*(unsigned char*)ip++)
515 #define KEEPOUT() (ko=op)
516 #define LASTOUT() (*(op-1))
517 #define PUTCHR(c) (*op++=(c))
518 #define SYNC() do{SYNCIN();SYNCOUT();proto->flags&=~(EXTERN|INIT|OTHER|VARIADIC|VARIADIC2);proto->flags|=flags&(EXTERN|INIT|OTHER|VARIADIC|VARIADIC2);proto->call=call;}while(0)
519 #define SYNCIN() (proto->ip=ip)
520 #define SYNCOUT() (proto->op=op)
521 #define UNGETCHR() (ip--)
522 #define UNPUTCHR() (op--)
523
524 /*
525 * advance to the next non-space character
526 */
527
528 static char*
nns(register char * s)529 nns(register char* s)
530 {
531 while (*s == ' ' || *s == '\t' || *s == '\n')
532 s++;
533 return s;
534 }
535
536 #define DIR_if 01
537 #define DIR_el 02
538 #define DIR_en 03
539 #define DIR 03
540
541 /*
542 * update directive mask
543 */
544
545 static int
directive(register char * s,int dir)546 directive(register char* s, int dir)
547 {
548 switch (*(s = nns(s)))
549 {
550 case 'e':
551 case 'i':
552 dir <<= 2;
553 switch (*++s)
554 {
555 case 'f':
556 dir |= DIR_if;
557 break;
558 case 'l':
559 dir |= DIR_el;
560 break;
561 case 'n':
562 dir |= DIR_en;
563 break;
564 }
565 break;
566 }
567 return dir;
568 }
569
570 /*
571 * the tokenizer
572 * top level calls loop until EOB
573 * recursive calls just return the next token
574 */
575
576 static int
lex(register Proto_t * proto,register long flags)577 lex(register Proto_t* proto, register long flags)
578 {
579 register char* ip;
580 register char* op;
581 register int c;
582 register int state;
583 register short* rp;
584 char* m;
585 char* e;
586 char* t;
587 char* bp;
588 char* v;
589 char* im;
590 char* ko;
591 char* aom;
592 int n;
593 int line;
594 int quot;
595 int brack;
596 int sub;
597 int x;
598 int vc;
599
600 char* ie = 0;
601 char* om = 0;
602 char* aim = 0;
603 char* aie = 0;
604 char* func = 0;
605 int call = 0;
606 int dir = 0;
607 int group = 0;
608 int last = 0;
609 int paren = 0;
610 #if PROTOMAIN
611 char* qe = 0;
612 int qn = 0;
613 int args = 0;
614 #endif
615
616 CACHE();
617 #if PROTOMAIN
618 if (flags & EXTERN) KEEPOUT();
619 #endif
620 fsm_start:
621 proto->tp = ip;
622 state = PROTO;
623 bp = ip;
624 do
625 {
626 rp = fsm[state];
627 fsm_get:
628 while (!(state = rp[c = GETCHR()]));
629 fsm_next:
630 ;
631 } while (state > 0);
632 if ((n = ip - bp - 1) > 0)
633 {
634 ip = bp;
635 MEMCPY(op, ip, n);
636 ip++;
637 }
638 state = ~state;
639 fsm_terminal:
640 switch (TERM(state))
641 {
642 case S_CHR:
643 if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c)
644 {
645 case '+':
646 case '-':
647 case '*':
648 case '&':
649 PUTCHR(' ');
650 break;
651 }
652 PUTCHR(c);
653 break;
654
655 case S_CHRB:
656 UNGETCHR();
657 c = LASTOUT();
658 break;
659
660 case S_COMMENT:
661 switch (c)
662 {
663 case '\n':
664 if (INCOMMENTXX(rp)) goto fsm_newline;
665 PUTCHR(c);
666 proto->line++;
667 rp = fsm[COM2];
668 break;
669 case '/':
670 #if PROTOMAIN
671 if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
672 else
673 #endif
674 PUTCHR(c);
675 if (INCOMMENTXX(rp))
676 {
677 rp = fsm[COM5];
678 break;
679 }
680 goto fsm_start;
681 case EOF:
682 break;
683 default:
684 #if PROTOMAIN
685 if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
686 else
687 #endif
688 PUTCHR(c);
689 rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
690 break;
691 }
692 bp = ip;
693 goto fsm_get;
694
695 case S_EOB:
696 if (c)
697 {
698 if (state = fsm[TERMINAL][INDEX(rp)+1])
699 goto fsm_terminal;
700 SYNC();
701 return 0;
702 }
703 UNGETCHR();
704 fsm_eob:
705 if ((flags & (DECLARE|GLOBAL|RECURSIVE)) == GLOBAL && (proto->flags & MORE))
706 {
707 #if PROTOMAIN
708 if (!(flags & EXTERN)) /* XXX */
709 #endif
710 flags |= SLIDE;
711 c = ip - proto->ib;
712 if (!(flags & MATCH))
713 im = proto->tp;
714 if (ip > proto->ib)
715 {
716 n = ip - im;
717 if (ip - n < proto->ib)
718 proto->flags |= ERROR;
719 memcopy(proto->ib - n, ip - n, n);
720 ip = proto->ib;
721 }
722 proto->tp -= c;
723 if (flags & MATCH)
724 {
725 im -= c;
726 ie -= c;
727 }
728 if (aim)
729 aim -= c;
730 if (aie)
731 aie -= c;
732 if ((n = read(proto->fd, ip, proto->iz)) > 0)
733 {
734 if ((proto->options & REGULAR) && n < proto->iz)
735 {
736 proto->flags &= ~MORE;
737 close(proto->fd);
738 }
739 *(ip + n) = 0;
740 if (state & SPLICE)
741 goto fsm_splice;
742 bp = ip;
743 goto fsm_get;
744 }
745 *ip = 0;
746 proto->flags &= ~MORE;
747 close(proto->fd);
748 }
749 if (state & SPLICE)
750 goto fsm_splice;
751 /* NOTE: RECURSIVE lex() should really SLIDE too */
752 if (!(flags & RECURSIVE) && (state = rp[c = EOF]))
753 {
754 bp = ip;
755 goto fsm_next;
756 }
757 SYNC();
758 return 0;
759
760 case S_LITBEG:
761 quot = c;
762 #if PROTOMAIN
763 if (c == '"' && qe)
764 {
765 for (n = 0, t = qe + 1; t < op && (*t == ' ' || *t == '\t' || *t == '\n' && ++n || *t >= 'A' && *t <= 'Z' || *t == '_'); t++);
766 if (t == op)
767 {
768 op = qe;
769 qe = 0;
770 qn = n;
771 }
772 else PUTCHR(c);
773 }
774 else
775 #endif
776 PUTCHR(c);
777 rp = fsm[LIT1];
778 bp = ip;
779 goto fsm_get;
780
781 case S_LITEND:
782 if (c == quot)
783 {
784 #if PROTOMAIN
785 if (!(flags & DIRECTIVE))
786 qe = (c == '"') ? op : (char*)0;
787 #endif
788 PUTCHR(c);
789 #if PROTOMAIN
790 while (qn > 0)
791 {
792 qn--;
793 PUTCHR('\n');
794 }
795 #endif
796 }
797 else if (c != '\n' && c != EOF)
798 {
799 PUTCHR(c);
800 bp = ip;
801 goto fsm_get;
802 }
803 else
804 {
805 #if PROTOMAIN
806 while (qn > 0)
807 {
808 qn--;
809 PUTCHR('\n');
810 }
811 #endif
812 UNGETCHR();
813 }
814 c = T_INVALID;
815 break;
816
817 case S_LITESC:
818 #if PROTOMAIN
819 if (flags & CLASSIC) PUTCHR(c);
820 else
821 #endif
822 switch (c)
823 {
824 case 'a':
825 n = CC_bel;
826 goto fsm_oct;
827 case 'E':
828 n = CC_esc;
829 goto fsm_oct;
830 case 'v':
831 n = CC_vt;
832 goto fsm_oct;
833 case 'x':
834 SYNC();
835 lex(proto, (flags & GLOBAL) | RECURSIVE);
836 for (n = x = 0; (c = GETCHR()), x < 3; x++) switch (c)
837 {
838 case '0': case '1': case '2': case '3':
839 case '4': case '5': case '6': case '7':
840 case '8': case '9':
841 n = (n << 4) + c - '0';
842 break;
843 case 'a': case 'b': case 'c': case 'd':
844 case 'e': case 'f':
845 n = (n << 4) + c - 'a' + 10;
846 break;
847 case 'A': case 'B': case 'C': case 'D':
848 case 'E': case 'F':
849 n = (n << 4) + c - 'A' + 10;
850 break;
851 default:
852 goto fsm_hex;
853 }
854 fsm_hex:
855 UNGETCHR();
856 fsm_oct:
857 PUTCHR(((n >> 6) & 07) + '0');
858 PUTCHR(((n >> 3) & 07) + '0');
859 PUTCHR((n & 07) + '0');
860 break;
861 default:
862 PUTCHR(c);
863 break;
864 }
865 rp = fsm[LIT1];
866 bp = ip;
867 goto fsm_get;
868
869 case S_MACRO:
870 UNGETCHR();
871 #if PROTOMAIN
872 if ((flags & EXTERN) && *proto->tp == 's' && !strncmp(proto->tp, "static", 6))
873 {
874 c = T_EXTERN;
875 break;
876 }
877 #endif
878 if (*proto->tp == '_' && !strncmp(proto->tp, "__STDPP__directive", 6)) c = '#';
879 else c = T_ID;
880
881 break;
882
883 case S_NL:
884 fsm_newline:
885 proto->line++;
886 #if PROTOMAIN
887 if (flags & EXTERN)
888 {
889 if (op != proto->ob && LASTOUT() != ' ' && LASTOUT() != '\n')
890 PUTCHR(' ');
891 }
892 else
893 #endif
894 PUTCHR(c);
895 if (flags & DIRECTIVE)
896 {
897 #if PROTOMAIN
898 if (flags & CLASSIC)
899 {
900 if (flags & EXTERN) BACKOUT();
901 if (flags & JUNK)
902 {
903 *(ip - 1) = 0;
904 op = strcopy(om, "/* ");
905 op = strcopy(op, im);
906 op = strcopy(op, " */\n");
907 }
908 flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|JUNK|MATCH|SHARP|TYPEDEF);
909 }
910 else
911 #endif
912 {
913 if ((flags & (DEFINE|SHARP)) == (DEFINE|SHARP))
914 {
915 *(ip - 1) = 0;
916 op = strcopy(om, "#if defined(__STDC__) || defined(__STDPP__)\n");
917 op = strcopy(op, im);
918 op = strcopy(op, "\n#else\n");
919 bp = ip;
920 ip = im;
921 *op++ = *ip++;
922 while (*op = *ip++)
923 if (*op++ == '#' && *ip != '(')
924 {
925 op--;
926 while (*--op == ' ' || *op == '\t');
927 if (*ip == '#')
928 {
929 op = strcopy(op + 1, "/**/");
930 while (*++ip == ' ' || *ip == '\t');
931 }
932 else
933 {
934 if (*op != '"') *++op = '"';
935 op++;
936 while (*ip == ' ' || *ip == '\t') ip++;
937 while ((c = *ip) >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '_') *op++ = *ip++;
938 while (*ip == ' ' || *ip == '\t') ip++;
939 if (*ip == '"') ip++;
940 else *op++ = '"';
941 }
942 }
943 ip = bp;
944 op = strcopy(op, "\n#endif\n");
945 op = linesync(proto, op, proto->line);
946 }
947 flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|MATCH|OTHER|SHARP|SKIP|TOKENS|TYPEDEF);
948 }
949 call = 0;
950 group = 0;
951 paren = 0;
952 last = '\n';
953 }
954 if (paren == 0 && (flags & (MATCH|RECURSIVE|SKIP|SLIDE)) == SLIDE)
955 {
956 #if PROTOMAIN
957 if (flags & EXTERN) BACKOUT();
958 #endif
959 SYNC();
960 return 0;
961 }
962 goto fsm_start;
963
964 case S_QUAL:
965 PUTCHR(c);
966 rp = fsm[NEXT(state)];
967 bp = ip;
968 goto fsm_get;
969
970 case S_TOK:
971 PUTCHR(c);
972 c = TYPE(state);
973 break;
974
975 case S_TOKB:
976 UNGETCHR();
977 c = TYPE(state);
978 break;
979
980 case S_RESERVED:
981 UNGETCHR();
982 c = T_ID;
983 if (!(flags & DECLARE)) switch (RESERVED(*proto->tp, *(ip - 1), ip - proto->tp))
984 {
985 case RESERVED('N', 'N', 3):
986 if (proto->tp[1] == 'o')
987 c = T_DO;
988 break;
989 case RESERVED('d', 'o', 2):
990 c = T_DO;
991 break;
992 case RESERVED('e', 'e', 4):
993 if (!(flags & RECURSIVE) && (flags & (DIRECTIVE|TOKENS)) != DIRECTIVE && !strncmp(proto->tp, "else", 4))
994 {
995 c = T_ELSE;
996 goto fsm_id;
997 }
998 break;
999 case RESERVED('e', 'n', 6):
1000 if (!strncmp(proto->tp, "extern", 6))
1001 c = T_EXTERN;
1002 break;
1003 case RESERVED('f', 'r', 3):
1004 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "for", 3))
1005 {
1006 c = T_FOR;
1007 goto fsm_id;
1008 }
1009 break;
1010 case RESERVED('i', 'f', 2):
1011 c = T_IF;
1012 break;
1013 case RESERVED('i', 'e', 6):
1014 if (!strncmp(proto->tp, "inline", 6) && !(flags & (MATCH|SKIP|TOKENS|TYPEDEF)) && proto->brace == 0 && paren == 0 && group == 0 && (last == ';' || last == '}' || last == '\n' || last == 0))
1015 {
1016 flags |= SKIP;
1017 SYNC();
1018 line = proto->line;
1019 op = strcopy(op - 6, "__INLINE__");
1020 SYNC();
1021 }
1022 break;
1023 case RESERVED('r', 'n', 6):
1024 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "return", 6))
1025 {
1026 c = T_RETURN;
1027 goto fsm_id;
1028 }
1029 break;
1030 case RESERVED('s', 'c', 6):
1031 if ((proto->options & EXTERNALIZE) && !strncmp(proto->tp, "static", 6))
1032 {
1033 proto->ox = op - 6;
1034 flags |= EXTERNALIZE;
1035 }
1036 break;
1037 case RESERVED('t', 'f', 7):
1038 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "typedef", 7))
1039 {
1040 flags |= TYPEDEF;
1041 c = T_EXTERN;
1042 }
1043 break;
1044 case RESERVED('v', 't', 8):
1045 if (*ip == '(' && !strncmp(proto->tp, "va_start", 8)) c = T_VA_START;
1046 break;
1047 case RESERVED('v', 'd', 4):
1048 if (!strncmp(proto->tp, "void", 4))
1049 {
1050 if (flags & (CLASSIC|PLUSONLY|INIT_DEFINE|INIT_INCLUDE)) c = T_VOID;
1051 else
1052 {
1053 SYNC();
1054 line = proto->line;
1055 if (lex(proto, (flags & GLOBAL) | RECURSIVE) == '*')
1056 {
1057 memcopy(op - 4, "__V_", 4);
1058 memcopy(ip - 4, "__V_", 4);
1059 }
1060 else c = T_VOID;
1061 proto->line = line;
1062 SYNC();
1063 bp = ip;
1064 }
1065 }
1066 break;
1067 case RESERVED('w', 'e', 5):
1068 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "while", 5))
1069 {
1070 c = T_WHILE;
1071 goto fsm_id;
1072 }
1073 break;
1074 }
1075 #if PROTOMAIN
1076 if ((flags & CLASSIC) && c != T_EXTERN)
1077 c = T_ID;
1078 #endif
1079 break;
1080
1081 case S_VS:
1082 goto fsm_start;
1083
1084 case S_WS:
1085 UNGETCHR();
1086 #if PROTOMAIN
1087 if ((flags & (EXTERN|MATCH)) == EXTERN)
1088 {
1089 while (op > proto->ob && (*(op - 1) == ' ' || *(op - 1) == '\t'))
1090 op--;
1091 if (op > proto->ob && *(op - 1) != '\n') *op++ = ' ';
1092 }
1093 #endif
1094 goto fsm_start;
1095
1096 default:
1097 if (state & SPLICE)
1098 {
1099 if (c == '\\')
1100 {
1101 if (!(n = GETCHR()))
1102 {
1103 goto fsm_eob;
1104 fsm_splice:
1105 c = '\\';
1106 n = GETCHR();
1107 }
1108 if (n == '\n')
1109 {
1110 proto->line++;
1111 PUTCHR('\\');
1112 PUTCHR('\n');
1113 bp = ip;
1114 goto fsm_get;
1115 }
1116 UNGETCHR();
1117 }
1118 state &= ~SPLICE;
1119 if (state >= TERMINAL)
1120 goto fsm_terminal;
1121 rp = fsm[state];
1122 }
1123 PUTCHR(c);
1124 bp = ip;
1125 goto fsm_get;
1126 }
1127 if (!(flags & (INIT_DEFINE|INIT_INCLUDE|RECURSIVE)))
1128 {
1129 if (!(flags & DIRECTIVE)) switch (c)
1130 {
1131 case '(':
1132 #if PROTOMAIN
1133 if (!(flags & CLASSIC) || proto->brace == 0)
1134 #endif
1135 {
1136 if (paren++ == 0)
1137 {
1138 #if PROTOMAIN
1139 if (!(flags & CLASSIC) || group <= 1)
1140 #endif
1141 {
1142 #if PROTOMAIN
1143 args = 0;
1144 #endif
1145 if (group++ == 0) group++;
1146 else if (flags & INDIRECT) call++;
1147 flags |= MATCH;
1148 im = ip - 1;
1149 om = op - 1;
1150 }
1151 sub = 0;
1152 }
1153 else if (paren == 2 && !aim)
1154 {
1155 sub++;
1156 if (last == '(')
1157 {
1158 flags &= ~MATCH;
1159 om = 0;
1160 }
1161 else if (flags & INDIRECT)
1162 {
1163 aim = ip - 1;
1164 aom = op - 1;
1165 }
1166 else if ((flags & (MATCH|TOKENS)) == MATCH)
1167 {
1168 for (m = ip - 2; m > im && (*m == ' ' || *m == '\t'); m--);
1169 if (m != im && sub == 1)
1170 {
1171 m = im + (*nns(ip) == '*');
1172 }
1173 if (m == im)
1174 {
1175 flags &= ~MATCH;
1176 om = 0;
1177 }
1178 }
1179 else if ((flags & MATCH) && sub == 1 && *nns(ip) != '*')
1180 {
1181 flags &= ~MATCH;
1182 om = 0;
1183 }
1184 }
1185 flags &= ~TOKENS;
1186 }
1187 break;
1188 case ')':
1189 #if PROTOMAIN
1190 if (!(flags & CLASSIC) || proto->brace == 0)
1191 #endif
1192 if (--paren == 0)
1193 {
1194 #if PROTOMAIN
1195 if (flags & CLASSIC)
1196 {
1197 if (group != 2)
1198 {
1199 c = T_ID;
1200 break;
1201 }
1202 group++;
1203 }
1204 #endif
1205 ie = ip;
1206 }
1207 else if (paren == 1 && (flags & INDIRECT) && !aie)
1208 aie = ip;
1209 break;
1210 case '*':
1211 if (last == '(' && group == 2)
1212 {
1213 group--;
1214 if (paren == 1)
1215 {
1216 flags |= INDIRECT;
1217 aim = aie = 0;
1218 }
1219 }
1220 break;
1221 case '#':
1222 dir = directive(ip, dir);
1223 if (proto->brace == 0 && paren == 0 && last != '=' && (flags & (CLASSIC|DECLARE|DIRECTIVE|MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS) && ((dir & DIR) != DIR_en || ((dir>>2) & DIR) != DIR_if))
1224 flags |= DIRECTIVE;
1225 else if (!(flags & (DECLARE|DIRECTIVE)))
1226 {
1227 flags |= DIRECTIVE;
1228 if (!(flags & PLUSONLY))
1229 {
1230 bp = ip;
1231 while (*ip == ' ' || *ip == '\t') ip++;
1232 if (*ip == 'l' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e')
1233 {
1234 if (*++ip == ' ' || *ip == '\t')
1235 {
1236 proto->line = 0;
1237 while (*++ip >= '0' && *ip <= '9')
1238 proto->line = proto->line * 10 + *ip - '0';
1239 proto->line--;
1240 }
1241 }
1242 #if PROTOMAIN
1243 else if ((flags & (CLASSIC|EXTERN)) == CLASSIC)
1244 {
1245 n = 0;
1246 t = ip + 6;
1247 while (ip < t && *ip >= 'a' && *ip <= 'z')
1248 n = HASHKEYPART(n, *ip++);
1249 switch (n)
1250 {
1251 case HASHKEY4('e','l','s','e'):
1252 case HASHKEY5('e','n','d','i','f'):
1253 while (*ip == ' ' || *ip == '\t') ip++;
1254 if (*ip != '\n' && *ip != '/' && *(ip + 1) != '*')
1255 {
1256 flags |= JUNK|MATCH;
1257 im = ip;
1258 om = op + (ip - bp);
1259 }
1260 break;
1261 case HASHKEY4('e','l','i','f'):
1262 case HASHKEY5('e','r','r','o','r'):
1263 case HASHKEY2('i','f'):
1264 case HASHKEY5('i','f','d','e','f'):
1265 case HASHKEY6('i','f','n','d','e','f'):
1266 case HASHKEY5('u','n','d','e','f'):
1267 break;
1268 case HASHKEY6('i','n','c','l','u','d'):
1269 if (*ip == 'e') ip++;
1270 /*FALLTHROUGH*/
1271 case HASHKEY6('d','e','f','i','n','e'):
1272 case HASHKEY6('p','r','a','g','m','a'):
1273 if (*ip < 'a' || *ip > 'z') break;
1274 /*FALLTHROUGH*/
1275 default:
1276 flags |= JUNK|MATCH;
1277 im = bp - 1;
1278 om = op - 1;
1279 break;
1280 }
1281 }
1282 else
1283 #endif
1284 {
1285 if (*ip == 'i' && *++ip == 'n' && *++ip == 'c' && *++ip == 'l' && *++ip == 'u' && *++ip == 'd' && *++ip == 'e')
1286 {
1287 while (*++ip == ' ' || *ip == '\t');
1288 if (*ip++ == '<' && *ip++ == 's' && *ip++ == 't' && *ip++ == 'd' && *ip++ == 'a' && *ip++ == 'r' && *ip++ == 'g' && *ip++ == '.' && *ip++ == 'h' && *ip++ == '>')
1289 {
1290 op = strcopy(op, "\
1291 if !defined(va_start)\n\
1292 #if defined(__STDARG__)\n\
1293 #include <stdarg.h>\n\
1294 #else\n\
1295 #include <varargs.h>\n\
1296 #endif\n\
1297 #endif\n\
1298 ");
1299 op = linesync(proto, op, proto->line);
1300 break;
1301 }
1302 }
1303 else if (*ip == 'd' && *++ip == 'e' && *++ ip == 'f' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e' && (*++ip == ' ' || *ip == '\t'))
1304 {
1305 while (*++ip == ' ' || *ip == '\t');
1306 if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t'))
1307 {
1308 t = ip;
1309 while (*++t == ' ' || *t == '\t');
1310 if (*t == 'e' && *++t == 'x' && *++ t == 't' && *++t == 'e' && *++t == 'r' && *++t == 'n' && (*++t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'))
1311 ip = t;
1312 t = ip;
1313 while (*++t == ' ' || *t == '\t');
1314 if (*t == '_' && *(t + 1) == '_')
1315 {
1316 op = strcopy(op, "undef __MANGLE__\n");
1317 op = linesync(proto, op, proto->line);
1318 op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
1319 break;
1320 }
1321 }
1322 flags |= DEFINE|MATCH;
1323 im = bp - 1;
1324 om = op - 1;
1325 }
1326 else if (*ip == 'u' && *++ip == 'n' && *++ ip == 'd' && *++ip == 'e' && *++ip == 'f' && (*++ip == ' ' || *ip == '\t'))
1327 {
1328 while (*++ip == ' ' || *ip == '\t');
1329 if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t' || *ip == '\n' || *ip == '\r'))
1330 {
1331 op = strcopy(op, "undef __MANGLE__\n");
1332 op = linesync(proto, op, proto->line);
1333 op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
1334 break;
1335 }
1336 flags |= DEFINE|MATCH;
1337 im = bp - 1;
1338 om = op - 1;
1339 }
1340 }
1341 ip = bp;
1342 }
1343 break;
1344 }
1345 else
1346 break;
1347 /*FALLTHROUGH*/
1348 case '{':
1349 if (proto->brace++ == 0 && paren == 0)
1350 {
1351 if (last == '=') flags |= INIT;
1352 #if PROTOMAIN
1353 else if (flags & CLASSIC)
1354 {
1355 if ((flags & (MATCH|OTHER|SKIP)) == MATCH)
1356 {
1357 if (args)
1358 {
1359 v = number(op, args < 0 ? -args : args);
1360 v = strcopy(v, " argument actual/formal mismatch");
1361 *v++ = ' ';
1362 v = memcopy(v, im, ie - im);
1363 *v = 0;
1364 proto_error((char*)proto + sizeof(Proto_t), 2, op, NiL);
1365 }
1366 ip--;
1367 /*UNDENT...*/
1368 v = ie;
1369 while (ie < ip)
1370 if (*ie++ == '/' && *ie == '*')
1371 {
1372 e = ie - 1;
1373 while (++ie < ip)
1374 {
1375 if (*ie == '*')
1376 {
1377 while (ie < ip && *ie == '*') ie++;
1378 if (ie < ip && *ie == '/')
1379 {
1380 while (++ie < ip && (*ie == ' ' || *ie == '\t'));
1381 while (e > v && (*(e - 1) == ' ' || *(e - 1) == '\t')) e--;
1382 if (e > v && *e != '\n') *e++ = ' ';
1383 t = ie;
1384 while (--e >= v)
1385 *--t = *e;
1386 v = t;
1387 break;
1388 }
1389 }
1390 }
1391 }
1392 ie = v;
1393 /*...INDENT*/
1394 op = om++;
1395 if (flags & EXTERN)
1396 {
1397 v = op;
1398 while (v > ko && *--v != ' ');
1399 if (*v != ' ')
1400 {
1401 om = (v = (op += 4)) + 1;
1402 while (v >= ko + 4)
1403 {
1404 *v = *(v - 4);
1405 v--;
1406 }
1407 memcopy(ko, "int ", 4);
1408 }
1409 if (*v == ' ')
1410 {
1411 while (*(v + 1) == '*')
1412 *v++ = '*';
1413 *v = '\t';
1414 if ((v - ko) <= 8)
1415 {
1416 om = (e = ++op) + 1;
1417 while (e > v)
1418 {
1419 *e = *(e - 1);
1420 e--;
1421 }
1422 }
1423 }
1424 om = (v = (op += 7)) + 1;
1425 while (v >= ko + 7)
1426 {
1427 *v = *(v - 7);
1428 v--;
1429 }
1430 memcopy(ko, "extern ", 7);
1431 }
1432 PUTCHR('(');
1433 t = op;
1434 e = 0;
1435 /*UNDENT...*/
1436 while (ie < ip)
1437 {
1438 if ((c = *ie) == ' ' || c == '\t' || c == '\n')
1439 {
1440 while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
1441 if (ie >= ip) break;
1442 if (c != '*' && op > om) PUTCHR(' ');
1443 }
1444 if ((n = ((c = *ie) == ',')) || c == ';')
1445 {
1446 if (flags & EXTERN)
1447 {
1448 m = op;
1449 while (op > om && ((c = *(op - 1)) == '(' || c == ')' || c == '[' || c == ']'))
1450 op--;
1451 v = op;
1452 while (op > om && (c = *(op - 1)) != ' ' && c != '*')
1453 op--;
1454 while (*(op - 1) == ' ')
1455 op--;
1456 if (!e)
1457 {
1458 e = op;
1459 while (e > om && *(e - 1) == '*')
1460 e--;
1461 }
1462 #if _s5r4_386_compiler_bug_fixed_
1463 if (op <= om || *(op - 1) == ',' && (*op++ = ' '))
1464 op = strcopy(op, "int");
1465 #else
1466 if (op <= om)
1467 op = strcopy(op, "int");
1468 else if (*(op - 1) == ',')
1469 op = strcopy(op, " int");
1470 #endif
1471 while (v < m)
1472 PUTCHR(*v++);
1473 }
1474 PUTCHR(',');
1475 if (n)
1476 {
1477 if (x = !e) e = op - 1;
1478 PUTCHR(' ');
1479 m = t;
1480 while (m < e)
1481 PUTCHR(*m++);
1482 if (x)
1483 {
1484 m = e;
1485 while (*--e != ' ');
1486 while (*(e - 1) == '*') e--;
1487 op -= m - e;
1488 }
1489 }
1490 while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
1491 if (ie >= ip) UNPUTCHR();
1492 else PUTCHR(' ');
1493 if (!n)
1494 {
1495 t = op;
1496 e = 0;
1497 }
1498 }
1499 else if (*ie == '*')
1500 {
1501 if (op > om && (c = *(op - 1)) == ' ') op--;
1502 while (*ie == '*') PUTCHR(*ie++);
1503 while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
1504 if (c != '(') PUTCHR(' ');
1505 }
1506 else if (*ie == '(')
1507 {
1508 if (op > om && *(op - 1) == ' ') op--;
1509 PUTCHR(*ie++);
1510 while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
1511 }
1512 else if (*ie == ')')
1513 {
1514 if (op > om && *(op - 1) == '(')
1515 proto_error((char*)proto + sizeof(Proto_t), 1, "function pointer argument prototype omitted", NiL);
1516 PUTCHR(*ie++);
1517 while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
1518 }
1519 else if ((flags & EXTERN) && (op == om || *(op - 1) == ' ') && *ie == 'r' && !strncmp(ie, "register", 8) && (*(ie + 8) == ' ' || *(ie + 8) == '\t' || *(ie + 8) == '\n'))
1520 {
1521 ie += 8;
1522 if (op > om) UNPUTCHR();
1523 }
1524 else PUTCHR(*ie++);
1525 }
1526 /*...INDENT*/
1527 if (op <= om) op = strcopy(op, "void");
1528 PUTCHR(')');
1529 if (flags & EXTERN)
1530 {
1531 PUTCHR(';');
1532 PUTCHR('\n');
1533 SYNCOUT();
1534 KEEPOUT();
1535 }
1536 else
1537 {
1538 PUTCHR('\n');
1539 PUTCHR(*ip);
1540 }
1541 ip++;
1542 flags &= ~(MATCH|SKIP);
1543 }
1544 }
1545 #endif
1546 else if ((flags & (MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS))
1547 {
1548 line = proto->line;
1549 op = strcopy(om, " __PARAM__(");
1550 op = memcopy(op, im, ie - im);
1551 PUTCHR(',');
1552 PUTCHR(' ');
1553 PUTCHR('(');
1554 flags &= ~(MATCH|SKIP);
1555 if (flags & VARIADIC)
1556 {
1557 if ((vc = ie - im + 1) > sizeof(proto->variadic)) vc = sizeof(proto->variadic);
1558 memcopy(proto->variadic, im, vc);
1559 op = strcopy(op, "va_alist)) __OTORP__(va_dcl)\n{");
1560 }
1561 else
1562 {
1563 flags |= SKIP;
1564 proto->ip = im;
1565 proto->op = op;
1566 group = 0;
1567 brack = 0;
1568 for (;;)
1569 {
1570 switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
1571 {
1572 case '[':
1573 brack++;
1574 continue;
1575 case ']':
1576 brack--;
1577 continue;
1578 case '(':
1579 if (paren++) group++;
1580 continue;
1581 case ')':
1582 if (--paren == 0)
1583 {
1584 group = 0;
1585 if (flags & MATCH)
1586 {
1587 flags &= ~(MATCH|SKIP);
1588 op = memcopy(op, m, e - m);
1589 }
1590 break;
1591 }
1592 continue;
1593 case ',':
1594 if (paren == 1)
1595 {
1596 group = 0;
1597 if (flags & MATCH)
1598 {
1599 flags &= ~(MATCH|SKIP);
1600 op = memcopy(op, m, e - m);
1601 }
1602 PUTCHR(',');
1603 PUTCHR(' ');
1604 proto->op = op;
1605 }
1606 continue;
1607 case T_ID:
1608 if (group <= 1 && !brack)
1609 {
1610 flags |= MATCH;
1611 m = proto->tp;
1612 e = proto->ip;
1613 }
1614 continue;
1615 default:
1616 continue;
1617 }
1618 break;
1619 }
1620 PUTCHR(')');
1621 PUTCHR(')');
1622 }
1623 if (!(flags & SKIP))
1624 {
1625 flags |= SKIP;
1626 proto->op = strcopy(op, " __OTORP__(");
1627 proto->ip = im + 1;
1628 n = *(ie - 1);
1629 *(ie - 1) = ';';
1630 c = *ie;
1631 *ie = 0;
1632 lex(proto, (flags & GLOBAL) | DECLARE);
1633 *(ie - 1) = n;
1634 *ie = c;
1635 proto->ip = ie;
1636 op = proto->op;
1637 PUTCHR(')');
1638 }
1639 if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
1640 op = linesync(proto, op, proto->line = line);
1641 if (flags & DIRECTIVE)
1642 {
1643 proto->brace = 0;
1644 PUTCHR('\n');
1645 PUTCHR('#');
1646 }
1647 else if (!(flags & VARIADIC)) PUTCHR('{');
1648 }
1649 }
1650 flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
1651 call = 0;
1652 group = 0;
1653 break;
1654 case '}':
1655 flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP|TOKENS);
1656 if (--proto->brace == 0)
1657 {
1658 flags &= ~(INIT|VARIADIC|VARIADIC2);
1659 #if PROTOMAIN
1660 if (flags & EXTERN) BACKOUT();
1661 #endif
1662 }
1663 call = 0;
1664 group = 0;
1665 paren = 0;
1666 break;
1667 case '=':
1668 if (last == '?') flags |= DIRECTIVE;
1669 else if (paren == 0 && (flags & (INIT|MATCH|SKIP)) == MATCH)
1670 {
1671 if (last == ')' && proto->brace && (group != 2 || call != 2)) flags |= SKIP;
1672 else goto fsm_statement;
1673 }
1674 goto fsm_other;
1675 case ',':
1676 #if PROTOMAIN
1677 if (flags & CLASSIC)
1678 {
1679 if (paren == 1) args++;
1680 else
1681 {
1682 args--;
1683 flags &= ~MATCH;
1684 }
1685 break;
1686 }
1687 #endif
1688 if (paren == 0 && (flags & DECLARE)) *(op - 1) = c = ';';
1689 /*FALLTHROUGH*/
1690 case ';':
1691 fsm_statement:
1692 if (flags & INIT) /* ignore */;
1693 #if PROTOMAIN
1694 else if (flags & CLASSIC)
1695 {
1696 if (paren == 0)
1697 {
1698 if ((flags & MATCH) && last == ')')
1699 flags &= ~MATCH;
1700 if (!(flags & MATCH))
1701 {
1702 call = 0;
1703 group = 0;
1704 flags &= ~SKIP;
1705 if (flags & EXTERN) BACKOUT();
1706 if (flags & SLIDE)
1707 {
1708 SYNC();
1709 return 0;
1710 }
1711 }
1712 else
1713 {
1714 args--;
1715 if ((flags & (EXTERN|SKIP)) == (EXTERN|SKIP))
1716 BACKOUT();
1717 }
1718 }
1719 }
1720 #endif
1721 else if (paren == 0)
1722 {
1723 if ((flags & (MATCH|OTHER|SKIP)) == MATCH && call > 1)
1724 {
1725 if ((flags & MANGLE) && func)
1726 {
1727 func[0] = 'F';
1728 func[1] = 'U';
1729 func[2] = 'N';
1730 func[3] = 'C';
1731 func = 0;
1732 }
1733 if ((flags & (DECLARE|INDIRECT)) == INDIRECT && aim && aie < im)
1734 {
1735 while (aie < ip && (*aie == ' ' || *aie == '\t' || *aie == '\n')) aie++;
1736 v = aim;
1737 while (v < aie)
1738 if (*v++ == ')') break;
1739 while (v < aie && (*v == ' ' || *v == '\t' || *v == '\n')) v++;
1740 if (v == aie || !(flags & PLUSPLUS))
1741 {
1742 if (flags & PLUSPLUS) n = 3;
1743 else if (v == aie && *v == '(') n = 10;
1744 else n = 11;
1745 ko = op;
1746 om += n;
1747 v = op += n;
1748 while (v >= ko + n)
1749 {
1750 *v = *(v - n);
1751 v--;
1752 }
1753 if (flags & PLUSPLUS) memcopy(aom, "(...))", 6);
1754 else if (n == 10) memcopy(aom, "(__VARARG__))", 13);
1755 else
1756 {
1757 ko = strcopy(aom, " __PROTO__(");
1758 ko = memcopy(ko, aim, aie - aim);
1759 *ko = ')';
1760 if (++ko >= om)
1761 {
1762 *ko++ = ')';
1763 om = ko;
1764 }
1765 }
1766 }
1767 }
1768 else if (flags & TYPEDEF)
1769 {
1770 op = om;
1771 while (*--op == ' ' || *op == '\t' || *op == '\n');
1772 if (*op != ')')
1773 {
1774 op = om += 14;
1775 *--op = ')';
1776 while ((x = *(op - 14)) >= 'A' && x <= 'Z' || x >= 'a' && x <= 'z' || x >= '0' && x <= '9' || x == '_')
1777 *--op = x;
1778 memcopy(op - 13, "(__OTORP__(*)", 13);
1779 }
1780 }
1781 if (flags & OTHER)
1782 ;
1783 else if (flags & PLUSPLUS)
1784 {
1785 op = om;
1786 if (!(flags & TOKENS)) op = strcopy(op, "(...)");
1787 else op = memcopy(op, im, ie - im);
1788 PUTCHR(c);
1789 }
1790 else
1791 {
1792 if (flags & DECLARE) op = strcopy(om, "()");
1793 else if (!(flags & TOKENS)) op = strcopy(om, "(__VARARG__)");
1794 else
1795 {
1796 op = strcopy(om, " __PROTO__(");
1797 op = memcopy(op, im, ie - im);
1798 PUTCHR(')');
1799 }
1800 if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
1801 PUTCHR(c);
1802 }
1803 flags &= ~(MATCH|VARIADIC|VARIADIC2);
1804 if (c == ',' && !(flags & INDIRECT))
1805 {
1806 call = 1;
1807 group = 0;
1808 break;
1809 }
1810 }
1811 else if (flags & (OTHER|SKIP)) call = 0;
1812 if (c == ';')
1813 {
1814 flags &= ~(EXTERNALIZE|MANGLE|TOKENS|TYPEDEF);
1815 call = 0;
1816 if (flags & SLIDE)
1817 {
1818 SYNC();
1819 return 0;
1820 }
1821 }
1822 else call = call > 1 && c == ',';
1823 group = 0;
1824 flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
1825 }
1826 else if (paren == 1 && group == 1 && !(flags & (IDID|MANGLE))) flags |= TOKENS|OTHER;
1827 break;
1828 case T_DO:
1829 case T_IF:
1830 flags |= TOKENS|SKIP;
1831 break;
1832 case T_EXTERN:
1833 #if PROTOMAIN
1834 if (flags & CLASSIC)
1835 {
1836 if (proto->brace == 0)
1837 flags |= SKIP;
1838 }
1839 else
1840 #endif
1841 if (paren == 0 && !(flags & TYPEDEF))
1842 {
1843 flags |= MANGLE;
1844 if (!(flags & PLUSONLY) || proto->package)
1845 {
1846 op = strcopy(op, " __MANGLE__");
1847 if (proto->package)
1848 {
1849 op = strcopy(op - 1, proto->package);
1850 func = op + 1;
1851 op = strcopy(op, "_DATA__");
1852 }
1853 }
1854 else
1855 func = 0;
1856 }
1857 break;
1858 case T_VARIADIC:
1859 if (paren == 0 && (flags & (DECLARE|VARIADIC)) == DECLARE)
1860 {
1861 op -= 3;
1862 SYNC();
1863 return c;
1864 }
1865 if (paren == 1 && !(flags & SKIP))
1866 flags |= VARIADIC;
1867 flags |= TOKENS;
1868 break;
1869 case T_VOID:
1870 goto fsm_id;
1871 case T_VA_START:
1872 if ((flags & (PLUSONLY|VARIADIC)) == VARIADIC)
1873 {
1874 flags &= ~MATCH;
1875 line = proto->line;
1876 op = strcopy(op - 8, "__VA_START__");
1877 SYNC();
1878 for (;;)
1879 {
1880 switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
1881 {
1882 case 0:
1883 case ';':
1884 break;
1885 case T_ID:
1886 if (!(flags & MATCH))
1887 {
1888 flags |= MATCH;
1889 m = proto->tp;
1890 e = proto->ip;
1891 }
1892 continue;
1893 default:
1894 continue;
1895 }
1896 break;
1897 }
1898 CACHE();
1899 if (flags & MATCH)
1900 {
1901 v = m;
1902 n = e - m;
1903 }
1904 else
1905 {
1906 v = "ap";
1907 n = 2;
1908 }
1909 op = strcopy(op, " __OTORP__(");
1910 proto->ip = proto->variadic;
1911 proto->op = op;
1912 flags &= ~MATCH;
1913 group = 0;
1914 bp = proto->ip + 1;
1915 if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
1916 for (;;)
1917 {
1918 switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
1919 {
1920 case '(':
1921 if (paren++) group++;
1922 continue;
1923 case ')':
1924 if (--paren == 0)
1925 {
1926 if (flags & MATCH)
1927 {
1928 flags &= ~MATCH;
1929 if (!(flags & VARIADIC2))
1930 {
1931 op = memcopy(op, m, e - m);
1932 op = strcopy(op, " = ");
1933 }
1934 op = strcopy(op, "va_arg(");
1935 op = memcopy(op, v, n);
1936 PUTCHR(',');
1937 PUTCHR(' ');
1938 if (m > bp) op = memcopy(op, bp, m - bp);
1939 else op = strcopy(op, "int ");
1940 if (group > 1) op = strcopy(op, ")()");
1941 else op = memcopy(op, e, proto->ip - e - 1);
1942 PUTCHR(')');
1943 PUTCHR(';');
1944 }
1945 group = 0;
1946 break;
1947 }
1948 continue;
1949 case ',':
1950 if (paren == 1)
1951 {
1952 if (flags & MATCH)
1953 {
1954 flags &= ~MATCH;
1955 if (!(flags & VARIADIC2))
1956 {
1957 op = memcopy(op, m, e - m);
1958 op = strcopy(op, " = ");
1959 }
1960 op = strcopy(op, "va_arg(");
1961 op = memcopy(op, v, n);
1962 PUTCHR(',');
1963 PUTCHR(' ');
1964 if (m > bp) op = memcopy(op, bp, m - bp);
1965 else op = strcopy(op, "int ");
1966 if (group > 1) op = strcopy(op, ")()");
1967 else op = memcopy(op, e, proto->ip - e - 1);
1968 PUTCHR(')');
1969 PUTCHR(';');
1970 bp = proto->ip + 1;
1971 if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
1972 }
1973 group = 0;
1974 proto->op = op;
1975 }
1976 continue;
1977 case T_ID:
1978 if (group <= 1)
1979 {
1980 flags |= MATCH;
1981 m = proto->tp;
1982 e = proto->ip;
1983 }
1984 continue;
1985 default:
1986 continue;
1987 }
1988 break;
1989 }
1990 op = strcopy(op, ")");
1991 flags |= VARIADIC2;
1992 proto->line = line;
1993 call = 0;
1994 break;
1995 }
1996 /*FALLTHROUGH*/
1997 case T_ID:
1998 fsm_id:
1999 #if PROTOMAIN
2000 if (flags & CLASSIC)
2001 {
2002 if (!args && paren == 1) args++;
2003 break;
2004 }
2005 #endif
2006 if (paren == 0)
2007 {
2008 if (last == ')')
2009 {
2010 if (proto->brace == 0 && !(flags & DECLARE)) flags |= SKIP;
2011 call = !call;
2012 }
2013 else if ((flags & SKIP) || c == T_ID || c == T_VOID) call++;
2014 else flags |= SKIP;
2015 if (last == T_ID) flags |= IDID;
2016 }
2017 c = T_ID;
2018 flags |= TOKENS;
2019 break;
2020 case T_INVALID:
2021 if (*proto->tp >= '0' && *proto->tp <= '9')
2022 {
2023 n = 0;
2024 for (;; op--)
2025 {
2026 switch (*(op - 1))
2027 {
2028 case 'f':
2029 case 'F':
2030 t = op;
2031 while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
2032 if (*t == '.')
2033 op--;
2034 n = 0;
2035 break;
2036 case 'l':
2037 case 'L':
2038 if (!(n & 01))
2039 {
2040 n |= 01;
2041 t = op;
2042 while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
2043 if (*t == '.')
2044 {
2045 n = 0;
2046 op--;
2047 break;
2048 }
2049 }
2050 continue;
2051 case 'u':
2052 case 'U':
2053 n |= 02;
2054 continue;
2055 }
2056 break;
2057 }
2058 if (n & 01)
2059 *op++ = 'L';
2060 if (n & 02)
2061 {
2062 m = op;
2063 t = op = m + 10;
2064 while ((c = *--m) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
2065 *--t = c;
2066 c = *t;
2067 strcopy(m + 1, "(unsigned)");
2068 *t = c;
2069 break;
2070 }
2071 }
2072 goto fsm_other;
2073 #if PROTOMAIN
2074 case '[':
2075 if ((flags & CLASSIC) && paren == 0 && group <= 2) flags |= SKIP;
2076 /*FALLTHROUGH*/
2077 #endif
2078 default:
2079 fsm_other:
2080 #if PROTOMAIN
2081 if (flags & CLASSIC) break;
2082 #endif
2083 flags |= TOKENS;
2084 if (paren == 0) flags |= OTHER;
2085 break;
2086 }
2087 else if (c == '#' && *ip != '(') flags |= SHARP;
2088 last = c;
2089 #if PROTOMAIN
2090 if ((flags & (EXTERN|MATCH)) == (EXTERN|MATCH) && ((flags & (DIRECTIVE|SKIP)) || proto->brace || c != '(' && c != ')' && c != '*' && c != T_ID))
2091 CACHEOUT();
2092 else
2093 #endif
2094 SYNCOUT();
2095 goto fsm_start;
2096 }
2097 else if (flags & (INIT_DEFINE|INIT_INCLUDE))
2098 {
2099 #if PROTOMAIN
2100 if ((flags & YACC) && c == '%' && *ip == '{')
2101 t = 0;
2102 else
2103 #endif
2104 {
2105 if (c == '#')
2106 {
2107 for (t = ip; *t == ' ' || *t == '\t'; t++);
2108 if (*t++ == 'i' && *t++ == 'f' && *t++ == 'n' && *t++ == 'd' && *t++ == 'e' && *t++ == 'f')
2109 {
2110 #if !PROTOMAIN
2111 while (*t == ' ' || *t == '\t') t++;
2112 if (*t != '_')
2113 #endif
2114 t = 0;
2115 }
2116 }
2117 else
2118 t = "";
2119 }
2120 if (t)
2121 {
2122 #if PROTOMAIN
2123 n = ip - proto->tp;
2124 ip -= n;
2125 op -= n;
2126 #else
2127 ip = bp;
2128 op = proto->op;
2129 #endif
2130 }
2131 else
2132 while (*ip != '\n')
2133 *op++ = *ip++;
2134 op = init(proto, op, flags);
2135 op = linesync(proto, op, proto->line);
2136 flags &= ~(INIT_DEFINE|INIT_INCLUDE);
2137 proto->flags &= ~(INIT_DEFINE|INIT_INCLUDE);
2138 goto fsm_start;
2139 }
2140 SYNC();
2141 return c;
2142 }
2143
2144 /*
2145 * close a proto buffer stream
2146 */
2147
2148 void
pppclose(char * iob)2149 pppclose(char* iob)
2150 {
2151 register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
2152
2153 if (proto->flags & MORE) close(proto->fd);
2154 free((char*)proto); /* some ANSI cc's botch the free() prototype */
2155 }
2156
2157 /*
2158 * open a new proto buffer stream
2159 * read buffer pointer returned
2160 * 0 returned on error or if no magic
2161 *
2162 * file !=0 file path to open, otherwise use fd
2163 * fd open file fd if file==0
2164 * notice !=0 copyright notice info commented at the top
2165 * options !=0 additional notice name=value pairs, space or ; separated
2166 * package !=0 generate header for this package
2167 */
2168
2169 char*
pppopen(char * file,int fd,char * notice,char * options,char * package,char * comment,int flags)2170 pppopen(char* file, int fd, char* notice, char* options, char* package, char* comment, int flags)
2171 {
2172 register Proto_t* proto;
2173 register char* iob;
2174 register long n;
2175 register char* s;
2176 char* t;
2177 int pragma;
2178 int clr;
2179 int hit;
2180 int i;
2181 int z;
2182 char* b;
2183 #if PROTOMAIN
2184 int comlen;
2185 char com[80];
2186 #endif
2187 int m = 0;
2188
2189 static int retain;
2190
2191 /*
2192 * initialize proto
2193 */
2194
2195 #if PROTOMAIN
2196 if (flags & PROTO_CLASSIC) flags &= ~PROTO_INCLUDE;
2197 #endif
2198 if (flags & PROTO_RETAIN) flags &= ~retain;
2199 else retain &= PROTO_INITIALIZED;
2200 if (file && (fd = open(file, O_RDONLY)) < 0) return 0;
2201 #if !PROTOMAIN
2202 if ((n = lseek(fd, 0L, 2)) > 0)
2203 {
2204 if (lseek(fd, 0L, 0)) return 0;
2205 if (n < CHUNK) n = CHUNK;
2206 else if (n > 2 * BLOCK) n = 0;
2207 m = 1;
2208 }
2209 if (n > 0)
2210 {
2211 /*
2212 * file read in one chunk
2213 */
2214
2215 if (!(proto = newof(0, Proto_t, 1, 4 * n + 2)))
2216 return 0;
2217 proto->iz = n;
2218 proto->oz = 3 * n;
2219 n = 0;
2220 }
2221 else
2222 #endif
2223 {
2224 /*
2225 * file read in BLOCK chunks
2226 */
2227
2228 n = BLOCK;
2229 if (!(proto = newof(0, Proto_t, 1, 5 * n + 2)))
2230 return 0;
2231 proto->iz = n;
2232 proto->oz = 3 * n;
2233 proto->flags |= MORE;
2234 }
2235 proto->fd = fd;
2236 proto->package = package;
2237 iob = (char*)proto + sizeof(Proto_t);
2238 proto->op = proto->ob = iob;
2239 proto->ip = proto->ib = iob + proto->oz + n;
2240 if (m) proto->options |= REGULAR;
2241 if (!comment)
2242 comment = "/*";
2243 if (!(proto->cc[0] = comment[0]))
2244 notice = options = 0;
2245 else if (comment[1])
2246 {
2247 proto->cc[1] = comment[1];
2248 proto->cc[2] = comment[2] ? comment[2] : comment[0];
2249 }
2250 else
2251 proto->cc[1] = proto->cc[2] = comment[0];
2252
2253 /*
2254 * read the first chunk
2255 */
2256
2257 n = read(fd, proto->ip, proto->iz);
2258 if (!(proto->flags & MORE))
2259 close(fd);
2260 if (n < 0)
2261 {
2262 pppclose(iob);
2263 return 0;
2264 }
2265 *(proto->ip + n) = 0;
2266
2267 /*
2268 * check for proto pragma in first block of lines
2269 * pragma blanked out if found
2270 *
2271 * -1 no pragma
2272 * 0 #pragma noprototyped
2273 * 1 #pragma prototyped
2274 *
2275 * NOTE: matches may occur inside comments and quotes
2276 */
2277
2278 #if PROTOMAIN
2279 if (!notice && !options || (comlen = astlicense(com, sizeof(com), NiL, "type=check", proto->cc[0], proto->cc[1], proto->cc[2])) <= 0)
2280 *com = 0;
2281 #endif
2282 hit = (notice || options) ? 0 : HIT_noticed;
2283 pragma = -1;
2284 s = proto->ip;
2285 m = MAGICTOP;
2286 while (m-- > 0 && *s && hit != (HIT_prototyped|HIT_noticed))
2287 {
2288 while (*s == ' ' || *s == '\t')
2289 s++;
2290 if (*s == '#')
2291 {
2292 b = s++;
2293 while (*s == ' ' || *s == '\t')
2294 s++;
2295 if (*s == *PRAGMADIR && !strncmp(s, PRAGMADIR, sizeof(PRAGMADIR) - 1) && (*(s += sizeof(PRAGMADIR) - 1) == ' ' || *s == '\t'))
2296 {
2297 clr = 0;
2298 while (*s && *s != '\r' && *s != '\n')
2299 {
2300 for (; *s == ' ' || *s == '\t'; s++);
2301 for (t = s; *s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n'; s++);
2302 z = s - t;
2303 for (i = 0; i < elementsof(pragmas); i++)
2304 if (pragmas[i].size == z && !strncmp(t, pragmas[i].name, z))
2305 {
2306 clr = 1;
2307 hit |= pragmas[i].hit;
2308 switch (pragmas[i].hit)
2309 {
2310 case HIT_noticed:
2311 notice = options = 0;
2312 break;
2313 case HIT_prototyped:
2314 pragma = pragmas[i].val;
2315 break;
2316 }
2317 }
2318 }
2319 if (clr)
2320 {
2321 #if PROTOMAIN
2322 if (!(flags & PROTO_DISABLE) || (flags & PROTO_NOPRAGMA))
2323 #endif
2324 for (; b < s; *b++ = ' ');
2325 }
2326 }
2327 }
2328 else if (*s == *GENERATED && !strncmp(s, GENERATED, sizeof(GENERATED) - 1))
2329 {
2330 pragma = 0;
2331 break;
2332 }
2333 #if PROTOMAIN
2334 else if (*s == '%' && *(s + 1) == '{')
2335 proto->flags |= YACC;
2336 else if (!(hit & HIT_noticed))
2337 {
2338 if (*s == *com && !strncmp(s, com, comlen))
2339 {
2340 hit |= HIT_noticed;
2341 notice = options = 0;
2342 }
2343 else
2344 for (; *s && *s != '\n' && !(hit & HIT_noticed); s++)
2345 for (i = 0; i < elementsof(notices); i++)
2346 if (*s == notices[i].name[0] && !strncmp(s, notices[i].name, notices[i].size))
2347 {
2348 s += notices[i].size;
2349 if (notices[i].val)
2350 {
2351 while (*s == ' ' || *s == '\t')
2352 s++;
2353 if (*s == '(' && (*(s + 1) == 'c' || *(s + 1) == 'C') && *(s + 2) == ')' || *s >= '0' && *s <= '9' && *(s + 1) >= '0' && *(s + 1) <= '9')
2354 {
2355 hit |= notices[i].hit;
2356 notice = options = 0;
2357 }
2358 }
2359 else
2360 {
2361 hit |= notices[i].hit;
2362 notice = options = 0;
2363 }
2364 break;
2365 }
2366 }
2367 #endif
2368 while (*s && *s++ != '\n');
2369 }
2370 if (flags & PROTO_PLUSPLUS) proto->flags |= PLUSPLUS;
2371 if (flags & PROTO_TEST) proto->test = 1;
2372 if (flags & PROTO_EXTERNALIZE) proto->options |= EXTERNALIZE;
2373 #if PROTOMAIN
2374 if (flags & PROTO_CLASSIC) pragma = -pragma;
2375 if (flags & PROTO_DISABLE) pragma = 0;
2376 if (flags & PROTO_LINESYNC) proto->flags |= LINESYNC;
2377 if (!(proto->flags & YACC) && file && (m = strlen(file)) > 2 && file[--m] == 'y' && file[--m] == '.')
2378 proto->flags |= YACC;
2379 #endif
2380 if (pragma <= 0)
2381 {
2382 if (flags & PROTO_PLUSPLUS)
2383 {
2384 flags &= ~(PROTO_HEADER|PROTO_INCLUDE);
2385 proto->flags |= PLUSONLY;
2386 }
2387 else if (!(flags & (PROTO_FORCE|PROTO_PASS)))
2388 {
2389 pppclose(iob);
2390 return 0;
2391 }
2392 else if ((flags & (PROTO_FORCE|PROTO_PASS)) == PROTO_PASS || !pragma)
2393 {
2394 proto->flags |= PASS;
2395 if (proto->flags & MORE)
2396 proto->oz += proto->iz;
2397 proto->iz = n;
2398 if (notice || options)
2399 {
2400 if (proto->cc[0] == '#' && proto->ip[0] == '#' && proto->ip[1] == '!')
2401 {
2402 s = proto->ip;
2403 while (*s && *s++ != '\n');
2404 m = s - proto->ip;
2405 proto->op = memcopy(proto->op, proto->ip, m);
2406 proto->ip = s;
2407 proto->iz = n -= m;
2408 }
2409 #if PROTOMAIN
2410 if (proto->cc[0])
2411 {
2412 if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
2413 proto_error((char*)proto + sizeof(Proto_t), 1, proto->op, NiL);
2414 else
2415 proto->op += comlen;
2416 }
2417 if (!(flags & PROTO_CLASSIC) && !(proto->flags & YACC))
2418 #endif
2419 proto->op = linesync(proto, proto->op, 1);
2420 proto->iz += proto->op - proto->ob;
2421 }
2422 memcopy(proto->op, proto->ip, n);
2423 return iob;
2424 }
2425 }
2426 #if PROTOMAIN
2427 if (!(retain & PROTO_INITIALIZED))
2428 {
2429 retain |= PROTO_INITIALIZED;
2430 ppfsm(FSM_INIT, NiL);
2431 }
2432 #endif
2433 proto->line = 1;
2434 #if CHUNK >= 512
2435 if (notice || options || (flags & (PROTO_HEADER|PROTO_INCLUDE)))
2436 {
2437 #if PROTOMAIN
2438 if (notice || options)
2439 {
2440 if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
2441 proto_error((char*)proto + sizeof(Proto_t), 1, proto->op, NiL);
2442 else
2443 proto->op += comlen;
2444 }
2445 #endif
2446 if (flags & PROTO_INCLUDE)
2447 {
2448 proto->flags |= INIT_INCLUDE;
2449 if (flags & PROTO_RETAIN)
2450 retain |= PROTO_INCLUDE;
2451 }
2452 else if (flags & PROTO_HEADER)
2453 {
2454 if (flags & PROTO_RETAIN) retain |= PROTO_HEADER;
2455 #if PROTOMAIN
2456 if (flags & PROTO_CLASSIC)
2457 {
2458 *proto->op++ = '#';
2459 proto->op = strcopy(proto->op, PRAGMADIR);
2460 *proto->op++ = ' ';
2461 proto->op = strcopy(proto->op, pragmas[0].name);
2462 *proto->op++ = '\n';
2463 }
2464 else
2465 #endif
2466 proto->flags |= INIT_DEFINE;
2467 }
2468 #if PROTOMAIN
2469 if (!(flags & PROTO_CLASSIC))
2470 {
2471 if (proto->flags & YACC)
2472 {
2473 proto->op = strcopy(proto->op, "\n%{\n" + !notice);
2474 proto->op = strcopy(proto->op, GENERATED);
2475 proto->op = strcopy(proto->op, "%}\n");
2476 }
2477 else
2478 {
2479 if (n || notice || options)
2480 *proto->op++ = '\n';
2481 proto->op = strcopy(proto->op, GENERATED);
2482 if (n)
2483 proto->op = linesync(proto, proto->op, proto->line);
2484 else if (proto->flags & (INIT_DEFINE|INIT_INCLUDE))
2485 proto->op = init(proto, proto->op, proto->flags);
2486 }
2487 }
2488 #endif
2489 }
2490 #endif
2491 #if PROTOMAIN
2492 proto->file = file;
2493 if (flags & PROTO_CLASSIC)
2494 {
2495 proto->flags |= CLASSIC;
2496 if (!(flags & PROTO_HEADER)) proto->flags |= EXTERN;
2497 }
2498 #endif
2499 return iob;
2500 }
2501
2502 /*
2503 * read next proto'd chunk into iob
2504 * the chunk is 0 terminated and its size is returned
2505 */
2506
2507 int
pppread(char * iob)2508 pppread(char* iob)
2509 {
2510 register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
2511 register int n;
2512
2513 if (proto->flags & PASS)
2514 {
2515 if (proto->iz)
2516 {
2517 n = proto->iz;
2518 proto->iz = 0;
2519 }
2520 else if (!(proto->flags & MORE)) n = 0;
2521 else if ((n = read(proto->fd, proto->ob, proto->oz)) <= 0 || (proto->options & REGULAR) && n < proto->oz)
2522 {
2523 proto->flags &= ~MORE;
2524 close(proto->fd);
2525 }
2526 }
2527 else
2528 {
2529 if (proto->op == proto->ob)
2530 {
2531 if (proto->flags & ERROR) return -1;
2532 #if PROTOMAIN
2533 if (proto->flags & YACC)
2534 {
2535 register char* ip = proto->ip;
2536 register char* op = proto->ob;
2537 register char* ep = proto->ob + proto->oz - 2;
2538
2539 if (!*ip)
2540 {
2541 ip = proto->ip = proto->ib;
2542 if (!(proto->flags & MORE)) n = 0;
2543 else if ((n = read(proto->fd, ip, proto->iz)) <= 0 || (proto->options & REGULAR) && n < proto->iz)
2544 {
2545 if (n < 0) n = 0;
2546 proto->flags &= ~MORE;
2547 close(proto->fd);
2548 }
2549 ip[n] = 0;
2550 }
2551 if (proto->flags & YACCSPLIT)
2552 {
2553 proto->flags &= ~YACCSPLIT;
2554 if (*ip == '%')
2555 {
2556 *op++ = *ip++;
2557 if (proto->flags & YACC2) proto->flags &= ~YACC;
2558 else proto->flags |= YACC2;
2559 }
2560 }
2561 if (proto->flags & YACC)
2562 while (op < ep && (n = *op++ = *ip))
2563 {
2564 ip++;
2565 if (n == '%')
2566 {
2567 if (*ip == '%' && (ip == proto->ip + 1 || *(ip - 2) == '\n'))
2568 {
2569 *op++ = *ip++;
2570 if (proto->flags & YACC2) proto->flags &= ~YACC;
2571 else proto->flags |= YACC2;
2572 break;
2573 }
2574 if (!*ip)
2575 {
2576 *op++ = '%';
2577 proto->flags |= YACCSPLIT;
2578 break;
2579 }
2580 }
2581 else if (n == '\n') proto->line++;
2582 }
2583 proto->op = memcopy(proto->ob, proto->ip, ip - proto->ip);
2584 proto->ip = ip;
2585 }
2586 else
2587 #endif
2588 lex(proto, proto->flags);
2589 if ((proto->flags & (ERROR|MORE)) == ERROR)
2590 proto->op = strcopy(proto->op, "/* NOTE: some constructs may not have been converted */\n");
2591 }
2592 n = proto->op - proto->ob;
2593 proto->op = proto->ob;
2594 }
2595 return n;
2596 }
2597
2598 #if !PROTOMAIN
2599
2600 /*
2601 * drop control of iob after first pppread()
2602 * return value is input fd
2603 * if fd<0 then all data in iob
2604 */
2605
2606 int
pppdrop(char * iob)2607 pppdrop(char* iob)
2608 {
2609 register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
2610
2611 if (proto->flags & MORE)
2612 {
2613 proto->flags &= ~MORE;
2614 return proto->fd;
2615 }
2616 return -1;
2617 }
2618
2619 #endif
2620