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