Category : OS/2 Files
Archive   : KSH48.ZIP
Filename : SYN.C

 
Output of file : SYN.C contained in archive : KSH48.ZIP
/*
* shell parser (C version)
*/

#ifndef lint
static char *RCSid = "$Id: syn.c,v 1.3 1992/08/10 12:03:10 sjg Exp $";
#endif

#include "stdh.h"
#include
#include
#include "sh.h"
#include "expand.h"

static struct op *pipeline ARGS((int cf));
static struct op *andor ARGS((void));
static struct op *c_list ARGS((void));
static struct ioword *synio ARGS((int cf));
static void musthave ARGS((int c, int cf));
static struct op *nested ARGS((int type, int mark));
static struct op *command ARGS((int cf));
static struct op *dogroup ARGS((int onlydone));
static struct op *thenpart ARGS((void));
static struct op *elsepart ARGS((void));
static struct op *caselist ARGS((void));
static struct op *casepart ARGS((void));
static char ** wordlist ARGS((void));
static struct op *block ARGS((int type, struct op *t1, struct op *t2, char **wp));
static struct op *newtp ARGS((int type));
static void zzerr ARGS((void));

static struct op *outtree; /* yyparse output */

static int reject; /* token(cf) gets symbol again */
static int symbol; /* yylex value */

