diff options
Diffstat (limited to 'usr/src/lib/libpp/common/ppproto.c')
-rw-r--r-- | usr/src/lib/libpp/common/ppproto.c | 2549 |
1 files changed, 2549 insertions, 0 deletions
diff --git a/usr/src/lib/libpp/common/ppproto.c b/usr/src/lib/libpp/common/ppproto.c new file mode 100644 index 0000000000..f03b2535bc --- /dev/null +++ b/usr/src/lib/libpp/common/ppproto.c @@ -0,0 +1,2549 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1986-2007 AT&T Knowledge Ventures * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Knowledge Ventures * +* * +* A copy of the License is available at * +* http://www.opensource.org/licenses/cpl1.0.txt * +* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * Glenn Fowler + * AT&T Research + * + * convert C prototypes to ANSI, K&R and C++ styles or K&R to ANSI + * slips into the pp block read + * + * define PROTOMAIN for standalone proto + * PROTOMAIN is coded for minimal library support + */ + +static const char id[] = "\n@(#)$Id: proto (AT&T Research) 2006-06-28 $\0\n"; + +#if PROTOMAIN + +#include "ppfsm.c" + +#include <hashkey.h> + +#if PROTO_STANDALONE +#undef O_RDONLY +#endif + +#else + +#include "pplib.h" +#include "ppfsm.h" + +#endif + +#define MAGICGEN "/* : : generated by proto : : */\n" + +#define MAGICDIR "pragma" /* proto magic directive */ +#define MAGICARG "prototyped" /* proto magic directive arg */ +#define MAGICOFF "noticed" /* no notice if found in pragma */ +#define MAGICTOP 64 /* must be in these top lines */ +#define NOTICED "Copyright" /* no notice if found in magic */ + +struct proto /* proto buffer state */ +{ + int brace; /* {..} level */ + int call; /* call level */ + int fd; /* input file descriptor */ + char* file; /* input file name */ + long flags; /* coupled flags */ + long options; /* uncoupled flags */ + char* package; /* header package */ + int line; /* input line count */ + int test; /* testing */ + + char* tp; /* input token base */ + + int iz; /* input buffer size */ + char* ib; /* input buffer base */ + char* ip; /* input buffer pointer */ + + int oz; /* output buffer size */ + char* ob; /* output buffer base */ + char* op; /* output buffer pointer */ + char* ox; /* output buffer externalize */ + + char cc[3]; /* beg mid end comment char */ + char pushback[4]; /* pushback area for caller */ + + char variadic[256]; /* variadic args buffer */ + + /* output buffer */ + /* slide buffer */ + /* input buffer */ +}; + +/* + * proto is separate from pp so these undef's are ok + */ + +#undef CLASSIC +#define CLASSIC (1L<<0) +#undef DECLARE +#define DECLARE (1L<<1) +#undef DEFINE +#define DEFINE (1L<<2) +#undef DIRECTIVE +#define DIRECTIVE (1L<<3) +#undef ERROR +#define ERROR (1L<<4) +#undef EXTERN +#define EXTERN (1L<<5) +#undef EXTERNALIZE +#define EXTERNALIZE (1L<<6) +#undef IDID +#define IDID (1L<<7) +#undef INDIRECT +#define INDIRECT (1L<<8) +#undef INIT +#define INIT (1L<<9) +#undef INIT_DEFINE +#define INIT_DEFINE (1L<<10) +#undef INIT_INCLUDE +#define INIT_INCLUDE (1L<<11) +#undef JUNK +#define JUNK (1L<<12) +#undef LINESYNC +#define LINESYNC (1L<<13) +#undef MANGLE +#define MANGLE (1L<<14) +#undef MATCH +#define MATCH (1L<<15) +#undef MORE +#define MORE (1L<<16) +#undef OTHER +#define OTHER (1L<<17) +#undef PASS +#define PASS (1L<<18) +#undef PLUSONLY +#define PLUSONLY (1L<<19) +#undef PLUSPLUS +#define PLUSPLUS (1L<<20) +#undef RECURSIVE +#define RECURSIVE (1L<<21) +#undef SHARP +#define SHARP (1L<<22) +#undef SKIP +#define SKIP (1L<<23) +#undef SLIDE +#define SLIDE (1L<<24) +#undef TOKENS +#define TOKENS (1L<<25) +#undef TYPEDEF +#define TYPEDEF (1L<<26) +#undef VARIADIC +#define VARIADIC (1L<<27) +#undef VARIADIC2 +#define VARIADIC2 (1L<<28) +#undef YACC +#define YACC (1L<<29) +#undef YACCSPLIT +#define YACCSPLIT (1L<<30) +#undef YACC2 +#define YACC2 (1L<<31) + +#undef GLOBAL +#define GLOBAL (MORE) + +#undef REGULAR +#define REGULAR (1L<<0) + +#ifndef CHUNK +#define CHUNK 1024 +#endif +#define BLOCK (8*CHUNK) + +#define T_VA_START (N_TOKEN+1) + +#define RESERVED(b,e,n) ((((long)(b))<<16)|(((long)(e))<<8)|((long)(n))) + +/* + * generate integer + * pointer to end returned + */ + +static char* +number(register char* p, register long n) +{ + register long d; + + for (d = 1000000; d > 1; d /= 10) + if (n >= d) *p++ = '0' + (n / d) % 10; + *p++ = '0' + n % 10; + return p; +} + +#if PROTOMAIN + +static int errors; + +#if PROTO_STANDALONE + +/* + * namespace pollution forces us to claim parts of libc + */ + +#undef memcpy +#define memcpy(t,f,n) memcopy(t,f,n) +#undef strcpy +#define strcpy(t,f) strcopy(t,f) +#undef strlen +#define strlen(s) sstrlen(s) +#undef strncmp +#define strncmp(s,t,n) sstrncmp(s,t,n) + +/* + * environmentally safe strlen() + */ + +static int +sstrlen(register const char* s) +{ + register const char* b; + + for (b = s; *s; s++); + return s - b; +} + +/* + * environmentally safe strncmp() + */ + +static int +sstrncmp(register const char* s, register char* t, register int n) +{ + register const char* e = s + n; + + while (s < e) + { + if (*s != *t || !*s) + return *s - *t; + s++; + t++; + } + return 0; +} + +/* + * strcpy() except pointer to end returned + */ + +static char* +strcopy(register char* s, register const char* t) +{ + while (*s++ = *t++); + return s - 1; +} + +#endif + +static void +proto_error(char* iob, int level, char* msg, char* arg) +{ + register char* p; + char buf[1024]; + + p = strcopy(buf, "proto: "); + if (iob) + { + register struct proto* proto = (struct proto*)(iob - sizeof(struct proto)); + + if (proto->line) + { + if (proto->file) + { + *p++ = '"'; + p = strcopy(p, proto->file); + *p++ = '"'; + *p++ = ','; + *p++ = ' '; + } + p = strcopy(p, "line "); + p = number(p, proto->line); + } + else if (proto->file) + p = strcopy(p, proto->file); + } + else + { + p = strcopy(p, msg); + msg = arg; + arg = 0; + } + if (*(p - 1) != ' ') + { + *p++ = ':'; + *p++ = ' '; + } + if (level == 1) + p = strcopy(p, "warning: "); + p = strcopy(p, msg); + if (arg) + { + *p++ = ' '; + p = strcopy(p, arg); + } + *p++ = '\n'; + write(2, buf, p - buf); + if (level >= 3) + exit(level - 2); + if (level >= 2) + errors++; +} + +/* + * memcpy() but pointer to end returned + */ + +static char* +memcopy(register char* s, register char* t, int n) +{ + register char* e = t + n; + + while (t < e) *s++ = *t++; + return s; +} + +#include "../libast/port/astlicense.c" + +#else + +#define memcopy(s,t,n) (((char*)memcpy(s,t,n))+(n)) + +#endif + +/* + * generate line sync + * pointer to end returned + */ + +static char* +linesync(register struct proto* proto, register char* p, register long n) +{ +#if PROTOMAIN + if (proto->flags & LINESYNC) +#endif + { +#if PROTOMAIN + p = strcopy(p, "\n#line "); +#else + p = strcopy(p, "\n# "); +#endif + p = number(p, n); + *p++ = '\n'; + } + return p; +} + +/* + * output init header + * pointer to end returned + */ + +static char* +init(struct proto* proto, char* op, int flags) +{ + register char* s; + + if (flags & INIT_DEFINE) + { + op = strcopy(op, "\ +\n\ +#if !defined(__PROTO__)\n\ +# if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\ +# if defined(__cplusplus)\n\ +# define __LINKAGE__ \"C\"\n\ +# else\n\ +# define __LINKAGE__\n\ +# endif\n\ +# define __STDARG__\n\ +# define __PROTO__(x) x\n\ +# define __OTORP__(x)\n\ +# define __PARAM__(n,o) n\n\ +# if !defined(__STDC__) && !defined(__cplusplus)\n\ +# if !defined(c_plusplus)\n\ +# define const\n\ +# endif\n\ +# define signed\n\ +# define void int\n\ +# define volatile\n\ +# define __V_ char\n\ +# else\n\ +# define __V_ void\n\ +# endif\n\ +# else\n\ +# define __PROTO__(x) ()\n\ +# define __OTORP__(x) x\n\ +# define __PARAM__(n,o) o\n\ +# define __LINKAGE__\n\ +# define __V_ char\n\ +# define const\n\ +# define signed\n\ +# define void int\n\ +# define volatile\n\ +# endif\n\ +# define __MANGLE__ __LINKAGE__\n\ +# if defined(__cplusplus) || defined(c_plusplus)\n\ +# define __VARARG__ ...\n\ +# else\n\ +# define __VARARG__\n\ +# endif\n\ +# if defined(__STDARG__)\n\ +# define __VA_START__(p,a) va_start(p,a)\n\ +# else\n\ +# define __VA_START__(p,a) va_start(p)\n\ +# endif\n\ +# if !defined(__INLINE__)\n\ +# if defined(__cplusplus)\n\ +# define __INLINE__ extern __MANGLE__ inline\n\ +# else\n\ +# if defined(_WIN32) && !defined(__GNUC__)\n\ +# define __INLINE__ __inline\n\ +# endif\n\ +# endif\n\ +# endif\n\ +#endif\n\ +#if !defined(__LINKAGE__)\n\ +#define __LINKAGE__ /* 2004-08-11 transition */\n\ +#endif\n\ +"); + } + else + op = strcopy(op, "\ +\n\ +#if !defined(__PROTO__)\n\ +#include <prototyped.h>\n\ +#endif\n\ +#if !defined(__LINKAGE__)\n\ +#define __LINKAGE__ /* 2004-08-11 transition */\n\ +#endif\n\ +"); + if (proto->package) + { + s = "\ +#ifndef __MANGLE_%_DATA__\n\ +# ifdef _BLD_%\n\ +# ifdef __EXPORT__\n\ +# define __MANGLE_%_DATA__ __MANGLE__ __EXPORT__\n\ +# else\n\ +# define __MANGLE_%_DATA__ __MANGLE__\n\ +# endif\n\ +# define __MANGLE_%_FUNC__ __MANGLE__\n\ +# else\n\ +# ifdef __IMPORT__\n\ +# define __MANGLE_%_DATA__ __MANGLE__ __IMPORT__\n\ +# else\n\ +# define __MANGLE_%_DATA__ __MANGLE__\n\ +# endif\n\ +# define __MANGLE_%_FUNC__ __MANGLE__\n\ +# endif\n\ +#endif\n\ +"; + for (;;) + { + switch (*op++ = *s++) + { + case 0: + op--; + break; + case '%': + op = strcopy(op - 1, proto->package); + continue; + default: + continue; + } + break; + } + } + return op; +} + +#define BACKOUT() (op=ko) +#define CACHE() do{CACHEIN();CACHEOUT();call=proto->call;}while(0) +#define CACHEIN() (ip=proto->ip) +#define CACHEOUT() (op=proto->op) +#define GETCHR() (*(unsigned char*)ip++) +#define KEEPOUT() (ko=op) +#define LASTOUT() (*(op-1)) +#define PUTCHR(c) (*op++=(c)) +#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) +#define SYNCIN() (proto->ip=ip) +#define SYNCOUT() (proto->op=op) +#define UNGETCHR() (ip--) +#define UNPUTCHR() (op--) + +/* + * advance to the next non-space character + */ + +static char* +nns(register char* s) +{ + while (*s == ' ' || *s == '\t' || *s == '\n') + s++; + return s; +} + +#define DIR_if 01 +#define DIR_el 02 +#define DIR_en 03 +#define DIR 03 + +/* + * update directive mask + */ + +static int +directive(register char* s, int dir) +{ + switch (*(s = nns(s))) + { + case 'e': + case 'i': + dir <<= 2; + switch (*++s) + { + case 'f': + dir |= DIR_if; + break; + case 'l': + dir |= DIR_el; + break; + case 'n': + dir |= DIR_en; + break; + } + break; + } + return dir; +} + +/* + * the tokenizer + * top level calls loop until EOB + * recursive calls just return the next token + */ + +static int +lex(register struct proto* proto, register long flags) +{ + register char* ip; + register char* op; + register int c; + register int state; + register short* rp; + char* m; + char* e; + char* t; + char* bp; + char* v; + char* im; + char* ko; + char* aom; + int n; + int line; + int quot; + int brack; + int sub; + int x; + int vc; + + char* ie = 0; + char* om = 0; + char* aim = 0; + char* aie = 0; + char* func = 0; + int call = 0; + int dir = 0; + int group = 0; + int last = 0; + int paren = 0; +#if PROTOMAIN + char* qe = 0; + int qn = 0; + int args = 0; +#endif + + CACHE(); +#if PROTOMAIN + if (flags & EXTERN) KEEPOUT(); +#endif + fsm_start: + proto->tp = ip; + state = PROTO; + bp = ip; + do + { + rp = fsm[state]; + fsm_get: + while (!(state = rp[c = GETCHR()])); + fsm_next: + ; + } while (state > 0); + if ((n = ip - bp - 1) > 0) + { + ip = bp; + MEMCPY(op, ip, n); + ip++; + } + state = ~state; + fsm_terminal: + switch (TERM(state)) + { + case S_CHR: + if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c) + { + case '+': + case '-': + case '*': + case '&': + PUTCHR(' '); + break; + } + PUTCHR(c); + break; + + case S_CHRB: + UNGETCHR(); + c = LASTOUT(); + break; + + case S_COMMENT: + switch (c) + { + case '\n': + if (INCOMMENTXX(rp)) goto fsm_newline; + PUTCHR(c); + proto->line++; + rp = fsm[COM2]; + break; + case '/': +#if PROTOMAIN + if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT(); + else +#endif + PUTCHR(c); + if (INCOMMENTXX(rp)) + { + rp = fsm[COM5]; + break; + } + goto fsm_start; + case EOF: + break; + default: +#if PROTOMAIN + if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT(); + else +#endif + PUTCHR(c); + rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3]; + break; + } + bp = ip; + goto fsm_get; + + case S_EOB: + if (c) + { + if (state = fsm[TERMINAL][INDEX(rp)+1]) + goto fsm_terminal; + SYNC(); + return 0; + } + UNGETCHR(); + fsm_eob: + if ((flags & (DECLARE|GLOBAL|RECURSIVE)) == GLOBAL && (proto->flags & MORE)) + { +#if PROTOMAIN + if (!(flags & EXTERN)) /* XXX */ +#endif + flags |= SLIDE; + c = ip - proto->ib; + if (!(flags & MATCH)) + im = proto->tp; + if (ip > proto->ib) + { + n = ip - im; + if (ip - n < proto->ib) + proto->flags |= ERROR; + memcopy(proto->ib - n, ip - n, n); + ip = proto->ib; + } + proto->tp -= c; + if (flags & MATCH) + { + im -= c; + ie -= c; + } + if (aim) + aim -= c; + if (aie) + aie -= c; + if ((n = read(proto->fd, ip, proto->iz)) > 0) + { + if ((proto->options & REGULAR) && n < proto->iz) + { + proto->flags &= ~MORE; + close(proto->fd); + } + *(ip + n) = 0; + if (state & SPLICE) + goto fsm_splice; + bp = ip; + goto fsm_get; + } + *ip = 0; + proto->flags &= ~MORE; + close(proto->fd); + } + if (state & SPLICE) + goto fsm_splice; + /* NOTE: RECURSIVE lex() should really SLIDE too */ + if (!(flags & RECURSIVE) && (state = rp[c = EOF])) + { + bp = ip; + goto fsm_next; + } + SYNC(); + return 0; + + case S_LITBEG: + quot = c; +#if PROTOMAIN + if (c == '"' && qe) + { + for (n = 0, t = qe + 1; t < op && (*t == ' ' || *t == '\t' || *t == '\n' && ++n || *t >= 'A' && *t <= 'Z' || *t == '_'); t++); + if (t == op) + { + op = qe; + qe = 0; + qn = n; + } + else PUTCHR(c); + } + else +#endif + PUTCHR(c); + rp = fsm[LIT1]; + bp = ip; + goto fsm_get; + + case S_LITEND: + if (c == quot) + { +#if PROTOMAIN + if (!(flags & DIRECTIVE)) + qe = (c == '"') ? op : (char*)0; +#endif + PUTCHR(c); +#if PROTOMAIN + while (qn > 0) + { + qn--; + PUTCHR('\n'); + } +#endif + } + else if (c != '\n' && c != EOF) + { + PUTCHR(c); + bp = ip; + goto fsm_get; + } + else + { +#if PROTOMAIN + while (qn > 0) + { + qn--; + PUTCHR('\n'); + } +#endif + UNGETCHR(); + } + c = T_INVALID; + break; + + case S_LITESC: +#if PROTOMAIN + if (flags & CLASSIC) PUTCHR(c); + else +#endif + switch (c) + { + case 'a': + n = CC_bel; + goto fsm_oct; + case 'E': + n = CC_esc; + goto fsm_oct; + case 'v': + n = CC_vt; + goto fsm_oct; + case 'x': + SYNC(); + lex(proto, (flags & GLOBAL) | RECURSIVE); + for (n = x = 0; (c = GETCHR()), x < 3; x++) switch (c) + { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + n = (n << 4) + c - '0'; + break; + case 'a': case 'b': case 'c': case 'd': + case 'e': case 'f': + n = (n << 4) + c - 'a' + 10; + break; + case 'A': case 'B': case 'C': case 'D': + case 'E': case 'F': + n = (n << 4) + c - 'A' + 10; + break; + default: + goto fsm_hex; + } + fsm_hex: + UNGETCHR(); + fsm_oct: + PUTCHR(((n >> 6) & 07) + '0'); + PUTCHR(((n >> 3) & 07) + '0'); + PUTCHR((n & 07) + '0'); + break; + default: + PUTCHR(c); + break; + } + rp = fsm[LIT1]; + bp = ip; + goto fsm_get; + + case S_MACRO: + UNGETCHR(); +#if PROTOMAIN + if ((flags & EXTERN) && *proto->tp == 's' && !strncmp(proto->tp, "static", 6)) + { + c = T_EXTERN; + break; + } +#endif + if (*proto->tp == '_' && !strncmp(proto->tp, "__STDPP__directive", 6)) c = '#'; + else c = T_ID; + + break; + + case S_NL: + fsm_newline: + proto->line++; +#if PROTOMAIN + if (flags & EXTERN) + { + if (op != proto->ob && LASTOUT() != ' ' && LASTOUT() != '\n') + PUTCHR(' '); + } + else +#endif + PUTCHR(c); + if (flags & DIRECTIVE) + { +#if PROTOMAIN + if (flags & CLASSIC) + { + if (flags & EXTERN) BACKOUT(); + if (flags & JUNK) + { + *(ip - 1) = 0; + op = strcopy(om, "/* "); + op = strcopy(op, im); + op = strcopy(op, " */\n"); + } + flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|JUNK|MATCH|SHARP|TYPEDEF); + } + else +#endif + { + if ((flags & (DEFINE|SHARP)) == (DEFINE|SHARP)) + { + *(ip - 1) = 0; + op = strcopy(om, "#if defined(__STDC__) || defined(__STDPP__)\n"); + op = strcopy(op, im); + op = strcopy(op, "\n#else\n"); + bp = ip; + ip = im; + *op++ = *ip++; + while (*op = *ip++) + if (*op++ == '#' && *ip != '(') + { + op--; + while (*--op == ' ' || *op == '\t'); + if (*ip == '#') + { + op = strcopy(op + 1, "/**/"); + while (*++ip == ' ' || *ip == '\t'); + } + else + { + if (*op != '"') *++op = '"'; + op++; + while (*ip == ' ' || *ip == '\t') ip++; + while ((c = *ip) >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '_') *op++ = *ip++; + while (*ip == ' ' || *ip == '\t') ip++; + if (*ip == '"') ip++; + else *op++ = '"'; + } + } + ip = bp; + op = strcopy(op, "\n#endif\n"); + op = linesync(proto, op, proto->line); + } + flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|MATCH|OTHER|SHARP|SKIP|TOKENS|TYPEDEF); + } + call = 0; + group = 0; + paren = 0; + last = '\n'; + } + if (paren == 0 && (flags & (MATCH|RECURSIVE|SKIP|SLIDE)) == SLIDE) + { +#if PROTOMAIN + if (flags & EXTERN) BACKOUT(); +#endif + SYNC(); + return 0; + } + goto fsm_start; + + case S_QUAL: + PUTCHR(c); + rp = fsm[NEXT(state)]; + bp = ip; + goto fsm_get; + + case S_TOK: + PUTCHR(c); + c = TYPE(state); + break; + + case S_TOKB: + UNGETCHR(); + c = TYPE(state); + break; + + case S_RESERVED: + UNGETCHR(); + c = T_ID; + if (!(flags & DECLARE)) switch (RESERVED(*proto->tp, *(ip - 1), ip - proto->tp)) + { + case RESERVED('N', 'N', 3): + if (proto->tp[1] == 'o') + c = T_DO; + break; + case RESERVED('d', 'o', 2): + c = T_DO; + break; + case RESERVED('e', 'e', 4): + if (!(flags & RECURSIVE) && (flags & (DIRECTIVE|TOKENS)) != DIRECTIVE && !strncmp(proto->tp, "else", 4)) + { + c = T_ELSE; + goto fsm_id; + } + break; + case RESERVED('e', 'n', 6): + if (!strncmp(proto->tp, "extern", 6)) + c = T_EXTERN; + break; + case RESERVED('f', 'r', 3): + if (!(flags & RECURSIVE) && !strncmp(proto->tp, "for", 3)) + { + c = T_FOR; + goto fsm_id; + } + break; + case RESERVED('i', 'f', 2): + c = T_IF; + break; + case RESERVED('i', 'e', 6): + if (!strncmp(proto->tp, "inline", 6) && !(flags & (MATCH|SKIP|TOKENS|TYPEDEF)) && proto->brace == 0 && paren == 0 && group == 0 && (last == ';' || last == '}' || last == '\n' || last == 0)) + { + flags |= SKIP; + SYNC(); + line = proto->line; + op = strcopy(op - 6, "__INLINE__"); + SYNC(); + } + break; + case RESERVED('r', 'n', 6): + if (!(flags & RECURSIVE) && !strncmp(proto->tp, "return", 6)) + { + c = T_RETURN; + goto fsm_id; + } + break; + case RESERVED('s', 'c', 6): + if ((proto->options & EXTERNALIZE) && !strncmp(proto->tp, "static", 6)) + { + proto->ox = op - 6; + flags |= EXTERNALIZE; + } + break; + case RESERVED('t', 'f', 7): + if (!(flags & RECURSIVE) && !strncmp(proto->tp, "typedef", 7)) + { + flags |= TYPEDEF; + c = T_EXTERN; + } + break; + case RESERVED('v', 't', 8): + if (*ip == '(' && !strncmp(proto->tp, "va_start", 8)) c = T_VA_START; + break; + case RESERVED('v', 'd', 4): + if (!strncmp(proto->tp, "void", 4)) + { + if (flags & (CLASSIC|PLUSONLY|INIT_DEFINE|INIT_INCLUDE)) c = T_VOID; + else + { + SYNC(); + line = proto->line; + if (lex(proto, (flags & GLOBAL) | RECURSIVE) == '*') + { + memcopy(op - 4, "__V_", 4); + memcopy(ip - 4, "__V_", 4); + } + else c = T_VOID; + proto->line = line; + SYNC(); + bp = ip; + } + } + break; + case RESERVED('w', 'e', 5): + if (!(flags & RECURSIVE) && !strncmp(proto->tp, "while", 5)) + { + c = T_WHILE; + goto fsm_id; + } + break; + } +#if PROTOMAIN + if ((flags & CLASSIC) && c != T_EXTERN) + c = T_ID; +#endif + break; + + case S_VS: + goto fsm_start; + + case S_WS: + UNGETCHR(); +#if PROTOMAIN + if ((flags & (EXTERN|MATCH)) == EXTERN) + { + while (op > proto->ob && (*(op - 1) == ' ' || *(op - 1) == '\t')) + op--; + if (op > proto->ob && *(op - 1) != '\n') *op++ = ' '; + } +#endif + goto fsm_start; + + default: + if (state & SPLICE) + { + if (c == '\\') + { + if (!(n = GETCHR())) + { + goto fsm_eob; + fsm_splice: + c = '\\'; + n = GETCHR(); + } + if (n == '\n') + { + proto->line++; + PUTCHR('\\'); + PUTCHR('\n'); + bp = ip; + goto fsm_get; + } + UNGETCHR(); + } + state &= ~SPLICE; + if (state >= TERMINAL) + goto fsm_terminal; + rp = fsm[state]; + } + PUTCHR(c); + bp = ip; + goto fsm_get; + } + if (!(flags & (INIT_DEFINE|INIT_INCLUDE|RECURSIVE))) + { + if (!(flags & DIRECTIVE)) switch (c) + { + case '(': +#if PROTOMAIN + if (!(flags & CLASSIC) || proto->brace == 0) +#endif + { + if (paren++ == 0) + { +#if PROTOMAIN + if (!(flags & CLASSIC) || group <= 1) +#endif + { +#if PROTOMAIN + args = 0; +#endif + if (group++ == 0) group++; + else if (flags & INDIRECT) call++; + flags |= MATCH; + im = ip - 1; + om = op - 1; + } + sub = 0; + } + else if (paren == 2 && !aim) + { + sub++; + if (last == '(') + { + flags &= ~MATCH; + om = 0; + } + else if (flags & INDIRECT) + { + aim = ip - 1; + aom = op - 1; + } + else if ((flags & (MATCH|TOKENS)) == MATCH) + { + for (m = ip - 2; m > im && (*m == ' ' || *m == '\t'); m--); + if (m != im && sub == 1) + { + m = im + (*nns(ip) == '*'); + } + if (m == im) + { + flags &= ~MATCH; + om = 0; + } + } + else if ((flags & MATCH) && sub == 1 && *nns(ip) != '*') + { + flags &= ~MATCH; + om = 0; + } + } + flags &= ~TOKENS; + } + break; + case ')': +#if PROTOMAIN + if (!(flags & CLASSIC) || proto->brace == 0) +#endif + if (--paren == 0) + { +#if PROTOMAIN + if (flags & CLASSIC) + { + if (group != 2) + { + c = T_ID; + break; + } + group++; + } +#endif + ie = ip; + } + else if (paren == 1 && (flags & INDIRECT) && !aie) + aie = ip; + break; + case '*': + if (last == '(' && group == 2) + { + group--; + if (paren == 1) + { + flags |= INDIRECT; + aim = aie = 0; + } + } + break; + case '#': + dir = directive(ip, dir); + 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)) + flags |= DIRECTIVE; + else if (!(flags & (DECLARE|DIRECTIVE))) + { + flags |= DIRECTIVE; + if (!(flags & PLUSONLY)) + { + bp = ip; + while (*ip == ' ' || *ip == '\t') ip++; + if (*ip == 'l' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e') + { + if (*++ip == ' ' || *ip == '\t') + { + proto->line = 0; + while (*++ip >= '0' && *ip <= '9') + proto->line = proto->line * 10 + *ip - '0'; + proto->line--; + } + } +#if PROTOMAIN + else if ((flags & (CLASSIC|EXTERN)) == CLASSIC) + { + n = 0; + t = ip + 6; + while (ip < t && *ip >= 'a' && *ip <= 'z') + n = HASHKEYPART(n, *ip++); + switch (n) + { + case HASHKEY4('e','l','s','e'): + case HASHKEY5('e','n','d','i','f'): + while (*ip == ' ' || *ip == '\t') ip++; + if (*ip != '\n' && *ip != '/' && *(ip + 1) != '*') + { + flags |= JUNK|MATCH; + im = ip; + om = op + (ip - bp); + } + break; + case HASHKEY4('e','l','i','f'): + case HASHKEY5('e','r','r','o','r'): + case HASHKEY2('i','f'): + case HASHKEY5('i','f','d','e','f'): + case HASHKEY6('i','f','n','d','e','f'): + case HASHKEY5('u','n','d','e','f'): + break; + case HASHKEY6('i','n','c','l','u','d'): + if (*ip == 'e') ip++; + /*FALLTHROUGH*/ + case HASHKEY6('d','e','f','i','n','e'): + case HASHKEY6('p','r','a','g','m','a'): + if (*ip < 'a' || *ip > 'z') break; + /*FALLTHROUGH*/ + default: + flags |= JUNK|MATCH; + im = bp - 1; + om = op - 1; + break; + } + } + else +#endif + { + if (*ip == 'i' && *++ip == 'n' && *++ip == 'c' && *++ip == 'l' && *++ip == 'u' && *++ip == 'd' && *++ip == 'e') + { + while (*++ip == ' ' || *ip == '\t'); + if (*ip++ == '<' && *ip++ == 's' && *ip++ == 't' && *ip++ == 'd' && *ip++ == 'a' && *ip++ == 'r' && *ip++ == 'g' && *ip++ == '.' && *ip++ == 'h' && *ip++ == '>') + { + op = strcopy(op, "\ +if !defined(va_start)\n\ +#if defined(__STDARG__)\n\ +#include <stdarg.h>\n\ +#else\n\ +#include <varargs.h>\n\ +#endif\n\ +#endif\n\ +"); + op = linesync(proto, op, proto->line); + break; + } + } + else if (*ip == 'd' && *++ip == 'e' && *++ ip == 'f' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e' && (*++ip == ' ' || *ip == '\t')) + { + while (*++ip == ' ' || *ip == '\t'); + if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t')) + { + t = ip; + while (*++t == ' ' || *t == '\t'); + if (*t == 'e' && *++t == 'x' && *++ t == 't' && *++t == 'e' && *++t == 'r' && *++t == 'n' && (*++t == ' ' || *t == '\t' || *t == '\n' || *t == '\r')) + ip = t; + t = ip; + while (*++t == ' ' || *t == '\t'); + if (*t == '_' && *(t + 1) == '_') + { + op = strcopy(op, "undef __MANGLE__\n"); + op = linesync(proto, op, proto->line); + op = strcopy(op, "#define __MANGLE__ __LINKAGE__"); + break; + } + } + flags |= DEFINE|MATCH; + im = bp - 1; + om = op - 1; + } + else if (*ip == 'u' && *++ip == 'n' && *++ ip == 'd' && *++ip == 'e' && *++ip == 'f' && (*++ip == ' ' || *ip == '\t')) + { + while (*++ip == ' ' || *ip == '\t'); + if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t' || *ip == '\n' || *ip == '\r')) + { + op = strcopy(op, "undef __MANGLE__\n"); + op = linesync(proto, op, proto->line); + op = strcopy(op, "#define __MANGLE__ __LINKAGE__"); + break; + } + flags |= DEFINE|MATCH; + im = bp - 1; + om = op - 1; + } + } + ip = bp; + } + break; + } + else + break; + /*FALLTHROUGH*/ + case '{': + if (proto->brace++ == 0 && paren == 0) + { + if (last == '=') flags |= INIT; +#if PROTOMAIN + else if (flags & CLASSIC) + { + if ((flags & (MATCH|OTHER|SKIP)) == MATCH) + { + if (args) + { + v = number(op, args < 0 ? -args : args); + v = strcopy(v, " argument actual/formal mismatch"); + *v++ = ' '; + v = memcopy(v, im, ie - im); + *v = 0; + proto_error((char*)proto + sizeof(struct proto), 2, op, NiL); + } + ip--; + /*UNDENT...*/ + v = ie; + while (ie < ip) + if (*ie++ == '/' && *ie == '*') + { + e = ie - 1; + while (++ie < ip) + { + if (*ie == '*') + { + while (ie < ip && *ie == '*') ie++; + if (ie < ip && *ie == '/') + { + while (++ie < ip && (*ie == ' ' || *ie == '\t')); + while (e > v && (*(e - 1) == ' ' || *(e - 1) == '\t')) e--; + if (e > v && *e != '\n') *e++ = ' '; + t = ie; + while (--e >= v) + *--t = *e; + v = t; + break; + } + } + } + } + ie = v; + /*...INDENT*/ + op = om++; + if (flags & EXTERN) + { + v = op; + while (v > ko && *--v != ' '); + if (*v != ' ') + { + om = (v = (op += 4)) + 1; + while (v >= ko + 4) + { + *v = *(v - 4); + v--; + } + memcopy(ko, "int ", 4); + } + if (*v == ' ') + { + while (*(v + 1) == '*') + *v++ = '*'; + *v = '\t'; + if ((v - ko) <= 8) + { + om = (e = ++op) + 1; + while (e > v) + { + *e = *(e - 1); + e--; + } + } + } + om = (v = (op += 7)) + 1; + while (v >= ko + 7) + { + *v = *(v - 7); + v--; + } + memcopy(ko, "extern ", 7); + } + PUTCHR('('); + t = op; + e = 0; + /*UNDENT...*/ + while (ie < ip) + { + if ((c = *ie) == ' ' || c == '\t' || c == '\n') + { + while ((c = *++ie) == ' ' || c == '\t' || c == '\n'); + if (ie >= ip) break; + if (c != '*' && op > om) PUTCHR(' '); + } + if ((n = ((c = *ie) == ',')) || c == ';') + { + if (flags & EXTERN) + { + m = op; + while (op > om && ((c = *(op - 1)) == '(' || c == ')' || c == '[' || c == ']')) + op--; + v = op; + while (op > om && (c = *(op - 1)) != ' ' && c != '*') + op--; + while (*(op - 1) == ' ') + op--; + if (!e) + { + e = op; + while (e > om && *(e - 1) == '*') + e--; + } +#if _s5r4_386_compiler_bug_fixed_ + if (op <= om || *(op - 1) == ',' && (*op++ = ' ')) + op = strcopy(op, "int"); +#else + if (op <= om) + op = strcopy(op, "int"); + else if (*(op - 1) == ',') + op = strcopy(op, " int"); +#endif + while (v < m) + PUTCHR(*v++); + } + PUTCHR(','); + if (n) + { + if (x = !e) e = op - 1; + PUTCHR(' '); + m = t; + while (m < e) + PUTCHR(*m++); + if (x) + { + m = e; + while (*--e != ' '); + while (*(e - 1) == '*') e--; + op -= m - e; + } + } + while ((c = *++ie) == ' ' || c == '\t' || c == '\n'); + if (ie >= ip) UNPUTCHR(); + else PUTCHR(' '); + if (!n) + { + t = op; + e = 0; + } + } + else if (*ie == '*') + { + if (op > om && (c = *(op - 1)) == ' ') op--; + while (*ie == '*') PUTCHR(*ie++); + while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++; + if (c != '(') PUTCHR(' '); + } + else if (*ie == '(') + { + if (op > om && *(op - 1) == ' ') op--; + PUTCHR(*ie++); + while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++; + } + else if (*ie == ')') + { + if (op > om && *(op - 1) == '(') + proto_error((char*)proto + sizeof(struct proto), 1, "function pointer argument prototype omitted", NiL); + PUTCHR(*ie++); + while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++; + } + else if ((flags & EXTERN) && (op == om || *(op - 1) == ' ') && *ie == 'r' && !strncmp(ie, "register", 8) && (*(ie + 8) == ' ' || *(ie + 8) == '\t' || *(ie + 8) == '\n')) + { + ie += 8; + if (op > om) UNPUTCHR(); + } + else PUTCHR(*ie++); + } + /*...INDENT*/ + if (op <= om) op = strcopy(op, "void"); + PUTCHR(')'); + if (flags & EXTERN) + { + PUTCHR(';'); + PUTCHR('\n'); + SYNCOUT(); + KEEPOUT(); + } + else + { + PUTCHR('\n'); + PUTCHR(*ip); + } + ip++; + flags &= ~(MATCH|SKIP); + } + } +#endif + else if ((flags & (MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS)) + { + line = proto->line; + op = strcopy(om, " __PARAM__("); + op = memcopy(op, im, ie - im); + PUTCHR(','); + PUTCHR(' '); + PUTCHR('('); + flags &= ~(MATCH|SKIP); + if (flags & VARIADIC) + { + if ((vc = ie - im + 1) > sizeof(proto->variadic)) vc = sizeof(proto->variadic); + memcopy(proto->variadic, im, vc); + op = strcopy(op, "va_alist)) __OTORP__(va_dcl)\n{"); + } + else + { + flags |= SKIP; + proto->ip = im; + proto->op = op; + group = 0; + brack = 0; + for (;;) + { + switch (lex(proto, (flags & GLOBAL) | RECURSIVE)) + { + case '[': + brack++; + continue; + case ']': + brack--; + continue; + case '(': + if (paren++) group++; + continue; + case ')': + if (--paren == 0) + { + group = 0; + if (flags & MATCH) + { + flags &= ~(MATCH|SKIP); + op = memcopy(op, m, e - m); + } + break; + } + continue; + case ',': + if (paren == 1) + { + group = 0; + if (flags & MATCH) + { + flags &= ~(MATCH|SKIP); + op = memcopy(op, m, e - m); + } + PUTCHR(','); + PUTCHR(' '); + proto->op = op; + } + continue; + case T_ID: + if (group <= 1 && !brack) + { + flags |= MATCH; + m = proto->tp; + e = proto->ip; + } + continue; + default: + continue; + } + break; + } + PUTCHR(')'); + PUTCHR(')'); + } + if (!(flags & SKIP)) + { + flags |= SKIP; + proto->op = strcopy(op, " __OTORP__("); + proto->ip = im + 1; + n = *(ie - 1); + *(ie - 1) = ';'; + c = *ie; + *ie = 0; + lex(proto, (flags & GLOBAL) | DECLARE); + *(ie - 1) = n; + *ie = c; + proto->ip = ie; + op = proto->op; + PUTCHR(')'); + } + if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6); + op = linesync(proto, op, proto->line = line); + if (flags & DIRECTIVE) + { + proto->brace = 0; + PUTCHR('\n'); + PUTCHR('#'); + } + else if (!(flags & VARIADIC)) PUTCHR('{'); + } + } + flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP); + call = 0; + group = 0; + break; + case '}': + flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP|TOKENS); + if (--proto->brace == 0) + { + flags &= ~(INIT|VARIADIC|VARIADIC2); +#if PROTOMAIN + if (flags & EXTERN) BACKOUT(); +#endif + } + call = 0; + group = 0; + paren = 0; + break; + case '=': + if (last == '?') flags |= DIRECTIVE; + else if (paren == 0 && (flags & (INIT|MATCH|SKIP)) == MATCH) goto fsm_statement; + goto fsm_other; + case ',': +#if PROTOMAIN + if (flags & CLASSIC) + { + if (paren == 1) args++; + else + { + args--; + flags &= ~MATCH; + } + break; + } +#endif + if (paren == 0 && (flags & DECLARE)) *(op - 1) = c = ';'; + /*FALLTHROUGH*/ + case ';': + fsm_statement: + if (flags & INIT) /* ignore */; +#if PROTOMAIN + else if (flags & CLASSIC) + { + if (paren == 0) + { + if ((flags & MATCH) && last == ')') + flags &= ~MATCH; + if (!(flags & MATCH)) + { + call = 0; + group = 0; + flags &= ~SKIP; + if (flags & EXTERN) BACKOUT(); + if (flags & SLIDE) + { + SYNC(); + return 0; + } + } + else + { + args--; + if ((flags & (EXTERN|SKIP)) == (EXTERN|SKIP)) + BACKOUT(); + } + } + } +#endif + else if (paren == 0) + { + if ((flags & (MATCH|OTHER|SKIP)) == MATCH && call > 1) + { + if ((flags & MANGLE) && func) + { + func[0] = 'F'; + func[1] = 'U'; + func[2] = 'N'; + func[3] = 'C'; + func = 0; + } + if ((flags & (DECLARE|INDIRECT)) == INDIRECT && aim && aie < im) + { + while (aie < ip && (*aie == ' ' || *aie == '\t' || *aie == '\n')) aie++; + v = aim; + while (v < aie) + if (*v++ == ')') break; + while (v < aie && (*v == ' ' || *v == '\t' || *v == '\n')) v++; + if (v == aie || !(flags & PLUSPLUS)) + { + if (flags & PLUSPLUS) n = 3; + else if (v == aie && *v == '(') n = 10; + else n = 11; + ko = op; + om += n; + v = op += n; + while (v >= ko + n) + { + *v = *(v - n); + v--; + } + if (flags & PLUSPLUS) memcopy(aom, "(...))", 6); + else if (n == 10) memcopy(aom, "(__VARARG__))", 13); + else + { + ko = strcopy(aom, " __PROTO__("); + ko = memcopy(ko, aim, aie - aim); + *ko = ')'; + if (++ko >= om) + { + *ko++ = ')'; + om = ko; + } + } + } + } + else if (flags & TYPEDEF) + { + op = om; + while (*--op == ' ' || *op == '\t' || *op == '\n'); + if (*op != ')') + { + op = om += 14; + *--op = ')'; + while ((x = *(op - 14)) >= 'A' && x <= 'Z' || x >= 'a' && x <= 'z' || x >= '0' && x <= '9' || x == '_') + *--op = x; + memcopy(op - 13, "(__OTORP__(*)", 13); + } + } + if (flags & OTHER) + ; + else if (flags & PLUSPLUS) + { + op = om; + if (!(flags & TOKENS)) op = strcopy(op, "(...)"); + else op = memcopy(op, im, ie - im); + PUTCHR(c); + } + else + { + if (flags & DECLARE) op = strcopy(om, "()"); + else if (!(flags & TOKENS)) op = strcopy(om, "(__VARARG__)"); + else + { + op = strcopy(om, " __PROTO__("); + op = memcopy(op, im, ie - im); + PUTCHR(')'); + } + if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6); + PUTCHR(c); + } + flags &= ~(MATCH|VARIADIC|VARIADIC2); + if (c == ',' && !(flags & INDIRECT)) + { + call = 1; + group = 0; + break; + } + } + else if (flags & (OTHER|SKIP)) call = 0; + if (c == ';') + { + flags &= ~(EXTERNALIZE|MANGLE|TOKENS|TYPEDEF); + call = 0; + if (flags & SLIDE) + { + SYNC(); + return 0; + } + } + else call = call > 1 && c == ','; + group = 0; + flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP); + } + else if (paren == 1 && group == 1 && !(flags & (IDID|MANGLE))) flags |= TOKENS|OTHER; + break; + case T_DO: + case T_IF: + flags |= TOKENS|SKIP; + break; + case T_EXTERN: +#if PROTOMAIN + if (flags & CLASSIC) + { + if (proto->brace == 0) + flags |= SKIP; + } + else +#endif + if (paren == 0 && !(flags & TYPEDEF)) + { + flags |= MANGLE; + if (!(flags & PLUSONLY) || proto->package) + { + op = strcopy(op, " __MANGLE__"); + if (proto->package) + { + op = strcopy(op - 1, proto->package); + func = op + 1; + op = strcopy(op, "_DATA__"); + } + } + else + func = 0; + } + break; + case T_VARIADIC: + if (paren == 0 && (flags & (DECLARE|VARIADIC)) == DECLARE) + { + op -= 3; + SYNC(); + return c; + } + if (paren == 1 && !(flags & SKIP)) + flags |= VARIADIC; + flags |= TOKENS; + break; + case T_VOID: + goto fsm_id; + case T_VA_START: + if ((flags & (PLUSONLY|VARIADIC)) == VARIADIC) + { + flags &= ~MATCH; + line = proto->line; + op = strcopy(op - 8, "__VA_START__"); + SYNC(); + for (;;) + { + switch (lex(proto, (flags & GLOBAL) | RECURSIVE)) + { + case 0: + case ';': + break; + case T_ID: + if (!(flags & MATCH)) + { + flags |= MATCH; + m = proto->tp; + e = proto->ip; + } + continue; + default: + continue; + } + break; + } + CACHE(); + if (flags & MATCH) + { + v = m; + n = e - m; + } + else + { + v = "ap"; + n = 2; + } + op = strcopy(op, " __OTORP__("); + proto->ip = proto->variadic; + proto->op = op; + flags &= ~MATCH; + group = 0; + bp = proto->ip + 1; + if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9; + for (;;) + { + switch (lex(proto, (flags & GLOBAL) | RECURSIVE)) + { + case '(': + if (paren++) group++; + continue; + case ')': + if (--paren == 0) + { + if (flags & MATCH) + { + flags &= ~MATCH; + if (!(flags & VARIADIC2)) + { + op = memcopy(op, m, e - m); + op = strcopy(op, " = "); + } + op = strcopy(op, "va_arg("); + op = memcopy(op, v, n); + PUTCHR(','); + PUTCHR(' '); + if (m > bp) op = memcopy(op, bp, m - bp); + else op = strcopy(op, "int "); + if (group > 1) op = strcopy(op, ")()"); + else op = memcopy(op, e, proto->ip - e - 1); + PUTCHR(')'); + PUTCHR(';'); + } + group = 0; + break; + } + continue; + case ',': + if (paren == 1) + { + if (flags & MATCH) + { + flags &= ~MATCH; + if (!(flags & VARIADIC2)) + { + op = memcopy(op, m, e - m); + op = strcopy(op, " = "); + } + op = strcopy(op, "va_arg("); + op = memcopy(op, v, n); + PUTCHR(','); + PUTCHR(' '); + if (m > bp) op = memcopy(op, bp, m - bp); + else op = strcopy(op, "int "); + if (group > 1) op = strcopy(op, ")()"); + else op = memcopy(op, e, proto->ip - e - 1); + PUTCHR(')'); + PUTCHR(';'); + bp = proto->ip + 1; + if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9; + } + group = 0; + proto->op = op; + } + continue; + case T_ID: + if (group <= 1) + { + flags |= MATCH; + m = proto->tp; + e = proto->ip; + } + continue; + default: + continue; + } + break; + } + op = strcopy(op, ")"); + flags |= VARIADIC2; + proto->line = line; + call = 0; + break; + } + /*FALLTHROUGH*/ + case T_ID: + fsm_id: +#if PROTOMAIN + if (flags & CLASSIC) + { + if (!args && paren == 1) args++; + break; + } +#endif + if (paren == 0) + { + if (last == ')') + { + if (proto->brace == 0 && !(flags & DECLARE)) flags |= SKIP; + call = !call; + } + else if ((flags & SKIP) || c == T_ID || c == T_VOID) call++; + else flags |= SKIP; + if (last == T_ID) flags |= IDID; + } + c = T_ID; + flags |= TOKENS; + break; + case T_INVALID: + if (*proto->tp >= '0' && *proto->tp <= '9') + { + n = 0; + for (;; op--) + { + switch (*(op - 1)) + { + case 'f': + case 'F': + t = op; + while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); + if (*t == '.') + op--; + n = 0; + break; + case 'l': + case 'L': + if (!(n & 01)) + { + n |= 01; + t = op; + while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); + if (*t == '.') + { + n = 0; + op--; + break; + } + } + continue; + case 'u': + case 'U': + n |= 02; + continue; + } + break; + } + if (n & 01) + *op++ = 'L'; + if (n & 02) + { + m = op; + t = op = m + 10; + while ((c = *--m) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') + *--t = c; + c = *t; + strcopy(m + 1, "(unsigned)"); + *t = c; + break; + } + } + goto fsm_other; +#if PROTOMAIN + case '[': + if ((flags & CLASSIC) && paren == 0 && group <= 2) flags |= SKIP; + /*FALLTHROUGH*/ +#endif + default: + fsm_other: +#if PROTOMAIN + if (flags & CLASSIC) break; +#endif + flags |= TOKENS; + if (paren == 0) flags |= OTHER; + break; + } + else if (c == '#' && *ip != '(') flags |= SHARP; + last = c; +#if PROTOMAIN + if ((flags & (EXTERN|MATCH)) == (EXTERN|MATCH) && ((flags & (DIRECTIVE|SKIP)) || proto->brace || c != '(' && c != ')' && c != '*' && c != T_ID)) + CACHEOUT(); + else +#endif + SYNCOUT(); + goto fsm_start; + } + else if (flags & (INIT_DEFINE|INIT_INCLUDE)) + { +#if PROTOMAIN + if ((flags & YACC) && c == '%' && *ip == '{') t = 0; + else +#endif + { + if (c == '#') for (t = ip; *t == ' ' || *t == '\t'; t++); + else t = ""; + if (*t++ == 'i' && *t++ == 'f' && *t++ == 'n' && *t++ == 'd' && *t++ == 'e' && *t++ == 'f') + { +#if !PROTOMAIN + while (*t == ' ' || *t == '\t') t++; + if (*t != '_') +#endif + t = 0; + } + } + if (t) + { + ip = bp; + op = proto->op; + } + else while (*ip != '\n') *op++ = *ip++; + op = init(proto, op, flags); + op = linesync(proto, op, proto->line); + flags &= ~(INIT_DEFINE|INIT_INCLUDE); + proto->flags &= ~(INIT_DEFINE|INIT_INCLUDE); + goto fsm_start; + } + SYNC(); + return c; +} + +/* + * close a proto buffer stream + */ + +void +pppclose(char* iob) +{ + register struct proto* proto = (struct proto*)(iob - sizeof(struct proto)); + + if (proto->flags & MORE) close(proto->fd); + free((char*)proto); /* some ANSI cc's botch the free() prototype */ +} + +/* + * open a new proto buffer stream + * read buffer pointer returned + * 0 returned on error or if no magic + * + * file !=0 file path to open, otherwise use fd + * fd open file fd if file==0 + * notice !=0 copyright notice info commented at the top + * options !=0 additional notice name=value pairs, space or ; separated + * package !=0 generate header for this package + */ + +char* +pppopen(char* file, int fd, char* notice, char* options, char* package, char* comment, int flags) +{ + register struct proto* proto; + register char* iob; + register long n; + register char* s; + int pragma; + char* b; +#if PROTOMAIN + int comlen; + char com[80]; +#endif + int m = 0; + + static int retain; + + /* + * initialize proto + */ + +#if PROTOMAIN + if (flags & PROTO_CLASSIC) flags &= ~PROTO_INCLUDE; +#endif + if (flags & PROTO_RETAIN) flags &= ~retain; + else retain &= PROTO_INITIALIZED; + if (file && (fd = open(file, O_RDONLY)) < 0) return 0; +#if !PROTOMAIN + if ((n = lseek(fd, 0L, 2)) > 0) + { + if (lseek(fd, 0L, 0)) return 0; + if (n < CHUNK) n = CHUNK; + else if (n > 2 * BLOCK) n = 0; + m = 1; + } + if (n > 0) + { + /* + * file read in one chunk + */ + + if (!(proto = newof(0, struct proto, 1, 4 * n + 2))) + return 0; + proto->iz = n; + proto->oz = 3 * n; + n = 0; + } + else +#endif + { + /* + * file read in BLOCK chunks + */ + + n = BLOCK; + if (!(proto = newof(0, struct proto, 1, 5 * n + 2))) + return 0; + proto->iz = n; + proto->oz = 3 * n; + proto->flags |= MORE; + } + proto->fd = fd; + proto->package = package; + iob = (char*)proto + sizeof(struct proto); + proto->op = proto->ob = iob; + proto->ip = proto->ib = iob + proto->oz + n; + if (m) proto->options |= REGULAR; + if (!comment) + comment = "/*"; + if (!(proto->cc[0] = comment[0])) + notice = options = 0; + else if (comment[1]) + { + proto->cc[1] = comment[1]; + proto->cc[2] = comment[2] ? comment[2] : comment[0]; + } + else + proto->cc[1] = proto->cc[2] = comment[0]; + + /* + * read the first chunk + */ + + n = read(fd, proto->ip, proto->iz); + if (!(proto->flags & MORE)) + close(fd); + if (n < 0) + { + pppclose(iob); + return 0; + } + *(proto->ip + n) = 0; + + /* + * check for proto pragma in first block of lines + * pragma blanked out if found + * + * -1 no pragma + * 0 #pragma noprototyped + * 1 #pragma prototyped + * + * NOTE: matches may occur inside comments and quotes + */ + +#if PROTOMAIN + if (!notice && !options || (comlen = astlicense(com, sizeof(com), NiL, "type=check", proto->cc[0], proto->cc[1], proto->cc[2])) <= 0) + *com = 0; +#endif + pragma = -1; + s = proto->ip; + m = MAGICTOP; + while (m-- > 0 && *s) + { + while (*s == ' ' || *s == '\t') s++; + if (*s == '#') + { + b = s++; + while (*s == ' ' || *s == '\t') s++; + if (!strncmp(s, MAGICDIR, sizeof(MAGICDIR) - 1) && (*(s += sizeof(MAGICDIR) - 1) == ' ' || *s == '\t')) + { + while (*s == ' ' || *s == '\t') s++; + if (*s == 'n' && *(s + 1) == 'o') + { + s += 2; + pragma = -2; + } + if (!strncmp(s, MAGICARG, sizeof(MAGICARG) - 1) && (*(s += sizeof(MAGICARG) - 1) == ' ' || *s == '\t' || *s == '\n' || *s == '\r')) + while (*s) + { + if ((*(s - 1) == ' ' || *(s - 1) == '\t') && *s == *MAGICOFF && !strncmp(s, MAGICOFF, sizeof(MAGICOFF) - 1)) + notice = options = 0; + if (*s++ == '\n') + { + pragma += 2; +#if PROTOMAIN + if (!(flags & PROTO_DISABLE) || (flags & PROTO_NOPRAGMA)) +#endif + for (s--; b < s; *b++ = ' '); + goto magic; + } + } + pragma = -1; + } + } + else if (*s == '/' && !strncmp(s, MAGICGEN, sizeof(MAGICGEN) - 1)) + { + pragma = 0; + break; + } +#if PROTOMAIN + else if (*s == '%' && *(s + 1) == '{') + proto->flags |= YACC; + if (notice || options) + { + if (*s == *com && !strncmp(s, com, comlen)) + notice = options = 0; + else + while (*s) + { + if (*s == *NOTICED && !strncmp(s, NOTICED, sizeof(NOTICED) - 1)) + { + s += sizeof(NOTICED) - 1; + while (*s == ' ' || *s == '\t') + s++; + if (*s == '(' && (*(s + 1) == 'c' || *(s + 1) == 'C') && *(s + 2) == ')' || *s >= '0' && *s <= '9' && *(s + 1) >= '0' && *(s + 1) <= '9') + { + notice = options = 0; + break; + } + } + else if (*s++ == '\n') + { + s--; + break; + } + } + } +#endif + while (*s && *s++ != '\n'); + } + magic: + if (flags & PROTO_PLUSPLUS) proto->flags |= PLUSPLUS; + if (flags & PROTO_TEST) proto->test = 1; + if (flags & PROTO_EXTERNALIZE) proto->options |= EXTERNALIZE; +#if PROTOMAIN + if (flags & PROTO_CLASSIC) pragma = -pragma; + if (flags & PROTO_DISABLE) pragma = 0; + if (flags & PROTO_LINESYNC) proto->flags |= LINESYNC; + if (!(proto->flags & YACC) && file && (m = strlen(file)) > 2 && file[--m] == 'y' && file[--m] == '.') + proto->flags |= YACC; +#endif + if (pragma <= 0) + { + if (flags & PROTO_PLUSPLUS) + { + flags &= ~(PROTO_HEADER|PROTO_INCLUDE); + proto->flags |= PLUSONLY; + } + else if (!(flags & (PROTO_FORCE|PROTO_PASS))) + { + pppclose(iob); + return 0; + } + else if ((flags & (PROTO_FORCE|PROTO_PASS)) == PROTO_PASS || !pragma) + { + proto->flags |= PASS; + if (proto->flags & MORE) + proto->oz += proto->iz; + proto->iz = n; + if (notice || options) + { + if (proto->cc[0] == '#' && proto->ip[0] == '#' && proto->ip[1] == '!') + { + s = proto->ip; + while (*s && *s++ != '\n'); + m = s - proto->ip; + proto->op = memcopy(proto->op, proto->ip, m); + proto->ip = s; + proto->iz = n -= m; + } +#if PROTOMAIN + if (proto->cc[0]) + { + if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0) + proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL); + else + proto->op += comlen; + } + if (!(flags & PROTO_CLASSIC) && !(proto->flags & YACC)) +#endif + proto->op = linesync(proto, proto->op, 1); + proto->iz += proto->op - proto->ob; + } + memcopy(proto->op, proto->ip, n); + return iob; + } + } +#if PROTOMAIN + if (!(retain & PROTO_INITIALIZED)) + { + retain |= PROTO_INITIALIZED; + ppfsm(FSM_INIT, NiL); + } +#endif + proto->line = 1; +#if CHUNK >= 512 + if (notice || options || (flags & (PROTO_HEADER|PROTO_INCLUDE))) + { +#if PROTOMAIN + if (notice || options) + { + if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0) + proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL); + else + proto->op += comlen; + } +#endif + if (flags & PROTO_INCLUDE) + { + proto->flags |= INIT_INCLUDE; + if (flags & PROTO_RETAIN) + retain |= PROTO_INCLUDE; + } + else if (flags & PROTO_HEADER) + { + if (flags & PROTO_RETAIN) retain |= PROTO_HEADER; +#if PROTOMAIN + if (flags & PROTO_CLASSIC) + { + *proto->op++ = '#'; + proto->op = strcopy(proto->op, MAGICDIR); + *proto->op++ = ' '; + proto->op = strcopy(proto->op, MAGICARG); + *proto->op++ = '\n'; + } + else +#endif + proto->flags |= INIT_DEFINE; + } +#if PROTOMAIN + if (!(flags & PROTO_CLASSIC)) + { + if (proto->flags & YACC) + { + proto->op = strcopy(proto->op, "\n%{\n" + !notice); + proto->op = strcopy(proto->op, MAGICGEN); + proto->op = strcopy(proto->op, "%}\n"); + } + else + { + if (n || notice || options) + *proto->op++ = '\n'; + proto->op = strcopy(proto->op, MAGICGEN); + if (n) + proto->op = linesync(proto, proto->op, proto->line); + else if (proto->flags & (INIT_DEFINE|INIT_INCLUDE)) + proto->op = init(proto, proto->op, proto->flags); + } + } +#endif + } +#endif +#if PROTOMAIN + proto->file = file; + if (flags & PROTO_CLASSIC) + { + proto->flags |= CLASSIC; + if (!(flags & PROTO_HEADER)) proto->flags |= EXTERN; + } +#endif + return iob; +} + +/* + * read next proto'd chunk into iob + * the chunk is 0 terminated and its size is returned + */ + +int +pppread(char* iob) +{ + register struct proto* proto = (struct proto*)(iob - sizeof(struct proto)); + register int n; + + if (proto->flags & PASS) + { + if (proto->iz) + { + n = proto->iz; + proto->iz = 0; + } + else if (!(proto->flags & MORE)) n = 0; + else if ((n = read(proto->fd, proto->ob, proto->oz)) <= 0 || (proto->options & REGULAR) && n < proto->oz) + { + proto->flags &= ~MORE; + close(proto->fd); + } + } + else + { + if (proto->op == proto->ob) + { + if (proto->flags & ERROR) return -1; +#if PROTOMAIN + if (proto->flags & YACC) + { + register char* ip = proto->ip; + register char* op = proto->ob; + register char* ep = proto->ob + proto->oz - 2; + + if (!*ip) + { + ip = proto->ip = proto->ib; + if (!(proto->flags & MORE)) n = 0; + else if ((n = read(proto->fd, ip, proto->iz)) <= 0 || (proto->options & REGULAR) && n < proto->iz) + { + if (n < 0) n = 0; + proto->flags &= ~MORE; + close(proto->fd); + } + ip[n] = 0; + } + if (proto->flags & YACCSPLIT) + { + proto->flags &= ~YACCSPLIT; + if (*ip == '%') + { + *op++ = *ip++; + if (proto->flags & YACC2) proto->flags &= ~YACC; + else proto->flags |= YACC2; + } + } + if (proto->flags & YACC) + while (op < ep && (n = *op++ = *ip)) + { + ip++; + if (n == '%') + { + if (*ip == '%' && (ip == proto->ip + 1 || *(ip - 2) == '\n')) + { + *op++ = *ip++; + if (proto->flags & YACC2) proto->flags &= ~YACC; + else proto->flags |= YACC2; + break; + } + if (!*ip) + { + *op++ = '%'; + proto->flags |= YACCSPLIT; + break; + } + } + else if (n == '\n') proto->line++; + } + proto->op = memcopy(proto->ob, proto->ip, ip - proto->ip); + proto->ip = ip; + } + else +#endif + lex(proto, proto->flags); + if ((proto->flags & (ERROR|MORE)) == ERROR) + proto->op = strcopy(proto->op, "/* NOTE: some constructs may not have been converted */\n"); + } + n = proto->op - proto->ob; + proto->op = proto->ob; + } + return n; +} + +#if !PROTOMAIN + +/* + * drop control of iob after first pppread() + * return value is input fd + * if fd<0 then all data in iob + */ + +int +pppdrop(char* iob) +{ + register struct proto* proto = (struct proto*)(iob - sizeof(struct proto)); + + if (proto->flags & MORE) + { + proto->flags &= ~MORE; + return proto->fd; + } + return -1; +} + +#endif |