/*
 * Bob Denny 28-Aug-82  Remove reference to stdio.h
 * Remove code to default lexin, change to call to
 * llstin(), generated by lex depending upon setting
 * of "-s" switch.  Eliminates hardwired dependency
 * on standard I/O library.  Moved declaration of
 * lexin to lexgetc().
 *
 * Bob Denny 31-Aug-82  Add call to lexswitch() in
 * the generated file, to switch to the table whose
 * name was given in the "-t" switch (or to "lextab"
 * if "-t" wasn't given).  Removed hardwired setting
 * of _tabp --> "lextab" here. Now handled automagically.
 *
 * Bob Denny 21-Oct-82  Add llinit() function to re-initialize
 * yylex(), making it serially reusable.
 *
 * Initialize _tabp to NULL so lexswitch() to real table happens
 * only once.
 *
 * Bob Denny 15-Apr-83 Move NBPW to LEX.H and make it 32 on VAX native,
 *                     else 16.
 * Scott Guthery 20-Nov-83      Adapt for IBM PC & DeSmet C
 * William Lee 28-Dec-86 Adapt for Commodore-Amiga 1000 and Lattice C
 */

/*
 * yylex for lex tables
 */

#include "lex.h"

#define ERROR   256     /* yacc's value */

tst__b(c, tab)
register int    c;
char            tab[];
{
        return(tab[(c >> 3) & 037] & (1 << (c & 07)) );
}

struct  lextab  *_tabp = 0;

extern char     *llsave[];      /* Right-context buffer                 */
char    llbuf[100];             /* work buffer                          */
char    *llp1   = &llbuf[0];    /* pointer to next avail. in token      */
char    *llp2   = &llbuf[0];    /* pointer to end of lookahead          */
char    *llend  = &llbuf[0];    /* pointer to end of token              */
char    *llebuf = &llbuf[sizeof llbuf];
int     lleof;
int     yylval  = 0;
int     yyline  = 0;

yylex()
{
        register int c, st;
        int final, l, llk, i;
        register struct lextab *lp;
        char *cp;

        /*
         * Call llstin() to default lexin to stdin
         * and assign _tabp to "real" table.
         */
        llstin();                       /* Initialize yylex() variables */

loop:
        llk = 0;
        if (llset())
                return(0);              /* Prevent EOF loop     */
        st = 0;
        final = -1;
        lp = _tabp;

        do {
                if (lp->lllook && (l = lp->lllook[st])) {
                        for (c=0; c<NBPW; c++)
                                if (l&(1<<c))
                                        llsave[c] = llp1;
                        llk++;
                }
                if ((i = lp->llfinal[st]) != -1) {
                        final = i;
                        llend = llp1;
                }
                if ((c = llinp()) < 0)
                        break;
                if ((cp = lp->llbrk) && llk==0 && tst__b(c, cp)) {
                        llp1--;
                        break;
                }
        } while ((st = (*lp->llmove)(lp, c, st)) != -1);


        if (llp2 < llp1)
                llp2 = llp1;
        if (final == -1) {
                llend = llp1;
                if (st == 0 && c < 0)
                        return(0);
                if ((cp = lp->llill) && tst__b(c, cp)) {
                        lexerror("Illegal character: %c (%03o)", c, c);
                        goto loop;
                }
                return(ERROR);
        }
        if (c = (final >> 11) & 037)
                llend = llsave[c-1];
        if ((c = (*lp->llactr)(final&03777)) >= 0)
                return(c);
        goto loop;
}

llinp()
{
        register c;
        register struct lextab *lp;
        register char *cp;

        lp = _tabp;
        cp = lp->llign;                         /* Ignore class         */
        for (;;) {
                /*
                 * Get the next character from the save buffer (if possible)
                 * If the save buffer's empty, then return EOF or the next
                 * input character.  Ignore the character if it's in the
                 * ignore class.
                 */
                c = (llp1 < llp2) ? *llp1 & 0377 : (lleof) ? EOF : lexgetc();
                if (c >= 0) {                   /* Got a character?     */
                        if (cp && tst__b(c, cp))
                                continue;       /* Ignore it            */
                        if (llp1 >= llebuf) {   /* No, is there room?   */
                                lexerror("Token buffer overflow");
                                exit(1);
                        }
                        *llp1++ = c;            /* Store in token buff  */
                } else
                        lleof = 1;              /* Set EOF signal       */
                return(c);
        }
}

llset()
/*
 * Return TRUE if EOF and nothing was moved in the look-ahead buffer
 */
{
        register char *lp1, *lp2;

        for (lp1 = llbuf, lp2 = llend; lp2 < llp2;)
                *lp1++ = *lp2++;
        llend = llp1 = llbuf;
        llp2 = lp1;
        return(lleof && lp1 == llbuf);
}

/*
 * Re-initialize yylex() so that it can be re-used on
 * another file.
 */
llinit()
   {
   llp1 = llp2 = llend = llbuf;
   llebuf = llbuf + sizeof(llbuf);
   lleof = yylval = yyline = 0;
   }
