296 lines
6.4 KiB
C
296 lines
6.4 KiB
C
|
/********************************************************************/
|
||
|
/** Microsoft LAN Manager **/
|
||
|
/** Copyright(c) Microsoft Corp., 1987-1990 **/
|
||
|
/********************************************************************/
|
||
|
|
||
|
#ifndef DEBUG
|
||
|
#ifndef NDEBUG // for assert()
|
||
|
#define NDEBUG // for assert()
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define INCL_NOCOMMON
|
||
|
#include <os2.h>
|
||
|
#include <stdio.h>
|
||
|
#include <assert.h>
|
||
|
#include <process.h>
|
||
|
#include "netcmds.h"
|
||
|
#include "interpre.h"
|
||
|
#include <msystem.h>
|
||
|
#include "os2incl.h"
|
||
|
#include "os2cmd.h"
|
||
|
|
||
|
#define STACKSIZE 20
|
||
|
#define RECURSE 10
|
||
|
|
||
|
/*
|
||
|
* XXSTKCHECK - checks the given expression. if true, then the stack
|
||
|
* is ok, else stack overflow will occur.
|
||
|
*/
|
||
|
#define xxstkcheck(cond) if(!(cond))xxovfl()
|
||
|
|
||
|
TOKSTACK *Tokptr, *Tokmax;
|
||
|
TOKSTACK Tokstack[STACKSIZE];
|
||
|
int Condition = FALSE;
|
||
|
int S_orstack[INTER_OR * 3 * RECURSE];
|
||
|
XX_USERTYPE S_frstack[INTER_FRAME * RECURSE];
|
||
|
|
||
|
extern TCHAR *xxswitch[];
|
||
|
|
||
|
/* Function Prototypes. */
|
||
|
|
||
|
XX_USERTYPE xx_parser(int, int *, int);
|
||
|
int XX_USERLEX(TOKSTACK *);
|
||
|
void xxinit(void);
|
||
|
void xxovfl(void);
|
||
|
int xxnext(void);
|
||
|
|
||
|
int (*XXulex)(TOKSTACK *) = XX_USERLEX;
|
||
|
int XXtoken = 0;
|
||
|
XX_USERTYPE XXnode = 0;
|
||
|
|
||
|
extern TCHAR *Rule_strings[];
|
||
|
extern SHORT Index_strings[];
|
||
|
/*
|
||
|
** XX_USERPARSE : this is what the user calls to parse a tree.
|
||
|
*/
|
||
|
XX_USERTYPE XX_USERPARSE(VOID)
|
||
|
{
|
||
|
xxinit();
|
||
|
return(xx_parser(XX_START,S_orstack,0));
|
||
|
}
|
||
|
/*
|
||
|
** xx_parser : this is what we call to actually parse the tree
|
||
|
*/
|
||
|
XX_USERTYPE xx_parser(pc,or_ptr,fp)
|
||
|
register int pc;
|
||
|
register int *or_ptr;
|
||
|
register int fp;
|
||
|
{
|
||
|
register int type;
|
||
|
register TOKSTACK *ptok;
|
||
|
int *or_start = or_ptr;
|
||
|
int fp_start = fp;
|
||
|
|
||
|
S_frstack[fp] = (XX_USERTYPE) 1;
|
||
|
while(1)
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon(TEXT("Current PC = %3d value = %4d type is "),pc,XXvalues[pc]);
|
||
|
#endif
|
||
|
switch(XXtype[pc])
|
||
|
{
|
||
|
case X_RULE :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_RULE\n"));
|
||
|
#endif
|
||
|
break;
|
||
|
case X_OR :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_OR\n"));
|
||
|
#endif
|
||
|
type = XXtype[pc + 1];
|
||
|
/*
|
||
|
** before we go through the bother of pushing a backup place,
|
||
|
** if the a token or a check and the current token
|
||
|
** does not match the value, then immediately update the pc
|
||
|
** to have the value of the X_OR.
|
||
|
** otherwise, save all the current info.
|
||
|
*/
|
||
|
if( ((type == X_TOKEN) || (type == X_CHECK))
|
||
|
&&
|
||
|
(XXvalues[pc + 1] != (SHORT) XXtoken))
|
||
|
{
|
||
|
pc = XXvalues[pc];
|
||
|
continue;
|
||
|
}
|
||
|
xxstkcheck(or_ptr < &S_orstack[DIMENSION(S_orstack) - 3]);
|
||
|
*(or_ptr++) = XXvalues[pc]; /* link to next subsection */
|
||
|
*(or_ptr++) = fp; /* the current frame ptr */
|
||
|
*(or_ptr++) = (int)(Tokptr - Tokstack); /* the Tokstack index */
|
||
|
break;
|
||
|
case X_PROC :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_PROC\n"));
|
||
|
#endif
|
||
|
xxstkcheck(fp < (DIMENSION(S_frstack) - 1));
|
||
|
if( ! (S_frstack[fp] = xx_parser(XXvalues[pc],or_ptr,fp)))
|
||
|
{
|
||
|
goto backout;
|
||
|
}
|
||
|
fp++;
|
||
|
break;
|
||
|
case X_CHECK :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_CHECK\n"));
|
||
|
#endif
|
||
|
if(XXtoken != XXvalues[pc])
|
||
|
{
|
||
|
goto backout;
|
||
|
}
|
||
|
break;
|
||
|
case X_SWITCH :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_SWITCH\n"));
|
||
|
#endif
|
||
|
/* if "/anything" was in the grammar, we call this
|
||
|
* routine for an implementation defined switch
|
||
|
* check, passing the text of the string as an argument.
|
||
|
*/
|
||
|
if(!CheckSwitch(xxswitch[XXvalues[pc]]))
|
||
|
{
|
||
|
goto backout;
|
||
|
}
|
||
|
break;
|
||
|
case X_ANY :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_ANY\n"));
|
||
|
#endif
|
||
|
/* match anything */
|
||
|
xxstkcheck(fp < DIMENSION(S_frstack));
|
||
|
S_frstack[fp++] = XXnode; /* must be here, read comment */
|
||
|
if (XXtoken == EOS)
|
||
|
goto backout;
|
||
|
else
|
||
|
xxnext();
|
||
|
break;
|
||
|
case X_TOKEN :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_TOKEN\n"));
|
||
|
#endif
|
||
|
xxstkcheck(fp < DIMENSION(S_frstack));
|
||
|
/*
|
||
|
** we first save the node, then check the token, since
|
||
|
** if the tokens match, xxlex will get the next one and we'll
|
||
|
** lose the current one of interest.
|
||
|
*/
|
||
|
S_frstack[fp++] = XXnode; /* must be here, read comment */
|
||
|
if(XXvalues[pc] != (SHORT) XXtoken)
|
||
|
{
|
||
|
goto backout;
|
||
|
}
|
||
|
else
|
||
|
xxnext();
|
||
|
break;
|
||
|
case X_CONDIT :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_CONDIT\n"));
|
||
|
#endif
|
||
|
if( ! xxcondition(XXvalues[pc], &S_frstack[fp_start]))
|
||
|
{
|
||
|
goto backout;
|
||
|
}
|
||
|
break;
|
||
|
case X_ACTION :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_ACTION\n"));
|
||
|
#endif
|
||
|
xxaction(XXvalues[pc],&S_frstack[fp_start]);
|
||
|
break;
|
||
|
case X_ACCEPT :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_ACCEPT\n"));
|
||
|
#endif
|
||
|
return(S_frstack[fp_start]);
|
||
|
case X_DEFINE :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_DEFINE\n"));
|
||
|
#endif
|
||
|
break;
|
||
|
/*
|
||
|
**case X_PUSH :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("X_PUSH\n"));
|
||
|
#endif
|
||
|
** ppush(XXvalues[pc],S_frstack[fp_start]);
|
||
|
** break;
|
||
|
*/
|
||
|
default :
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("UNKNOWN\n"));
|
||
|
#endif
|
||
|
assert(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
pc++;
|
||
|
continue;
|
||
|
|
||
|
backout: /* BACK OUT !!! recover an earlier state */
|
||
|
|
||
|
if(or_ptr != or_start)
|
||
|
{
|
||
|
/*
|
||
|
** reset the 'or' stack
|
||
|
*/
|
||
|
Tokptr = ptok = Tokstack + *(--or_ptr);
|
||
|
XXtoken = ptok->token;
|
||
|
XXnode = ptok->node;
|
||
|
fp = *(--or_ptr);
|
||
|
pc = *(--or_ptr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return((XX_USERTYPE) 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
** xxinit - Clear the input stack and get the first token.
|
||
|
**/
|
||
|
VOID
|
||
|
xxinit(VOID)
|
||
|
{
|
||
|
register TOKSTACK *ptok;
|
||
|
|
||
|
/* fill the first one with a token */
|
||
|
Tokmax = Tokptr = ptok = &Tokstack[0];
|
||
|
(*XXulex)(ptok);
|
||
|
XXtoken = ptok->token;
|
||
|
XXnode = ptok->node;
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("xxinit, new token value is %d\n"),XXtoken);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** XXOVFL - a common subexpression, used in xxstkcheck macro above
|
||
|
**/
|
||
|
VOID
|
||
|
xxovfl(VOID)
|
||
|
{
|
||
|
GenOutput(g_hStdErr, TEXT("PANIC: expression too complex, please simplify;"));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XXLEX - If a match occurs, get the next input token and return TRUE.
|
||
|
* Otherwise return FALSE. If backup has occured, the token will be
|
||
|
* fetched from the token stack. Otherwise the user routine will be called.
|
||
|
*/
|
||
|
int
|
||
|
xxnext(VOID)
|
||
|
{
|
||
|
register TOKSTACK *ptok;
|
||
|
|
||
|
ptok = ++Tokptr;
|
||
|
xxstkcheck(ptok < &Tokstack[DIMENSION(Tokstack)]);
|
||
|
if (ptok > Tokmax)
|
||
|
{
|
||
|
(*XXulex)(ptok);
|
||
|
Tokmax++;
|
||
|
}
|
||
|
|
||
|
XXtoken = ptok->token;
|
||
|
XXnode = ptok->node;
|
||
|
#ifdef DEBUG
|
||
|
WriteToCon( TEXT("xxnext, new token value is %d\n"),XXtoken);
|
||
|
#endif
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
#if XX_XACCLEX
|
||
|
XXlex(VOID)
|
||
|
{
|
||
|
}
|
||
|
#endif
|