#define REJECT (reject = 1)
#define ACCEPT (reject = 0)
#define token(cf) \
((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
#define tpeek(cf) \
((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))

int
yyparse()
{
ACCEPT;
yynerrs = 0;
if ((tpeek(KEYWORD|ALIAS)) == 0) { /* EOF */
outtree = newtp(TEOF);
return 0;
}
outtree = c_list();
musthave('\n', 0);
return (yynerrs != 0);
}

static struct op *
pipeline(cf)
int cf;
{
register struct op *t, *p, *tl = NULL;
register int c;

t = command(cf);
if (t != NULL) {
while ((c = token(0)) == '|') {
if ((p = command(CONTIN)) == NULL)
SYNTAXERR;
if (tl == NULL)
t = tl = block(TPIPE, t, p, NOWORDS);
else
tl = tl->right = block(TPIPE, tl->right, p, NOWORDS);
/*t = block(TPIPE, t, p, NOWORDS);*/
}
REJECT;
}
return (t);
}

static struct op *
andor()
{
register struct op *t, *p;
register int c;

t = pipeline(0);
if (t != NULL) {
while ((c = token(0)) == LOGAND || c == LOGOR) {
if ((p = pipeline(CONTIN)) == NULL)
SYNTAXERR;
t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
}
REJECT;
}
return (t);
}

static struct op *
c_list()
{
register struct op *t, *p, *tl = NULL;
register int c;

t = andor();
if (t != NULL) {
while ((c = token(0)) == ';' || c == '&' ||
((multiline || source->type == SSTRING
|| (source->type == SALIAS)) && c == '\n')) {
if (c == '&') {
if (tl)
tl->right = block(TASYNC, tl->right, NOBLOCK, NOWORDS);
else
t = block(TASYNC, t, NOBLOCK, NOWORDS);
}
if ((p = andor()) == NULL)
return (t);
if (tl == NULL)
t = tl = block(TLIST, t, p, NOWORDS);
else
tl = tl->right = block(TLIST, tl->right, p, NOWORDS);
}
REJECT;
}
return (t);
}

static struct ioword *
synio(cf)
int cf;
{
register struct ioword *iop;

if (tpeek(cf) != REDIR)
return NULL;
ACCEPT;
iop = yylval.iop;
musthave(LWORD, 0);
iop->name = yylval.cp;
if ((iop->flag&IOTYPE) == IOHERE) {
if (*ident != 0) /* unquoted */
iop->flag |= IOEVAL;
if (herep >= &heres[HERES])
errorf("too many <<'s\n");
*herep++ = iop;
}
return iop;
}

static void
musthave(c, cf)
int c, cf;
{
if ((token(cf)) != c)
SYNTAXERR;
}

static struct op *
nested(type, mark)
int type, mark;
{
register struct op *t;

multiline++;
t = c_list();
musthave(mark, KEYWORD);
multiline--;
return (block(type, t, NOBLOCK, NOWORDS));
}

static struct op *
command(cf)
int cf;
{
register struct op *t;
register int c, iopn = 0;
struct ioword *iop, **iops;
XPtrV args, vars;

iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1), ATEMP);
XPinit(args, 16);
XPinit(vars, 16);

if (multiline)
cf = CONTIN;
cf |= KEYWORD|ALIAS;

while ((iop = synio(cf)) != NULL) {
if (iopn >= NUFILE)
yyerror("too many redirections");
iops[iopn++] = iop;
cf &=~ CONTIN;
}

switch (c = token(cf)) {
case 0:
yyerror("unexpected EOF");
return NULL;

default:
REJECT;
if (iopn == 0)
return NULL; /* empty line */
t = newtp(TCOM);
break;

case LWORD:
case MDPAREN:
REJECT;
t = newtp(TCOM);
if (c == MDPAREN) {
ACCEPT;
XPput(args,"let");
musthave(LWORD,LETEXPR);
XPput(args,yylval.cp);
}
while (1)
switch (tpeek(0)) {
case REDIR:
if (iopn >= NUFILE)
yyerror("too many redirections");
iops[iopn++] = synio(0);
break;

case LWORD:
ACCEPT;
if ((XPsize(args) == 0 || flag[FKEYWORD])
&& strchr(ident+1, '='))
{XPput(vars, yylval.cp);}
else
{XPput(args, yylval.cp);}
break;

case MPAREN:
ACCEPT;
if (XPsize(args) != 1)
SYNTAXERR;
if (*ident == 0)
yyerror("invalid function name\n");
t = newtp(TFUNCT);
t->str = strsave(ident, ATEMP);
musthave('{', CONTIN|KEYWORD);
t->left = nested(TBRACE, '}');
return t;

default:
goto Leave;
}
Leave:
break;

case '(':
t = nested(TPAREN, ')');
break;

case '{':
t = nested(TBRACE, '}');
break;

case FOR:
case SELECT:
t = newtp((c == FOR) ? TFOR: TSELECT);
musthave(LWORD, 0);
t->str = strsave(ident, ATEMP);
multiline++;
t->vars = wordlist();
t->left = dogroup(0);
multiline--;
break;

case WHILE:
case UNTIL:
multiline++;
t = newtp((c == WHILE) ? TWHILE: TUNTIL);
t->left = c_list();
t->right = dogroup(1);
multiline--;
break;

case CASE:
t = newtp(TCASE);
musthave(LWORD, 0);
t->str = yylval.cp;
multiline++;
musthave(IN, KEYWORD|CONTIN);
t->left = caselist();
musthave(ESAC, KEYWORD);
multiline--;
break;

case IF:
multiline++;
t = newtp(TIF);
t->left = c_list();
t->right = thenpart();
musthave(FI, KEYWORD);
multiline--;
break;

case TIME:
t = pipeline(CONTIN);
t = block(TTIME, t, NOBLOCK, NOWORDS);
break;

case FUNCTION:
t = newtp(TFUNCT);
musthave(LWORD, 0);
t->str = strsave(ident, ATEMP);
musthave('{', CONTIN|KEYWORD);
t->left = nested(TBRACE, '}');
break;

#if 0
case MDPAREN:
t = newtp(TCOM);
XPput(args, "let");
musthave(LWORD, LETEXPR);
XPput(args, yylval.cp);
while (tpeek(0) == REDIR) {
if (iopn >= NUFILE)
yyerror("too many redirections");
iops[iopn++] = synio(0);
}
break;
#endif
}

while ((iop = synio(0)) != NULL) {
if (iopn >= NUFILE)
yyerror("too many redirections");
iops[iopn++] = iop;
}

if (iopn == 0) {
afree((void*) iops, ATEMP);
t->ioact = NULL;
} else {
iops[iopn++] = NULL;
aresize((void*) iops, sizeofN(struct ioword *, iopn), ATEMP);
t->ioact = iops;
}

if (t->type == TCOM) {
XPput(args, NULL);
t->args = (char **) XPclose(args);
XPput(vars, NULL);
t->vars = (char **) XPclose(vars);
} else {
XPfree(args);
XPfree(vars);
}

return t;
}

