8834 libpp: 'id' defined but not used
[unleashed.git] / usr / src / lib / libpp / common / ppproto.c
blob2a197b231a464e533cb413f284336cefb1da834b
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
22 * Glenn Fowler
23 * AT&T Research
25 * convert C prototypes to ANSI, K&R and C++ styles or K&R to ANSI
26 * slips into the pp block read
28 * define PROTOMAIN for standalone proto
29 * PROTOMAIN is coded for minimal library support
32 #if PROTOMAIN
34 #include "ppfsm.c"
36 #include <hashkey.h>
38 #if PROTO_STANDALONE
39 #undef O_RDONLY
40 #endif
42 #else
44 #include "pplib.h"
45 #include "ppfsm.h"
47 #endif
49 #define MAGICGEN "/* : : generated by proto : : */\n"
51 #define MAGICDIR "pragma" /* proto magic directive */
52 #define MAGICARG "prototyped" /* proto magic directive arg */
53 #define MAGICOFF "noticed" /* no notice if found in pragma */
54 #define MAGICTOP 64 /* must be in these top lines */
55 #define NOTICED "Copyright" /* no notice if found in magic */
56 #define PUBLICDOMAIN "Public Domain" /* no notice if found in magic */
58 struct proto /* proto buffer state */
60 int brace; /* {..} level */
61 int call; /* call level */
62 int fd; /* input file descriptor */
63 char* file; /* input file name */
64 long flags; /* coupled flags */
65 long options; /* uncoupled flags */
66 char* package; /* header package */
67 int line; /* input line count */
68 int test; /* testing */
70 char* tp; /* input token base */
72 int iz; /* input buffer size */
73 char* ib; /* input buffer base */
74 char* ip; /* input buffer pointer */
76 int oz; /* output buffer size */
77 char* ob; /* output buffer base */
78 char* op; /* output buffer pointer */
79 char* ox; /* output buffer externalize */
81 char cc[3]; /* beg mid end comment char */
82 char pushback[4]; /* pushback area for caller */
84 char variadic[256]; /* variadic args buffer */
86 /* output buffer */
87 /* slide buffer */
88 /* input buffer */
92 * proto is separate from pp so these undef's are ok
95 #undef CLASSIC
96 #define CLASSIC (1L<<0)
97 #undef DECLARE
98 #define DECLARE (1L<<1)
99 #undef DEFINE
100 #define DEFINE (1L<<2)
101 #undef DIRECTIVE
102 #define DIRECTIVE (1L<<3)
103 #undef ERROR
104 #define ERROR (1L<<4)
105 #undef EXTERN
106 #define EXTERN (1L<<5)
107 #undef EXTERNALIZE
108 #define EXTERNALIZE (1L<<6)
109 #undef IDID
110 #define IDID (1L<<7)
111 #undef INDIRECT
112 #define INDIRECT (1L<<8)
113 #undef INIT
114 #define INIT (1L<<9)
115 #undef INIT_DEFINE
116 #define INIT_DEFINE (1L<<10)
117 #undef INIT_INCLUDE
118 #define INIT_INCLUDE (1L<<11)
119 #undef JUNK
120 #define JUNK (1L<<12)
121 #undef LINESYNC
122 #define LINESYNC (1L<<13)
123 #undef MANGLE
124 #define MANGLE (1L<<14)
125 #undef MATCH
126 #define MATCH (1L<<15)
127 #undef MORE
128 #define MORE (1L<<16)
129 #undef OTHER
130 #define OTHER (1L<<17)
131 #undef PASS
132 #define PASS (1L<<18)
133 #undef PLUSONLY
134 #define PLUSONLY (1L<<19)
135 #undef PLUSPLUS
136 #define PLUSPLUS (1L<<20)
137 #undef RECURSIVE
138 #define RECURSIVE (1L<<21)
139 #undef SHARP
140 #define SHARP (1L<<22)
141 #undef SKIP
142 #define SKIP (1L<<23)
143 #undef SLIDE
144 #define SLIDE (1L<<24)
145 #undef TOKENS
146 #define TOKENS (1L<<25)
147 #undef TYPEDEF
148 #define TYPEDEF (1L<<26)
149 #undef VARIADIC
150 #define VARIADIC (1L<<27)
151 #undef VARIADIC2
152 #define VARIADIC2 (1L<<28)
153 #undef YACC
154 #define YACC (1L<<29)
155 #undef YACCSPLIT
156 #define YACCSPLIT (1L<<30)
157 #undef YACC2
158 #define YACC2 (1L<<31)
160 #undef GLOBAL
161 #define GLOBAL (MORE)
163 #undef REGULAR
164 #define REGULAR (1L<<0)
166 #ifndef CHUNK
167 #define CHUNK 1024
168 #endif
169 #define BLOCK (8*CHUNK)
171 #define T_VA_START (N_TOKEN+1)
173 #define RESERVED(b,e,n) ((((long)(b))<<16)|(((long)(e))<<8)|((long)(n)))
176 * generate integer
177 * pointer to end returned
180 static char*
181 number(register char* p, register long n)
183 register long d;
185 for (d = 1000000; d > 1; d /= 10)
186 if (n >= d) *p++ = '0' + (n / d) % 10;
187 *p++ = '0' + n % 10;
188 return p;
191 #if PROTOMAIN
193 static int errors;
195 #if PROTO_STANDALONE
198 * namespace pollution forces us to claim parts of libc
201 #undef memcpy
202 #define memcpy(t,f,n) memcopy(t,f,n)
203 #undef strcpy
204 #define strcpy(t,f) strcopy(t,f)
205 #undef strlen
206 #define strlen(s) sstrlen(s)
207 #undef strncmp
208 #define strncmp(s,t,n) sstrncmp(s,t,n)
211 * environmentally safe strlen()
214 static int
215 sstrlen(register const char* s)
217 register const char* b;
219 for (b = s; *s; s++);
220 return s - b;
224 * environmentally safe strncmp()
227 static int
228 sstrncmp(register const char* s, register char* t, register int n)
230 register const char* e = s + n;
232 while (s < e)
234 if (*s != *t || !*s)
235 return *s - *t;
236 s++;
237 t++;
239 return 0;
243 * strcpy() except pointer to end returned
246 static char*
247 strcopy(register char* s, register const char* t)
249 while (*s++ = *t++);
250 return s - 1;
253 #endif
255 static void
256 proto_error(char* iob, int level, char* msg, char* arg)
258 register char* p;
259 char buf[1024];
261 p = strcopy(buf, "proto: ");
262 if (iob)
264 register struct proto* proto = (struct proto*)(iob - sizeof(struct proto));
266 if (proto->line)
268 if (proto->file)
270 *p++ = '"';
271 p = strcopy(p, proto->file);
272 *p++ = '"';
273 *p++ = ',';
274 *p++ = ' ';
276 p = strcopy(p, "line ");
277 p = number(p, proto->line);
279 else if (proto->file)
280 p = strcopy(p, proto->file);
282 else
284 p = strcopy(p, msg);
285 msg = arg;
286 arg = 0;
288 if (*(p - 1) != ' ')
290 *p++ = ':';
291 *p++ = ' ';
293 if (level == 1)
294 p = strcopy(p, "warning: ");
295 p = strcopy(p, msg);
296 if (arg)
298 *p++ = ' ';
299 p = strcopy(p, arg);
301 *p++ = '\n';
302 write(2, buf, p - buf);
303 if (level >= 3)
304 exit(level - 2);
305 if (level >= 2)
306 errors++;
310 * memcpy() but pointer to end returned
313 static char*
314 memcopy(register char* s, register char* t, int n)
316 register char* e = t + n;
318 while (t < e) *s++ = *t++;
319 return s;
322 #include "../libast/port/astlicense.c"
324 #else
326 #define memcopy(s,t,n) (((char*)memcpy(s,t,n))+(n))
328 #endif
331 * generate line sync
332 * pointer to end returned
335 static char*
336 linesync(register struct proto* proto, register char* p, register long n)
338 #if PROTOMAIN
339 if (proto->flags & LINESYNC)
340 #endif
342 #if PROTOMAIN
343 p = strcopy(p, "\n#line ");
344 #else
345 p = strcopy(p, "\n# ");
346 #endif
347 p = number(p, n);
348 *p++ = '\n';
350 return p;
354 * output init header
355 * pointer to end returned
358 static char*
359 init(struct proto* proto, char* op, int flags)
361 register char* s;
363 if (flags & INIT_DEFINE)
365 op = strcopy(op, "\
367 #if !defined(__PROTO__)\n\
368 # if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\
369 # if defined(__cplusplus)\n\
370 # define __LINKAGE__ \"C\"\n\
371 # else\n\
372 # define __LINKAGE__\n\
373 # endif\n\
374 # define __STDARG__\n\
375 # define __PROTO__(x) x\n\
376 # define __OTORP__(x)\n\
377 # define __PARAM__(n,o) n\n\
378 # if !defined(__STDC__) && !defined(__cplusplus)\n\
379 # if !defined(c_plusplus)\n\
380 # define const\n\
381 # endif\n\
382 # define signed\n\
383 # define void int\n\
384 # define volatile\n\
385 # define __V_ char\n\
386 # else\n\
387 # define __V_ void\n\
388 # endif\n\
389 # else\n\
390 # define __PROTO__(x) ()\n\
391 # define __OTORP__(x) x\n\
392 # define __PARAM__(n,o) o\n\
393 # define __LINKAGE__\n\
394 # define __V_ char\n\
395 # define const\n\
396 # define signed\n\
397 # define void int\n\
398 # define volatile\n\
399 # endif\n\
400 # define __MANGLE__ __LINKAGE__\n\
401 # if defined(__cplusplus) || defined(c_plusplus)\n\
402 # define __VARARG__ ...\n\
403 # else\n\
404 # define __VARARG__\n\
405 # endif\n\
406 # if defined(__STDARG__)\n\
407 # define __VA_START__(p,a) va_start(p,a)\n\
408 # else\n\
409 # define __VA_START__(p,a) va_start(p)\n\
410 # endif\n\
411 # if !defined(__INLINE__)\n\
412 # if defined(__cplusplus)\n\
413 # define __INLINE__ extern __MANGLE__ inline\n\
414 # else\n\
415 # if defined(_WIN32) && !defined(__GNUC__)\n\
416 # define __INLINE__ __inline\n\
417 # endif\n\
418 # endif\n\
419 # endif\n\
420 #endif\n\
421 #if !defined(__LINKAGE__)\n\
422 #define __LINKAGE__ /* 2004-08-11 transition */\n\
423 #endif\n\
426 else
427 op = strcopy(op, "\
429 #if !defined(__PROTO__)\n\
430 #include <prototyped.h>\n\
431 #endif\n\
432 #if !defined(__LINKAGE__)\n\
433 #define __LINKAGE__ /* 2004-08-11 transition */\n\
434 #endif\n\
436 if (proto->package)
438 s = "\
439 #ifndef __MANGLE_%_DATA__\n\
440 # ifdef _BLD_%\n\
441 # ifdef __EXPORT__\n\
442 # define __MANGLE_%_DATA__ __MANGLE__ __EXPORT__\n\
443 # else\n\
444 # define __MANGLE_%_DATA__ __MANGLE__\n\
445 # endif\n\
446 # define __MANGLE_%_FUNC__ __MANGLE__\n\
447 # else\n\
448 # ifdef __IMPORT__\n\
449 # define __MANGLE_%_DATA__ __MANGLE__ __IMPORT__\n\
450 # else\n\
451 # define __MANGLE_%_DATA__ __MANGLE__\n\
452 # endif\n\
453 # define __MANGLE_%_FUNC__ __MANGLE__\n\
454 # endif\n\
455 #endif\n\
457 for (;;)
459 switch (*op++ = *s++)
461 case 0:
462 op--;
463 break;
464 case '%':
465 op = strcopy(op - 1, proto->package);
466 continue;
467 default:
468 continue;
470 break;
473 return op;
476 #define BACKOUT() (op=ko)
477 #define CACHE() do{CACHEIN();CACHEOUT();call=proto->call;}while(0)
478 #define CACHEIN() (ip=proto->ip)
479 #define CACHEOUT() (op=proto->op)
480 #define GETCHR() (*(unsigned char*)ip++)
481 #define KEEPOUT() (ko=op)
482 #define LASTOUT() (*(op-1))
483 #define PUTCHR(c) (*op++=(c))
484 #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)
485 #define SYNCIN() (proto->ip=ip)
486 #define SYNCOUT() (proto->op=op)
487 #define UNGETCHR() (ip--)
488 #define UNPUTCHR() (op--)
491 * advance to the next non-space character
494 static char*
495 nns(register char* s)
497 while (*s == ' ' || *s == '\t' || *s == '\n')
498 s++;
499 return s;
502 #define DIR_if 01
503 #define DIR_el 02
504 #define DIR_en 03
505 #define DIR 03
508 * update directive mask
511 static int
512 directive(register char* s, int dir)
514 switch (*(s = nns(s)))
516 case 'e':
517 case 'i':
518 dir <<= 2;
519 switch (*++s)
521 case 'f':
522 dir |= DIR_if;
523 break;
524 case 'l':
525 dir |= DIR_el;
526 break;
527 case 'n':
528 dir |= DIR_en;
529 break;
531 break;
533 return dir;
537 * the tokenizer
538 * top level calls loop until EOB
539 * recursive calls just return the next token
542 static int
543 lex(register struct proto* proto, register long flags)
545 register char* ip;
546 register char* op;
547 register int c;
548 register int state;
549 register short* rp;
550 char* m;
551 char* e;
552 char* t;
553 char* bp;
554 char* v;
555 char* im;
556 char* ko;
557 char* aom;
558 int n;
559 int line;
560 int quot;
561 int brack;
562 int sub;
563 int x;
564 int vc;
566 char* ie = 0;
567 char* om = 0;
568 char* aim = 0;
569 char* aie = 0;
570 char* func = 0;
571 int call = 0;
572 int dir = 0;
573 int group = 0;
574 int last = 0;
575 int paren = 0;
576 #if PROTOMAIN
577 char* qe = 0;
578 int qn = 0;
579 int args = 0;
580 #endif
582 CACHE();
583 #if PROTOMAIN
584 if (flags & EXTERN) KEEPOUT();
585 #endif
586 fsm_start:
587 proto->tp = ip;
588 state = PROTO;
589 bp = ip;
592 rp = fsm[state];
593 fsm_get:
594 while (!(state = rp[c = GETCHR()]));
595 fsm_next:
597 } while (state > 0);
598 if ((n = ip - bp - 1) > 0)
600 ip = bp;
601 MEMCPY(op, ip, n);
602 ip++;
604 state = ~state;
605 fsm_terminal:
606 switch (TERM(state))
608 case S_CHR:
609 if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c)
611 case '+':
612 case '-':
613 case '*':
614 case '&':
615 PUTCHR(' ');
616 break;
618 PUTCHR(c);
619 break;
621 case S_CHRB:
622 UNGETCHR();
623 c = LASTOUT();
624 break;
626 case S_COMMENT:
627 switch (c)
629 case '\n':
630 if (INCOMMENTXX(rp)) goto fsm_newline;
631 PUTCHR(c);
632 proto->line++;
633 rp = fsm[COM2];
634 break;
635 case '/':
636 #if PROTOMAIN
637 if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
638 else
639 #endif
640 PUTCHR(c);
641 if (INCOMMENTXX(rp))
643 rp = fsm[COM5];
644 break;
646 goto fsm_start;
647 case EOF:
648 break;
649 default:
650 #if PROTOMAIN
651 if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
652 else
653 #endif
654 PUTCHR(c);
655 rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
656 break;
658 bp = ip;
659 goto fsm_get;
661 case S_EOB:
662 if (c)
664 if (state = fsm[TERMINAL][INDEX(rp)+1])
665 goto fsm_terminal;
666 SYNC();
667 return 0;
669 UNGETCHR();
670 fsm_eob:
671 if ((flags & (DECLARE|GLOBAL|RECURSIVE)) == GLOBAL && (proto->flags & MORE))
673 #if PROTOMAIN
674 if (!(flags & EXTERN)) /* XXX */
675 #endif
676 flags |= SLIDE;
677 c = ip - proto->ib;
678 if (!(flags & MATCH))
679 im = proto->tp;
680 if (ip > proto->ib)
682 n = ip - im;
683 if (ip - n < proto->ib)
684 proto->flags |= ERROR;
685 memcopy(proto->ib - n, ip - n, n);
686 ip = proto->ib;
688 proto->tp -= c;
689 if (flags & MATCH)
691 im -= c;
692 ie -= c;
694 if (aim)
695 aim -= c;
696 if (aie)
697 aie -= c;
698 if ((n = read(proto->fd, ip, proto->iz)) > 0)
700 if ((proto->options & REGULAR) && n < proto->iz)
702 proto->flags &= ~MORE;
703 close(proto->fd);
705 *(ip + n) = 0;
706 if (state & SPLICE)
707 goto fsm_splice;
708 bp = ip;
709 goto fsm_get;
711 *ip = 0;
712 proto->flags &= ~MORE;
713 close(proto->fd);
715 if (state & SPLICE)
716 goto fsm_splice;
717 /* NOTE: RECURSIVE lex() should really SLIDE too */
718 if (!(flags & RECURSIVE) && (state = rp[c = EOF]))
720 bp = ip;
721 goto fsm_next;
723 SYNC();
724 return 0;
726 case S_LITBEG:
727 quot = c;
728 #if PROTOMAIN
729 if (c == '"' && qe)
731 for (n = 0, t = qe + 1; t < op && (*t == ' ' || *t == '\t' || *t == '\n' && ++n || *t >= 'A' && *t <= 'Z' || *t == '_'); t++);
732 if (t == op)
734 op = qe;
735 qe = 0;
736 qn = n;
738 else PUTCHR(c);
740 else
741 #endif
742 PUTCHR(c);
743 rp = fsm[LIT1];
744 bp = ip;
745 goto fsm_get;
747 case S_LITEND:
748 if (c == quot)
750 #if PROTOMAIN
751 if (!(flags & DIRECTIVE))
752 qe = (c == '"') ? op : (char*)0;
753 #endif
754 PUTCHR(c);
755 #if PROTOMAIN
756 while (qn > 0)
758 qn--;
759 PUTCHR('\n');
761 #endif
763 else if (c != '\n' && c != EOF)
765 PUTCHR(c);
766 bp = ip;
767 goto fsm_get;
769 else
771 #if PROTOMAIN
772 while (qn > 0)
774 qn--;
775 PUTCHR('\n');
777 #endif
778 UNGETCHR();
780 c = T_INVALID;
781 break;
783 case S_LITESC:
784 #if PROTOMAIN
785 if (flags & CLASSIC) PUTCHR(c);
786 else
787 #endif
788 switch (c)
790 case 'a':
791 n = CC_bel;
792 goto fsm_oct;
793 case 'E':
794 n = CC_esc;
795 goto fsm_oct;
796 case 'v':
797 n = CC_vt;
798 goto fsm_oct;
799 case 'x':
800 SYNC();
801 lex(proto, (flags & GLOBAL) | RECURSIVE);
802 for (n = x = 0; (c = GETCHR()), x < 3; x++) switch (c)
804 case '0': case '1': case '2': case '3':
805 case '4': case '5': case '6': case '7':
806 case '8': case '9':
807 n = (n << 4) + c - '0';
808 break;
809 case 'a': case 'b': case 'c': case 'd':
810 case 'e': case 'f':
811 n = (n << 4) + c - 'a' + 10;
812 break;
813 case 'A': case 'B': case 'C': case 'D':
814 case 'E': case 'F':
815 n = (n << 4) + c - 'A' + 10;
816 break;
817 default:
818 goto fsm_hex;
820 fsm_hex:
821 UNGETCHR();
822 fsm_oct:
823 PUTCHR(((n >> 6) & 07) + '0');
824 PUTCHR(((n >> 3) & 07) + '0');
825 PUTCHR((n & 07) + '0');
826 break;
827 default:
828 PUTCHR(c);
829 break;
831 rp = fsm[LIT1];
832 bp = ip;
833 goto fsm_get;
835 case S_MACRO:
836 UNGETCHR();
837 #if PROTOMAIN
838 if ((flags & EXTERN) && *proto->tp == 's' && !strncmp(proto->tp, "static", 6))
840 c = T_EXTERN;
841 break;
843 #endif
844 if (*proto->tp == '_' && !strncmp(proto->tp, "__STDPP__directive", 6)) c = '#';
845 else c = T_ID;
847 break;
849 case S_NL:
850 fsm_newline:
851 proto->line++;
852 #if PROTOMAIN
853 if (flags & EXTERN)
855 if (op != proto->ob && LASTOUT() != ' ' && LASTOUT() != '\n')
856 PUTCHR(' ');
858 else
859 #endif
860 PUTCHR(c);
861 if (flags & DIRECTIVE)
863 #if PROTOMAIN
864 if (flags & CLASSIC)
866 if (flags & EXTERN) BACKOUT();
867 if (flags & JUNK)
869 *(ip - 1) = 0;
870 op = strcopy(om, "/* ");
871 op = strcopy(op, im);
872 op = strcopy(op, " */\n");
874 flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|JUNK|MATCH|SHARP|TYPEDEF);
876 else
877 #endif
879 if ((flags & (DEFINE|SHARP)) == (DEFINE|SHARP))
881 *(ip - 1) = 0;
882 op = strcopy(om, "#if defined(__STDC__) || defined(__STDPP__)\n");
883 op = strcopy(op, im);
884 op = strcopy(op, "\n#else\n");
885 bp = ip;
886 ip = im;
887 *op++ = *ip++;
888 while (*op = *ip++)
889 if (*op++ == '#' && *ip != '(')
891 op--;
892 while (*--op == ' ' || *op == '\t');
893 if (*ip == '#')
895 op = strcopy(op + 1, "/**/");
896 while (*++ip == ' ' || *ip == '\t');
898 else
900 if (*op != '"') *++op = '"';
901 op++;
902 while (*ip == ' ' || *ip == '\t') ip++;
903 while ((c = *ip) >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '_') *op++ = *ip++;
904 while (*ip == ' ' || *ip == '\t') ip++;
905 if (*ip == '"') ip++;
906 else *op++ = '"';
909 ip = bp;
910 op = strcopy(op, "\n#endif\n");
911 op = linesync(proto, op, proto->line);
913 flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|MATCH|OTHER|SHARP|SKIP|TOKENS|TYPEDEF);
915 call = 0;
916 group = 0;
917 paren = 0;
918 last = '\n';
920 if (paren == 0 && (flags & (MATCH|RECURSIVE|SKIP|SLIDE)) == SLIDE)
922 #if PROTOMAIN
923 if (flags & EXTERN) BACKOUT();
924 #endif
925 SYNC();
926 return 0;
928 goto fsm_start;
930 case S_QUAL:
931 PUTCHR(c);
932 rp = fsm[NEXT(state)];
933 bp = ip;
934 goto fsm_get;
936 case S_TOK:
937 PUTCHR(c);
938 c = TYPE(state);
939 break;
941 case S_TOKB:
942 UNGETCHR();
943 c = TYPE(state);
944 break;
946 case S_RESERVED:
947 UNGETCHR();
948 c = T_ID;
949 if (!(flags & DECLARE)) switch (RESERVED(*proto->tp, *(ip - 1), ip - proto->tp))
951 case RESERVED('N', 'N', 3):
952 if (proto->tp[1] == 'o')
953 c = T_DO;
954 break;
955 case RESERVED('d', 'o', 2):
956 c = T_DO;
957 break;
958 case RESERVED('e', 'e', 4):
959 if (!(flags & RECURSIVE) && (flags & (DIRECTIVE|TOKENS)) != DIRECTIVE && !strncmp(proto->tp, "else", 4))
961 c = T_ELSE;
962 goto fsm_id;
964 break;
965 case RESERVED('e', 'n', 6):
966 if (!strncmp(proto->tp, "extern", 6))
967 c = T_EXTERN;
968 break;
969 case RESERVED('f', 'r', 3):
970 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "for", 3))
972 c = T_FOR;
973 goto fsm_id;
975 break;
976 case RESERVED('i', 'f', 2):
977 c = T_IF;
978 break;
979 case RESERVED('i', 'e', 6):
980 if (!strncmp(proto->tp, "inline", 6) && !(flags & (MATCH|SKIP|TOKENS|TYPEDEF)) && proto->brace == 0 && paren == 0 && group == 0 && (last == ';' || last == '}' || last == '\n' || last == 0))
982 flags |= SKIP;
983 SYNC();
984 line = proto->line;
985 op = strcopy(op - 6, "__INLINE__");
986 SYNC();
988 break;
989 case RESERVED('r', 'n', 6):
990 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "return", 6))
992 c = T_RETURN;
993 goto fsm_id;
995 break;
996 case RESERVED('s', 'c', 6):
997 if ((proto->options & EXTERNALIZE) && !strncmp(proto->tp, "static", 6))
999 proto->ox = op - 6;
1000 flags |= EXTERNALIZE;
1002 break;
1003 case RESERVED('t', 'f', 7):
1004 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "typedef", 7))
1006 flags |= TYPEDEF;
1007 c = T_EXTERN;
1009 break;
1010 case RESERVED('v', 't', 8):
1011 if (*ip == '(' && !strncmp(proto->tp, "va_start", 8)) c = T_VA_START;
1012 break;
1013 case RESERVED('v', 'd', 4):
1014 if (!strncmp(proto->tp, "void", 4))
1016 if (flags & (CLASSIC|PLUSONLY|INIT_DEFINE|INIT_INCLUDE)) c = T_VOID;
1017 else
1019 SYNC();
1020 line = proto->line;
1021 if (lex(proto, (flags & GLOBAL) | RECURSIVE) == '*')
1023 memcopy(op - 4, "__V_", 4);
1024 memcopy(ip - 4, "__V_", 4);
1026 else c = T_VOID;
1027 proto->line = line;
1028 SYNC();
1029 bp = ip;
1032 break;
1033 case RESERVED('w', 'e', 5):
1034 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "while", 5))
1036 c = T_WHILE;
1037 goto fsm_id;
1039 break;
1041 #if PROTOMAIN
1042 if ((flags & CLASSIC) && c != T_EXTERN)
1043 c = T_ID;
1044 #endif
1045 break;
1047 case S_VS:
1048 goto fsm_start;
1050 case S_WS:
1051 UNGETCHR();
1052 #if PROTOMAIN
1053 if ((flags & (EXTERN|MATCH)) == EXTERN)
1055 while (op > proto->ob && (*(op - 1) == ' ' || *(op - 1) == '\t'))
1056 op--;
1057 if (op > proto->ob && *(op - 1) != '\n') *op++ = ' ';
1059 #endif
1060 goto fsm_start;
1062 default:
1063 if (state & SPLICE)
1065 if (c == '\\')
1067 if (!(n = GETCHR()))
1069 goto fsm_eob;
1070 fsm_splice:
1071 c = '\\';
1072 n = GETCHR();
1074 if (n == '\n')
1076 proto->line++;
1077 PUTCHR('\\');
1078 PUTCHR('\n');
1079 bp = ip;
1080 goto fsm_get;
1082 UNGETCHR();
1084 state &= ~SPLICE;
1085 if (state >= TERMINAL)
1086 goto fsm_terminal;
1087 rp = fsm[state];
1089 PUTCHR(c);
1090 bp = ip;
1091 goto fsm_get;
1093 if (!(flags & (INIT_DEFINE|INIT_INCLUDE|RECURSIVE)))
1095 if (!(flags & DIRECTIVE)) switch (c)
1097 case '(':
1098 #if PROTOMAIN
1099 if (!(flags & CLASSIC) || proto->brace == 0)
1100 #endif
1102 if (paren++ == 0)
1104 #if PROTOMAIN
1105 if (!(flags & CLASSIC) || group <= 1)
1106 #endif
1108 #if PROTOMAIN
1109 args = 0;
1110 #endif
1111 if (group++ == 0) group++;
1112 else if (flags & INDIRECT) call++;
1113 flags |= MATCH;
1114 im = ip - 1;
1115 om = op - 1;
1117 sub = 0;
1119 else if (paren == 2 && !aim)
1121 sub++;
1122 if (last == '(')
1124 flags &= ~MATCH;
1125 om = 0;
1127 else if (flags & INDIRECT)
1129 aim = ip - 1;
1130 aom = op - 1;
1132 else if ((flags & (MATCH|TOKENS)) == MATCH)
1134 for (m = ip - 2; m > im && (*m == ' ' || *m == '\t'); m--);
1135 if (m != im && sub == 1)
1137 m = im + (*nns(ip) == '*');
1139 if (m == im)
1141 flags &= ~MATCH;
1142 om = 0;
1145 else if ((flags & MATCH) && sub == 1 && *nns(ip) != '*')
1147 flags &= ~MATCH;
1148 om = 0;
1151 flags &= ~TOKENS;
1153 break;
1154 case ')':
1155 #if PROTOMAIN
1156 if (!(flags & CLASSIC) || proto->brace == 0)
1157 #endif
1158 if (--paren == 0)
1160 #if PROTOMAIN
1161 if (flags & CLASSIC)
1163 if (group != 2)
1165 c = T_ID;
1166 break;
1168 group++;
1170 #endif
1171 ie = ip;
1173 else if (paren == 1 && (flags & INDIRECT) && !aie)
1174 aie = ip;
1175 break;
1176 case '*':
1177 if (last == '(' && group == 2)
1179 group--;
1180 if (paren == 1)
1182 flags |= INDIRECT;
1183 aim = aie = 0;
1186 break;
1187 case '#':
1188 dir = directive(ip, dir);
1189 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))
1190 flags |= DIRECTIVE;
1191 else if (!(flags & (DECLARE|DIRECTIVE)))
1193 flags |= DIRECTIVE;
1194 if (!(flags & PLUSONLY))
1196 bp = ip;
1197 while (*ip == ' ' || *ip == '\t') ip++;
1198 if (*ip == 'l' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e')
1200 if (*++ip == ' ' || *ip == '\t')
1202 proto->line = 0;
1203 while (*++ip >= '0' && *ip <= '9')
1204 proto->line = proto->line * 10 + *ip - '0';
1205 proto->line--;
1208 #if PROTOMAIN
1209 else if ((flags & (CLASSIC|EXTERN)) == CLASSIC)
1211 n = 0;
1212 t = ip + 6;
1213 while (ip < t && *ip >= 'a' && *ip <= 'z')
1214 n = HASHKEYPART(n, *ip++);
1215 switch (n)
1217 case HASHKEY4('e','l','s','e'):
1218 case HASHKEY5('e','n','d','i','f'):
1219 while (*ip == ' ' || *ip == '\t') ip++;
1220 if (*ip != '\n' && *ip != '/' && *(ip + 1) != '*')
1222 flags |= JUNK|MATCH;
1223 im = ip;
1224 om = op + (ip - bp);
1226 break;
1227 case HASHKEY4('e','l','i','f'):
1228 case HASHKEY5('e','r','r','o','r'):
1229 case HASHKEY2('i','f'):
1230 case HASHKEY5('i','f','d','e','f'):
1231 case HASHKEY6('i','f','n','d','e','f'):
1232 case HASHKEY5('u','n','d','e','f'):
1233 break;
1234 case HASHKEY6('i','n','c','l','u','d'):
1235 if (*ip == 'e') ip++;
1236 /*FALLTHROUGH*/
1237 case HASHKEY6('d','e','f','i','n','e'):
1238 case HASHKEY6('p','r','a','g','m','a'):
1239 if (*ip < 'a' || *ip > 'z') break;
1240 /*FALLTHROUGH*/
1241 default:
1242 flags |= JUNK|MATCH;
1243 im = bp - 1;
1244 om = op - 1;
1245 break;
1248 else
1249 #endif
1251 if (*ip == 'i' && *++ip == 'n' && *++ip == 'c' && *++ip == 'l' && *++ip == 'u' && *++ip == 'd' && *++ip == 'e')
1253 while (*++ip == ' ' || *ip == '\t');
1254 if (*ip++ == '<' && *ip++ == 's' && *ip++ == 't' && *ip++ == 'd' && *ip++ == 'a' && *ip++ == 'r' && *ip++ == 'g' && *ip++ == '.' && *ip++ == 'h' && *ip++ == '>')
1256 op = strcopy(op, "\
1257 if !defined(va_start)\n\
1258 #if defined(__STDARG__)\n\
1259 #include <stdarg.h>\n\
1260 #else\n\
1261 #include <varargs.h>\n\
1262 #endif\n\
1263 #endif\n\
1265 op = linesync(proto, op, proto->line);
1266 break;
1269 else if (*ip == 'd' && *++ip == 'e' && *++ ip == 'f' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e' && (*++ip == ' ' || *ip == '\t'))
1271 while (*++ip == ' ' || *ip == '\t');
1272 if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t'))
1274 t = ip;
1275 while (*++t == ' ' || *t == '\t');
1276 if (*t == 'e' && *++t == 'x' && *++ t == 't' && *++t == 'e' && *++t == 'r' && *++t == 'n' && (*++t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'))
1277 ip = t;
1278 t = ip;
1279 while (*++t == ' ' || *t == '\t');
1280 if (*t == '_' && *(t + 1) == '_')
1282 op = strcopy(op, "undef __MANGLE__\n");
1283 op = linesync(proto, op, proto->line);
1284 op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
1285 break;
1288 flags |= DEFINE|MATCH;
1289 im = bp - 1;
1290 om = op - 1;
1292 else if (*ip == 'u' && *++ip == 'n' && *++ ip == 'd' && *++ip == 'e' && *++ip == 'f' && (*++ip == ' ' || *ip == '\t'))
1294 while (*++ip == ' ' || *ip == '\t');
1295 if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t' || *ip == '\n' || *ip == '\r'))
1297 op = strcopy(op, "undef __MANGLE__\n");
1298 op = linesync(proto, op, proto->line);
1299 op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
1300 break;
1302 flags |= DEFINE|MATCH;
1303 im = bp - 1;
1304 om = op - 1;
1307 ip = bp;
1309 break;
1311 else
1312 break;
1313 /*FALLTHROUGH*/
1314 case '{':
1315 if (proto->brace++ == 0 && paren == 0)
1317 if (last == '=') flags |= INIT;
1318 #if PROTOMAIN
1319 else if (flags & CLASSIC)
1321 if ((flags & (MATCH|OTHER|SKIP)) == MATCH)
1323 if (args)
1325 v = number(op, args < 0 ? -args : args);
1326 v = strcopy(v, " argument actual/formal mismatch");
1327 *v++ = ' ';
1328 v = memcopy(v, im, ie - im);
1329 *v = 0;
1330 proto_error((char*)proto + sizeof(struct proto), 2, op, NiL);
1332 ip--;
1333 /*UNDENT...*/
1334 v = ie;
1335 while (ie < ip)
1336 if (*ie++ == '/' && *ie == '*')
1338 e = ie - 1;
1339 while (++ie < ip)
1341 if (*ie == '*')
1343 while (ie < ip && *ie == '*') ie++;
1344 if (ie < ip && *ie == '/')
1346 while (++ie < ip && (*ie == ' ' || *ie == '\t'));
1347 while (e > v && (*(e - 1) == ' ' || *(e - 1) == '\t')) e--;
1348 if (e > v && *e != '\n') *e++ = ' ';
1349 t = ie;
1350 while (--e >= v)
1351 *--t = *e;
1352 v = t;
1353 break;
1358 ie = v;
1359 /*...INDENT*/
1360 op = om++;
1361 if (flags & EXTERN)
1363 v = op;
1364 while (v > ko && *--v != ' ');
1365 if (*v != ' ')
1367 om = (v = (op += 4)) + 1;
1368 while (v >= ko + 4)
1370 *v = *(v - 4);
1371 v--;
1373 memcopy(ko, "int ", 4);
1375 if (*v == ' ')
1377 while (*(v + 1) == '*')
1378 *v++ = '*';
1379 *v = '\t';
1380 if ((v - ko) <= 8)
1382 om = (e = ++op) + 1;
1383 while (e > v)
1385 *e = *(e - 1);
1386 e--;
1390 om = (v = (op += 7)) + 1;
1391 while (v >= ko + 7)
1393 *v = *(v - 7);
1394 v--;
1396 memcopy(ko, "extern ", 7);
1398 PUTCHR('(');
1399 t = op;
1400 e = 0;
1401 /*UNDENT...*/
1402 while (ie < ip)
1404 if ((c = *ie) == ' ' || c == '\t' || c == '\n')
1406 while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
1407 if (ie >= ip) break;
1408 if (c != '*' && op > om) PUTCHR(' ');
1410 if ((n = ((c = *ie) == ',')) || c == ';')
1412 if (flags & EXTERN)
1414 m = op;
1415 while (op > om && ((c = *(op - 1)) == '(' || c == ')' || c == '[' || c == ']'))
1416 op--;
1417 v = op;
1418 while (op > om && (c = *(op - 1)) != ' ' && c != '*')
1419 op--;
1420 while (*(op - 1) == ' ')
1421 op--;
1422 if (!e)
1424 e = op;
1425 while (e > om && *(e - 1) == '*')
1426 e--;
1428 #if _s5r4_386_compiler_bug_fixed_
1429 if (op <= om || *(op - 1) == ',' && (*op++ = ' '))
1430 op = strcopy(op, "int");
1431 #else
1432 if (op <= om)
1433 op = strcopy(op, "int");
1434 else if (*(op - 1) == ',')
1435 op = strcopy(op, " int");
1436 #endif
1437 while (v < m)
1438 PUTCHR(*v++);
1440 PUTCHR(',');
1441 if (n)
1443 if (x = !e) e = op - 1;
1444 PUTCHR(' ');
1445 m = t;
1446 while (m < e)
1447 PUTCHR(*m++);
1448 if (x)
1450 m = e;
1451 while (*--e != ' ');
1452 while (*(e - 1) == '*') e--;
1453 op -= m - e;
1456 while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
1457 if (ie >= ip) UNPUTCHR();
1458 else PUTCHR(' ');
1459 if (!n)
1461 t = op;
1462 e = 0;
1465 else if (*ie == '*')
1467 if (op > om && (c = *(op - 1)) == ' ') op--;
1468 while (*ie == '*') PUTCHR(*ie++);
1469 while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
1470 if (c != '(') PUTCHR(' ');
1472 else if (*ie == '(')
1474 if (op > om && *(op - 1) == ' ') op--;
1475 PUTCHR(*ie++);
1476 while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
1478 else if (*ie == ')')
1480 if (op > om && *(op - 1) == '(')
1481 proto_error((char*)proto + sizeof(struct proto), 1, "function pointer argument prototype omitted", NiL);
1482 PUTCHR(*ie++);
1483 while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
1485 else if ((flags & EXTERN) && (op == om || *(op - 1) == ' ') && *ie == 'r' && !strncmp(ie, "register", 8) && (*(ie + 8) == ' ' || *(ie + 8) == '\t' || *(ie + 8) == '\n'))
1487 ie += 8;
1488 if (op > om) UNPUTCHR();
1490 else PUTCHR(*ie++);
1492 /*...INDENT*/
1493 if (op <= om) op = strcopy(op, "void");
1494 PUTCHR(')');
1495 if (flags & EXTERN)
1497 PUTCHR(';');
1498 PUTCHR('\n');
1499 SYNCOUT();
1500 KEEPOUT();
1502 else
1504 PUTCHR('\n');
1505 PUTCHR(*ip);
1507 ip++;
1508 flags &= ~(MATCH|SKIP);
1511 #endif
1512 else if ((flags & (MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS))
1514 line = proto->line;
1515 op = strcopy(om, " __PARAM__(");
1516 op = memcopy(op, im, ie - im);
1517 PUTCHR(',');
1518 PUTCHR(' ');
1519 PUTCHR('(');
1520 flags &= ~(MATCH|SKIP);
1521 if (flags & VARIADIC)
1523 if ((vc = ie - im + 1) > sizeof(proto->variadic)) vc = sizeof(proto->variadic);
1524 memcopy(proto->variadic, im, vc);
1525 op = strcopy(op, "va_alist)) __OTORP__(va_dcl)\n{");
1527 else
1529 flags |= SKIP;
1530 proto->ip = im;
1531 proto->op = op;
1532 group = 0;
1533 brack = 0;
1534 for (;;)
1536 switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
1538 case '[':
1539 brack++;
1540 continue;
1541 case ']':
1542 brack--;
1543 continue;
1544 case '(':
1545 if (paren++) group++;
1546 continue;
1547 case ')':
1548 if (--paren == 0)
1550 group = 0;
1551 if (flags & MATCH)
1553 flags &= ~(MATCH|SKIP);
1554 op = memcopy(op, m, e - m);
1556 break;
1558 continue;
1559 case ',':
1560 if (paren == 1)
1562 group = 0;
1563 if (flags & MATCH)
1565 flags &= ~(MATCH|SKIP);
1566 op = memcopy(op, m, e - m);
1568 PUTCHR(',');
1569 PUTCHR(' ');
1570 proto->op = op;
1572 continue;
1573 case T_ID:
1574 if (group <= 1 && !brack)
1576 flags |= MATCH;
1577 m = proto->tp;
1578 e = proto->ip;
1580 continue;
1581 default:
1582 continue;
1584 break;
1586 PUTCHR(')');
1587 PUTCHR(')');
1589 if (!(flags & SKIP))
1591 flags |= SKIP;
1592 proto->op = strcopy(op, " __OTORP__(");
1593 proto->ip = im + 1;
1594 n = *(ie - 1);
1595 *(ie - 1) = ';';
1596 c = *ie;
1597 *ie = 0;
1598 lex(proto, (flags & GLOBAL) | DECLARE);
1599 *(ie - 1) = n;
1600 *ie = c;
1601 proto->ip = ie;
1602 op = proto->op;
1603 PUTCHR(')');
1605 if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
1606 op = linesync(proto, op, proto->line = line);
1607 if (flags & DIRECTIVE)
1609 proto->brace = 0;
1610 PUTCHR('\n');
1611 PUTCHR('#');
1613 else if (!(flags & VARIADIC)) PUTCHR('{');
1616 flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
1617 call = 0;
1618 group = 0;
1619 break;
1620 case '}':
1621 flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP|TOKENS);
1622 if (--proto->brace == 0)
1624 flags &= ~(INIT|VARIADIC|VARIADIC2);
1625 #if PROTOMAIN
1626 if (flags & EXTERN) BACKOUT();
1627 #endif
1629 call = 0;
1630 group = 0;
1631 paren = 0;
1632 break;
1633 case '=':
1634 if (last == '?') flags |= DIRECTIVE;
1635 else if (paren == 0 && (flags & (INIT|MATCH|SKIP)) == MATCH)
1637 if (last == ')' && proto->brace && (group != 2 || call != 2)) flags |= SKIP;
1638 else goto fsm_statement;
1640 goto fsm_other;
1641 case ',':
1642 #if PROTOMAIN
1643 if (flags & CLASSIC)
1645 if (paren == 1) args++;
1646 else
1648 args--;
1649 flags &= ~MATCH;
1651 break;
1653 #endif
1654 if (paren == 0 && (flags & DECLARE)) *(op - 1) = c = ';';
1655 /*FALLTHROUGH*/
1656 case ';':
1657 fsm_statement:
1658 if (flags & INIT) /* ignore */;
1659 #if PROTOMAIN
1660 else if (flags & CLASSIC)
1662 if (paren == 0)
1664 if ((flags & MATCH) && last == ')')
1665 flags &= ~MATCH;
1666 if (!(flags & MATCH))
1668 call = 0;
1669 group = 0;
1670 flags &= ~SKIP;
1671 if (flags & EXTERN) BACKOUT();
1672 if (flags & SLIDE)
1674 SYNC();
1675 return 0;
1678 else
1680 args--;
1681 if ((flags & (EXTERN|SKIP)) == (EXTERN|SKIP))
1682 BACKOUT();
1686 #endif
1687 else if (paren == 0)
1689 if ((flags & (MATCH|OTHER|SKIP)) == MATCH && call > 1)
1691 if ((flags & MANGLE) && func)
1693 func[0] = 'F';
1694 func[1] = 'U';
1695 func[2] = 'N';
1696 func[3] = 'C';
1697 func = 0;
1699 if ((flags & (DECLARE|INDIRECT)) == INDIRECT && aim && aie < im)
1701 while (aie < ip && (*aie == ' ' || *aie == '\t' || *aie == '\n')) aie++;
1702 v = aim;
1703 while (v < aie)
1704 if (*v++ == ')') break;
1705 while (v < aie && (*v == ' ' || *v == '\t' || *v == '\n')) v++;
1706 if (v == aie || !(flags & PLUSPLUS))
1708 if (flags & PLUSPLUS) n = 3;
1709 else if (v == aie && *v == '(') n = 10;
1710 else n = 11;
1711 ko = op;
1712 om += n;
1713 v = op += n;
1714 while (v >= ko + n)
1716 *v = *(v - n);
1717 v--;
1719 if (flags & PLUSPLUS) memcopy(aom, "(...))", 6);
1720 else if (n == 10) memcopy(aom, "(__VARARG__))", 13);
1721 else
1723 ko = strcopy(aom, " __PROTO__(");
1724 ko = memcopy(ko, aim, aie - aim);
1725 *ko = ')';
1726 if (++ko >= om)
1728 *ko++ = ')';
1729 om = ko;
1734 else if (flags & TYPEDEF)
1736 op = om;
1737 while (*--op == ' ' || *op == '\t' || *op == '\n');
1738 if (*op != ')')
1740 op = om += 14;
1741 *--op = ')';
1742 while ((x = *(op - 14)) >= 'A' && x <= 'Z' || x >= 'a' && x <= 'z' || x >= '0' && x <= '9' || x == '_')
1743 *--op = x;
1744 memcopy(op - 13, "(__OTORP__(*)", 13);
1747 if (flags & OTHER)
1749 else if (flags & PLUSPLUS)
1751 op = om;
1752 if (!(flags & TOKENS)) op = strcopy(op, "(...)");
1753 else op = memcopy(op, im, ie - im);
1754 PUTCHR(c);
1756 else
1758 if (flags & DECLARE) op = strcopy(om, "()");
1759 else if (!(flags & TOKENS)) op = strcopy(om, "(__VARARG__)");
1760 else
1762 op = strcopy(om, " __PROTO__(");
1763 op = memcopy(op, im, ie - im);
1764 PUTCHR(')');
1766 if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
1767 PUTCHR(c);
1769 flags &= ~(MATCH|VARIADIC|VARIADIC2);
1770 if (c == ',' && !(flags & INDIRECT))
1772 call = 1;
1773 group = 0;
1774 break;
1777 else if (flags & (OTHER|SKIP)) call = 0;
1778 if (c == ';')
1780 flags &= ~(EXTERNALIZE|MANGLE|TOKENS|TYPEDEF);
1781 call = 0;
1782 if (flags & SLIDE)
1784 SYNC();
1785 return 0;
1788 else call = call > 1 && c == ',';
1789 group = 0;
1790 flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
1792 else if (paren == 1 && group == 1 && !(flags & (IDID|MANGLE))) flags |= TOKENS|OTHER;
1793 break;
1794 case T_DO:
1795 case T_IF:
1796 flags |= TOKENS|SKIP;
1797 break;
1798 case T_EXTERN:
1799 #if PROTOMAIN
1800 if (flags & CLASSIC)
1802 if (proto->brace == 0)
1803 flags |= SKIP;
1805 else
1806 #endif
1807 if (paren == 0 && !(flags & TYPEDEF))
1809 flags |= MANGLE;
1810 if (!(flags & PLUSONLY) || proto->package)
1812 op = strcopy(op, " __MANGLE__");
1813 if (proto->package)
1815 op = strcopy(op - 1, proto->package);
1816 func = op + 1;
1817 op = strcopy(op, "_DATA__");
1820 else
1821 func = 0;
1823 break;
1824 case T_VARIADIC:
1825 if (paren == 0 && (flags & (DECLARE|VARIADIC)) == DECLARE)
1827 op -= 3;
1828 SYNC();
1829 return c;
1831 if (paren == 1 && !(flags & SKIP))
1832 flags |= VARIADIC;
1833 flags |= TOKENS;
1834 break;
1835 case T_VOID:
1836 goto fsm_id;
1837 case T_VA_START:
1838 if ((flags & (PLUSONLY|VARIADIC)) == VARIADIC)
1840 flags &= ~MATCH;
1841 line = proto->line;
1842 op = strcopy(op - 8, "__VA_START__");
1843 SYNC();
1844 for (;;)
1846 switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
1848 case 0:
1849 case ';':
1850 break;
1851 case T_ID:
1852 if (!(flags & MATCH))
1854 flags |= MATCH;
1855 m = proto->tp;
1856 e = proto->ip;
1858 continue;
1859 default:
1860 continue;
1862 break;
1864 CACHE();
1865 if (flags & MATCH)
1867 v = m;
1868 n = e - m;
1870 else
1872 v = "ap";
1873 n = 2;
1875 op = strcopy(op, " __OTORP__(");
1876 proto->ip = proto->variadic;
1877 proto->op = op;
1878 flags &= ~MATCH;
1879 group = 0;
1880 bp = proto->ip + 1;
1881 if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
1882 for (;;)
1884 switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
1886 case '(':
1887 if (paren++) group++;
1888 continue;
1889 case ')':
1890 if (--paren == 0)
1892 if (flags & MATCH)
1894 flags &= ~MATCH;
1895 if (!(flags & VARIADIC2))
1897 op = memcopy(op, m, e - m);
1898 op = strcopy(op, " = ");
1900 op = strcopy(op, "va_arg(");
1901 op = memcopy(op, v, n);
1902 PUTCHR(',');
1903 PUTCHR(' ');
1904 if (m > bp) op = memcopy(op, bp, m - bp);
1905 else op = strcopy(op, "int ");
1906 if (group > 1) op = strcopy(op, ")()");
1907 else op = memcopy(op, e, proto->ip - e - 1);
1908 PUTCHR(')');
1909 PUTCHR(';');
1911 group = 0;
1912 break;
1914 continue;
1915 case ',':
1916 if (paren == 1)
1918 if (flags & MATCH)
1920 flags &= ~MATCH;
1921 if (!(flags & VARIADIC2))
1923 op = memcopy(op, m, e - m);
1924 op = strcopy(op, " = ");
1926 op = strcopy(op, "va_arg(");
1927 op = memcopy(op, v, n);
1928 PUTCHR(',');
1929 PUTCHR(' ');
1930 if (m > bp) op = memcopy(op, bp, m - bp);
1931 else op = strcopy(op, "int ");
1932 if (group > 1) op = strcopy(op, ")()");
1933 else op = memcopy(op, e, proto->ip - e - 1);
1934 PUTCHR(')');
1935 PUTCHR(';');
1936 bp = proto->ip + 1;
1937 if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
1939 group = 0;
1940 proto->op = op;
1942 continue;
1943 case T_ID:
1944 if (group <= 1)
1946 flags |= MATCH;
1947 m = proto->tp;
1948 e = proto->ip;
1950 continue;
1951 default:
1952 continue;
1954 break;
1956 op = strcopy(op, ")");
1957 flags |= VARIADIC2;
1958 proto->line = line;
1959 call = 0;
1960 break;
1962 /*FALLTHROUGH*/
1963 case T_ID:
1964 fsm_id:
1965 #if PROTOMAIN
1966 if (flags & CLASSIC)
1968 if (!args && paren == 1) args++;
1969 break;
1971 #endif
1972 if (paren == 0)
1974 if (last == ')')
1976 if (proto->brace == 0 && !(flags & DECLARE)) flags |= SKIP;
1977 call = !call;
1979 else if ((flags & SKIP) || c == T_ID || c == T_VOID) call++;
1980 else flags |= SKIP;
1981 if (last == T_ID) flags |= IDID;
1983 c = T_ID;
1984 flags |= TOKENS;
1985 break;
1986 case T_INVALID:
1987 if (*proto->tp >= '0' && *proto->tp <= '9')
1989 n = 0;
1990 for (;; op--)
1992 switch (*(op - 1))
1994 case 'f':
1995 case 'F':
1996 t = op;
1997 while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
1998 if (*t == '.')
1999 op--;
2000 n = 0;
2001 break;
2002 case 'l':
2003 case 'L':
2004 if (!(n & 01))
2006 n |= 01;
2007 t = op;
2008 while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
2009 if (*t == '.')
2011 n = 0;
2012 op--;
2013 break;
2016 continue;
2017 case 'u':
2018 case 'U':
2019 n |= 02;
2020 continue;
2022 break;
2024 if (n & 01)
2025 *op++ = 'L';
2026 if (n & 02)
2028 m = op;
2029 t = op = m + 10;
2030 while ((c = *--m) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
2031 *--t = c;
2032 c = *t;
2033 strcopy(m + 1, "(unsigned)");
2034 *t = c;
2035 break;
2038 goto fsm_other;
2039 #if PROTOMAIN
2040 case '[':
2041 if ((flags & CLASSIC) && paren == 0 && group <= 2) flags |= SKIP;
2042 /*FALLTHROUGH*/
2043 #endif
2044 default:
2045 fsm_other:
2046 #if PROTOMAIN
2047 if (flags & CLASSIC) break;
2048 #endif
2049 flags |= TOKENS;
2050 if (paren == 0) flags |= OTHER;
2051 break;
2053 else if (c == '#' && *ip != '(') flags |= SHARP;
2054 last = c;
2055 #if PROTOMAIN
2056 if ((flags & (EXTERN|MATCH)) == (EXTERN|MATCH) && ((flags & (DIRECTIVE|SKIP)) || proto->brace || c != '(' && c != ')' && c != '*' && c != T_ID))
2057 CACHEOUT();
2058 else
2059 #endif
2060 SYNCOUT();
2061 goto fsm_start;
2063 else if (flags & (INIT_DEFINE|INIT_INCLUDE))
2065 #if PROTOMAIN
2066 if ((flags & YACC) && c == '%' && *ip == '{') t = 0;
2067 else
2068 #endif
2070 if (c == '#') for (t = ip; *t == ' ' || *t == '\t'; t++);
2071 else t = "";
2072 if (*t++ == 'i' && *t++ == 'f' && *t++ == 'n' && *t++ == 'd' && *t++ == 'e' && *t++ == 'f')
2074 #if !PROTOMAIN
2075 while (*t == ' ' || *t == '\t') t++;
2076 if (*t != '_')
2077 #endif
2078 t = 0;
2081 if (t)
2083 ip = bp;
2084 op = proto->op;
2086 else while (*ip != '\n') *op++ = *ip++;
2087 op = init(proto, op, flags);
2088 op = linesync(proto, op, proto->line);
2089 flags &= ~(INIT_DEFINE|INIT_INCLUDE);
2090 proto->flags &= ~(INIT_DEFINE|INIT_INCLUDE);
2091 goto fsm_start;
2093 SYNC();
2094 return c;
2098 * close a proto buffer stream
2101 void
2102 pppclose(char* iob)
2104 register struct proto* proto = (struct proto*)(iob - sizeof(struct proto));
2106 if (proto->flags & MORE) close(proto->fd);
2107 free((char*)proto); /* some ANSI cc's botch the free() prototype */
2111 * open a new proto buffer stream
2112 * read buffer pointer returned
2113 * 0 returned on error or if no magic
2115 * file !=0 file path to open, otherwise use fd
2116 * fd open file fd if file==0
2117 * notice !=0 copyright notice info commented at the top
2118 * options !=0 additional notice name=value pairs, space or ; separated
2119 * package !=0 generate header for this package
2122 char*
2123 pppopen(char* file, int fd, char* notice, char* options, char* package, char* comment, int flags)
2125 register struct proto* proto;
2126 register char* iob;
2127 register long n;
2128 register char* s;
2129 int pragma;
2130 char* b;
2131 #if PROTOMAIN
2132 int comlen;
2133 char com[80];
2134 #endif
2135 int m = 0;
2137 static int retain;
2140 * initialize proto
2143 #if PROTOMAIN
2144 if (flags & PROTO_CLASSIC) flags &= ~PROTO_INCLUDE;
2145 #endif
2146 if (flags & PROTO_RETAIN) flags &= ~retain;
2147 else retain &= PROTO_INITIALIZED;
2148 if (file && (fd = open(file, O_RDONLY)) < 0) return 0;
2149 #if !PROTOMAIN
2150 if ((n = lseek(fd, 0L, 2)) > 0)
2152 if (lseek(fd, 0L, 0)) return 0;
2153 if (n < CHUNK) n = CHUNK;
2154 else if (n > 2 * BLOCK) n = 0;
2155 m = 1;
2157 if (n > 0)
2160 * file read in one chunk
2163 if (!(proto = newof(0, struct proto, 1, 4 * n + 2)))
2164 return 0;
2165 proto->iz = n;
2166 proto->oz = 3 * n;
2167 n = 0;
2169 else
2170 #endif
2173 * file read in BLOCK chunks
2176 n = BLOCK;
2177 if (!(proto = newof(0, struct proto, 1, 5 * n + 2)))
2178 return 0;
2179 proto->iz = n;
2180 proto->oz = 3 * n;
2181 proto->flags |= MORE;
2183 proto->fd = fd;
2184 proto->package = package;
2185 iob = (char*)proto + sizeof(struct proto);
2186 proto->op = proto->ob = iob;
2187 proto->ip = proto->ib = iob + proto->oz + n;
2188 if (m) proto->options |= REGULAR;
2189 if (!comment)
2190 comment = "/*";
2191 if (!(proto->cc[0] = comment[0]))
2192 notice = options = 0;
2193 else if (comment[1])
2195 proto->cc[1] = comment[1];
2196 proto->cc[2] = comment[2] ? comment[2] : comment[0];
2198 else
2199 proto->cc[1] = proto->cc[2] = comment[0];
2202 * read the first chunk
2205 n = read(fd, proto->ip, proto->iz);
2206 if (!(proto->flags & MORE))
2207 close(fd);
2208 if (n < 0)
2210 pppclose(iob);
2211 return 0;
2213 *(proto->ip + n) = 0;
2216 * check for proto pragma in first block of lines
2217 * pragma blanked out if found
2219 * -1 no pragma
2220 * 0 #pragma noprototyped
2221 * 1 #pragma prototyped
2223 * NOTE: matches may occur inside comments and quotes
2226 #if PROTOMAIN
2227 if (!notice && !options || (comlen = astlicense(com, sizeof(com), NiL, "type=check", proto->cc[0], proto->cc[1], proto->cc[2])) <= 0)
2228 *com = 0;
2229 #endif
2230 pragma = -1;
2231 s = proto->ip;
2232 m = MAGICTOP;
2233 while (m-- > 0 && *s)
2235 while (*s == ' ' || *s == '\t') s++;
2236 if (*s == '#')
2238 b = s++;
2239 while (*s == ' ' || *s == '\t') s++;
2240 if (!strncmp(s, MAGICDIR, sizeof(MAGICDIR) - 1) && (*(s += sizeof(MAGICDIR) - 1) == ' ' || *s == '\t'))
2242 while (*s == ' ' || *s == '\t') s++;
2243 if (*s == 'n' && *(s + 1) == 'o')
2245 s += 2;
2246 pragma = -2;
2248 if (!strncmp(s, MAGICARG, sizeof(MAGICARG) - 1) && (*(s += sizeof(MAGICARG) - 1) == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
2249 while (*s)
2251 if ((*(s - 1) == ' ' || *(s - 1) == '\t') && *s == *MAGICOFF && !strncmp(s, MAGICOFF, sizeof(MAGICOFF) - 1))
2252 notice = options = 0;
2253 if (*s++ == '\n')
2255 pragma += 2;
2256 #if PROTOMAIN
2257 if (!(flags & PROTO_DISABLE) || (flags & PROTO_NOPRAGMA))
2258 #endif
2259 for (s--; b < s; *b++ = ' ');
2260 goto magic;
2263 pragma = -1;
2266 else if (*s == '/' && !strncmp(s, MAGICGEN, sizeof(MAGICGEN) - 1))
2268 pragma = 0;
2269 break;
2271 #if PROTOMAIN
2272 else if (*s == '%' && *(s + 1) == '{')
2273 proto->flags |= YACC;
2274 if (notice || options)
2276 if (*s == *com && !strncmp(s, com, comlen))
2277 notice = options = 0;
2278 else
2279 while (*s)
2281 if (*s == *NOTICED && !strncmp(s, NOTICED, sizeof(NOTICED) - 1))
2283 s += sizeof(NOTICED) - 1;
2284 while (*s == ' ' || *s == '\t')
2285 s++;
2286 if (*s == '(' && (*(s + 1) == 'c' || *(s + 1) == 'C') && *(s + 2) == ')' || *s >= '0' && *s <= '9' && *(s + 1) >= '0' && *(s + 1) <= '9')
2288 notice = options = 0;
2289 break;
2292 if (*s == *PUBLICDOMAIN && !strncmp(s, PUBLICDOMAIN, sizeof(PUBLICDOMAIN) - 1))
2294 notice = options = 0;
2295 break;
2297 else if (*s++ == '\n')
2299 s--;
2300 break;
2304 #endif
2305 while (*s && *s++ != '\n');
2307 magic:
2308 if (flags & PROTO_PLUSPLUS) proto->flags |= PLUSPLUS;
2309 if (flags & PROTO_TEST) proto->test = 1;
2310 if (flags & PROTO_EXTERNALIZE) proto->options |= EXTERNALIZE;
2311 #if PROTOMAIN
2312 if (flags & PROTO_CLASSIC) pragma = -pragma;
2313 if (flags & PROTO_DISABLE) pragma = 0;
2314 if (flags & PROTO_LINESYNC) proto->flags |= LINESYNC;
2315 if (!(proto->flags & YACC) && file && (m = strlen(file)) > 2 && file[--m] == 'y' && file[--m] == '.')
2316 proto->flags |= YACC;
2317 #endif
2318 if (pragma <= 0)
2320 if (flags & PROTO_PLUSPLUS)
2322 flags &= ~(PROTO_HEADER|PROTO_INCLUDE);
2323 proto->flags |= PLUSONLY;
2325 else if (!(flags & (PROTO_FORCE|PROTO_PASS)))
2327 pppclose(iob);
2328 return 0;
2330 else if ((flags & (PROTO_FORCE|PROTO_PASS)) == PROTO_PASS || !pragma)
2332 proto->flags |= PASS;
2333 if (proto->flags & MORE)
2334 proto->oz += proto->iz;
2335 proto->iz = n;
2336 if (notice || options)
2338 if (proto->cc[0] == '#' && proto->ip[0] == '#' && proto->ip[1] == '!')
2340 s = proto->ip;
2341 while (*s && *s++ != '\n');
2342 m = s - proto->ip;
2343 proto->op = memcopy(proto->op, proto->ip, m);
2344 proto->ip = s;
2345 proto->iz = n -= m;
2347 #if PROTOMAIN
2348 if (proto->cc[0])
2350 if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
2351 proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL);
2352 else
2353 proto->op += comlen;
2355 if (!(flags & PROTO_CLASSIC) && !(proto->flags & YACC))
2356 #endif
2357 proto->op = linesync(proto, proto->op, 1);
2358 proto->iz += proto->op - proto->ob;
2360 memcopy(proto->op, proto->ip, n);
2361 return iob;
2364 #if PROTOMAIN
2365 if (!(retain & PROTO_INITIALIZED))
2367 retain |= PROTO_INITIALIZED;
2368 ppfsm(FSM_INIT, NiL);
2370 #endif
2371 proto->line = 1;
2372 #if CHUNK >= 512
2373 if (notice || options || (flags & (PROTO_HEADER|PROTO_INCLUDE)))
2375 #if PROTOMAIN
2376 if (notice || options)
2378 if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
2379 proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL);
2380 else
2381 proto->op += comlen;
2383 #endif
2384 if (flags & PROTO_INCLUDE)
2386 proto->flags |= INIT_INCLUDE;
2387 if (flags & PROTO_RETAIN)
2388 retain |= PROTO_INCLUDE;
2390 else if (flags & PROTO_HEADER)
2392 if (flags & PROTO_RETAIN) retain |= PROTO_HEADER;
2393 #if PROTOMAIN
2394 if (flags & PROTO_CLASSIC)
2396 *proto->op++ = '#';
2397 proto->op = strcopy(proto->op, MAGICDIR);
2398 *proto->op++ = ' ';
2399 proto->op = strcopy(proto->op, MAGICARG);
2400 *proto->op++ = '\n';
2402 else
2403 #endif
2404 proto->flags |= INIT_DEFINE;
2406 #if PROTOMAIN
2407 if (!(flags & PROTO_CLASSIC))
2409 if (proto->flags & YACC)
2411 proto->op = strcopy(proto->op, "\n%{\n" + !notice);
2412 proto->op = strcopy(proto->op, MAGICGEN);
2413 proto->op = strcopy(proto->op, "%}\n");
2415 else
2417 if (n || notice || options)
2418 *proto->op++ = '\n';
2419 proto->op = strcopy(proto->op, MAGICGEN);
2420 if (n)
2421 proto->op = linesync(proto, proto->op, proto->line);
2422 else if (proto->flags & (INIT_DEFINE|INIT_INCLUDE))
2423 proto->op = init(proto, proto->op, proto->flags);
2426 #endif
2428 #endif
2429 #if PROTOMAIN
2430 proto->file = file;
2431 if (flags & PROTO_CLASSIC)
2433 proto->flags |= CLASSIC;
2434 if (!(flags & PROTO_HEADER)) proto->flags |= EXTERN;
2436 #endif
2437 return iob;
2441 * read next proto'd chunk into iob
2442 * the chunk is 0 terminated and its size is returned
2446 pppread(char* iob)
2448 register struct proto* proto = (struct proto*)(iob - sizeof(struct proto));
2449 register int n;
2451 if (proto->flags & PASS)
2453 if (proto->iz)
2455 n = proto->iz;
2456 proto->iz = 0;
2458 else if (!(proto->flags & MORE)) n = 0;
2459 else if ((n = read(proto->fd, proto->ob, proto->oz)) <= 0 || (proto->options & REGULAR) && n < proto->oz)
2461 proto->flags &= ~MORE;
2462 close(proto->fd);
2465 else
2467 if (proto->op == proto->ob)
2469 if (proto->flags & ERROR) return -1;
2470 #if PROTOMAIN
2471 if (proto->flags & YACC)
2473 register char* ip = proto->ip;
2474 register char* op = proto->ob;
2475 register char* ep = proto->ob + proto->oz - 2;
2477 if (!*ip)
2479 ip = proto->ip = proto->ib;
2480 if (!(proto->flags & MORE)) n = 0;
2481 else if ((n = read(proto->fd, ip, proto->iz)) <= 0 || (proto->options & REGULAR) && n < proto->iz)
2483 if (n < 0) n = 0;
2484 proto->flags &= ~MORE;
2485 close(proto->fd);
2487 ip[n] = 0;
2489 if (proto->flags & YACCSPLIT)
2491 proto->flags &= ~YACCSPLIT;
2492 if (*ip == '%')
2494 *op++ = *ip++;
2495 if (proto->flags & YACC2) proto->flags &= ~YACC;
2496 else proto->flags |= YACC2;
2499 if (proto->flags & YACC)
2500 while (op < ep && (n = *op++ = *ip))
2502 ip++;
2503 if (n == '%')
2505 if (*ip == '%' && (ip == proto->ip + 1 || *(ip - 2) == '\n'))
2507 *op++ = *ip++;
2508 if (proto->flags & YACC2) proto->flags &= ~YACC;
2509 else proto->flags |= YACC2;
2510 break;
2512 if (!*ip)
2514 *op++ = '%';
2515 proto->flags |= YACCSPLIT;
2516 break;
2519 else if (n == '\n') proto->line++;
2521 proto->op = memcopy(proto->ob, proto->ip, ip - proto->ip);
2522 proto->ip = ip;
2524 else
2525 #endif
2526 lex(proto, proto->flags);
2527 if ((proto->flags & (ERROR|MORE)) == ERROR)
2528 proto->op = strcopy(proto->op, "/* NOTE: some constructs may not have been converted */\n");
2530 n = proto->op - proto->ob;
2531 proto->op = proto->ob;
2533 return n;
2536 #if !PROTOMAIN
2539 * drop control of iob after first pppread()
2540 * return value is input fd
2541 * if fd<0 then all data in iob
2545 pppdrop(char* iob)
2547 register struct proto* proto = (struct proto*)(iob - sizeof(struct proto));
2549 if (proto->flags & MORE)
2551 proto->flags &= ~MORE;
2552 return proto->fd;
2554 return -1;
2557 #endif