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