/*********************************************************************** * * * 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 * * * ***********************************************************************/ #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 #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 \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 \n\ #else\n\ #include \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