Logo Search packages:      
Sourcecode: ksh version File versions  Download package

ppproto.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*          Copyright (c) 1986-2007 AT&T Intellectual Property          *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                    by AT&T Intellectual Property                     *
*                                                                      *
*                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) 2007-09-21 $\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      */
#define PUBLICDOMAIN    "Public Domain"   /* 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;
                                    }
                              }
                              if (*s == *PUBLICDOMAIN && !strncmp(s, PUBLICDOMAIN, sizeof(PUBLICDOMAIN) - 1))
                              {
                                    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

Generated by  Doxygen 1.6.0   Back to index