static struct op *
dogroup(onlydone)
int onlydone;
{
register int c;
register struct op *list;

c = token(CONTIN|KEYWORD);
if (c == DONE && onlydone)
return NULL;
if (c != DO)
SYNTAXERR;
list = c_list();
musthave(DONE, KEYWORD);
return list;
}

static struct op *
thenpart()
{
register int c;
register struct op *t;

if ((c = token(0)) != THEN) {
REJECT;
return NULL;
}
t = newtp(0);
t->left = c_list();
if (t->left == NULL)
SYNTAXERR;
t->right = elsepart();
return (t);
}

static struct op *
elsepart()
{
register int c;
register struct op *t;

switch (c = token(0)) {
case ELSE:
if ((t = c_list()) == NULL)
SYNTAXERR;
return (t);

case ELIF:
t = newtp(TELIF);
t->left = c_list();
t->right = thenpart();
return (t);

default:
REJECT;
return NULL;
}
}

static struct op *
caselist()
{
register struct op *t, *tl;

t = tl = NULL;
while ((tpeek(CONTIN|KEYWORD)) != ESAC) {
struct op *tc = casepart();
if (tl == NULL)
t = tl = tc, tl->right = NULL;
else
tl->right = tc, tl = tc;
}
return (t);
}

static struct op *
casepart()
{
register struct op *t;
register int c, cf;
XPtrV ptns;

XPinit(ptns, 16);
t = newtp(TPAT);
cf = CONTIN|KEYWORD;
c = token(cf);
if (c != '(')
REJECT;
else
cf = 0;
do {
musthave(LWORD, cf);
XPput(ptns, yylval.cp);
cf = 0;
} while ((c = token(0)) == '|');
REJECT;
XPput(ptns, NULL);
t->vars = (char **) XPclose(ptns);
musthave(')', 0);

t->left = c_list();
if ((tpeek(CONTIN|KEYWORD)) != ESAC)
musthave(BREAK, CONTIN|KEYWORD);
return (t);
}

static char **
wordlist()
{
register int c;
XPtrV args;

XPinit(args, 16);
if ((c = token(CONTIN|KEYWORD)) != IN) {
REJECT;
return NULL;
}
while ((c = token(0)) == LWORD)
XPput(args, yylval.cp);
if (c != '\n' && c != ';')
SYNTAXERR;
if (XPsize(args) == 0) {
XPfree(args);
return NULL;
} else {
XPput(args, NULL);
return (char **) XPclose(args);
}
}

/*
* supporting functions
*/

static struct op *
block(type, t1, t2, wp)
struct op *t1, *t2;
char **wp;
{
register struct op *t;

t = newtp(type);
t->left = t1;
t->right = t2;
t->vars = wp;
return (t);
}

const struct res {
char *name;
int val;
} restab[] = {
"for", FOR,
"select", SELECT,
"case", CASE,
"esac", ESAC,
"while", WHILE,
"do", DO,
"done", DONE,
"if", IF,
"in", IN,
"then", THEN,
"else", ELSE,
"elif", ELIF,
"until", UNTIL,
"fi", FI,
"function", FUNCTION,
"time", TIME,
"{", '{',
"}", '}',
0
};

keywords()
{
register struct res const *rp;
register struct tbl *p;

for (rp = restab; rp->name; rp++) {
p = tenter(&lexicals, rp->name, hash(rp->name));
p->flag |= DEFINED|ISSET;
p->type = CKEYWD;
p->val.i = rp->val;
}
}

static struct op *
newtp(type)
int type;
{
register struct op *t;

t = (struct op *) alloc(sizeof(*t), ATEMP);
t->type = type;
t->args = t->vars = NULL;
t->ioact = NULL;
t->left = t->right = NULL;
t->str = NULL;
return (t);
}

static void
zzerr()
{
yyerror("syntax error");
}

struct op *
compile(s)
Source *s;
{
yynerrs = 0;
multiline = 0;
herep = heres;
source = s;
if (yyparse())
unwind();
if (s->type == STTY || s->type == SFILE || s->type == SHIST)
s->str = null; /* line is not preserved */
return outtree;
}



  3 Responses to “Category : OS/2 Files
Archive   : KSH48.ZIP
Filename : SYN.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/