Home | History | Annotate | Line # | Download | only in ksh
syn.c revision 1.1.1.3
      1      1.1  jtc /*
      2      1.1  jtc  * shell parser (C version)
      3      1.1  jtc  */
      4      1.1  jtc 
      5      1.1  jtc #include "sh.h"
      6      1.1  jtc #include "c_test.h"
      7      1.1  jtc 
      8      1.1  jtc struct multiline_state {
      9      1.1  jtc 	int	on;		/* set in multiline commands (\n becomes ;) */
     10      1.1  jtc 	int	start_token;	/* token multiline is for (eg, FOR, {, etc.) */
     11      1.1  jtc 	int	start_line;	/* line multiline command started on */
     12      1.1  jtc };
     13      1.1  jtc 
     14      1.1  jtc static void	yyparse		ARGS((void));
     15      1.1  jtc static struct op *pipeline	ARGS((int cf));
     16      1.1  jtc static struct op *andor		ARGS((void));
     17      1.1  jtc static struct op *c_list	ARGS((void));
     18      1.1  jtc static struct ioword *synio	ARGS((int cf));
     19      1.1  jtc static void	musthave	ARGS((int c, int cf));
     20      1.1  jtc static struct op *nested	ARGS((int type, int smark, int emark));
     21      1.1  jtc static struct op *get_command	ARGS((int cf));
     22      1.1  jtc static struct op *dogroup	ARGS((void));
     23      1.1  jtc static struct op *thenpart	ARGS((void));
     24      1.1  jtc static struct op *elsepart	ARGS((void));
     25      1.1  jtc static struct op *caselist	ARGS((void));
     26      1.1  jtc static struct op *casepart	ARGS((int endtok));
     27      1.1  jtc static struct op *function_body	ARGS((char *name, int ksh_func));
     28      1.1  jtc static char **	wordlist	ARGS((void));
     29      1.1  jtc static struct op *block		ARGS((int type, struct op *t1, struct op *t2,
     30      1.1  jtc 				      char **wp));
     31      1.1  jtc static struct op *newtp		ARGS((int type));
     32      1.1  jtc static void	syntaxerr	ARGS((const char *what))
     33      1.1  jtc 						GCC_FUNC_ATTR(noreturn);
     34      1.1  jtc static void	multiline_push ARGS((struct multiline_state *save, int tok));
     35      1.1  jtc static void	multiline_pop ARGS((struct multiline_state *saved));
     36      1.1  jtc static int	assign_command ARGS((char *s));
     37  1.1.1.3  jtc static int	inalias ARGS((struct source *s));
     38      1.1  jtc #ifdef KSH
     39      1.1  jtc static int	dbtestp_isa ARGS((Test_env *te, Test_meta meta));
     40      1.1  jtc static const char *dbtestp_getopnd ARGS((Test_env *te, Test_op op,
     41      1.1  jtc 					int do_eval));
     42      1.1  jtc static int	dbtestp_eval ARGS((Test_env *te, Test_op op, const char *opnd1,
     43      1.1  jtc 				const char *opnd2, int do_eval));
     44      1.1  jtc static void	dbtestp_error ARGS((Test_env *te, int offset, const char *msg));
     45      1.1  jtc #endif /* KSH */
     46      1.1  jtc 
     47      1.1  jtc static	struct	op	*outtree; /* yyparse output */
     48      1.1  jtc 
     49      1.1  jtc static struct multiline_state multiline;	/* \n changed to ; */
     50      1.1  jtc 
     51      1.1  jtc static	int	reject;		/* token(cf) gets symbol again */
     52      1.1  jtc static	int	symbol;		/* yylex value */
     53      1.1  jtc 
     54      1.1  jtc #define	REJECT	(reject = 1)
     55      1.1  jtc #define	ACCEPT	(reject = 0)
     56      1.1  jtc #define	token(cf) \
     57      1.1  jtc 	((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
     58      1.1  jtc #define	tpeek(cf) \
     59      1.1  jtc 	((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
     60      1.1  jtc 
     61      1.1  jtc static void
     62      1.1  jtc yyparse()
     63      1.1  jtc {
     64      1.1  jtc 	int c;
     65      1.1  jtc 
     66      1.1  jtc 	ACCEPT;
     67      1.1  jtc 	yynerrs = 0;
     68      1.1  jtc 
     69      1.1  jtc 	outtree = c_list();
     70      1.1  jtc 	c = tpeek(0);
     71      1.1  jtc 	if (c == 0 && !outtree)
     72      1.1  jtc 		outtree = newtp(TEOF);
     73      1.1  jtc 	else if (c != '\n' && c != 0)
     74      1.1  jtc 		syntaxerr((char *) 0);
     75      1.1  jtc }
     76      1.1  jtc 
     77      1.1  jtc static struct op *
     78      1.1  jtc pipeline(cf)
     79      1.1  jtc 	int cf;
     80      1.1  jtc {
     81      1.1  jtc 	register struct op *t, *p, *tl = NULL;
     82      1.1  jtc 
     83      1.1  jtc 	t = get_command(cf);
     84      1.1  jtc 	if (t != NULL) {
     85      1.1  jtc 		while (token(0) == '|') {
     86      1.1  jtc 			if ((p = get_command(CONTIN)) == NULL)
     87      1.1  jtc 				syntaxerr((char *) 0);
     88      1.1  jtc 			if (tl == NULL)
     89      1.1  jtc 				t = tl = block(TPIPE, t, p, NOWORDS);
     90      1.1  jtc 			else
     91      1.1  jtc 				tl = tl->right = block(TPIPE, tl->right, p, NOWORDS);
     92      1.1  jtc 		}
     93      1.1  jtc 		REJECT;
     94      1.1  jtc 	}
     95      1.1  jtc 	return (t);
     96      1.1  jtc }
     97      1.1  jtc 
     98      1.1  jtc static struct op *
     99      1.1  jtc andor()
    100      1.1  jtc {
    101      1.1  jtc 	register struct op *t, *p;
    102      1.1  jtc 	register int c;
    103      1.1  jtc 
    104      1.1  jtc 	t = pipeline(0);
    105      1.1  jtc 	if (t != NULL) {
    106      1.1  jtc 		while ((c = token(0)) == LOGAND || c == LOGOR) {
    107      1.1  jtc 			if ((p = pipeline(CONTIN)) == NULL)
    108      1.1  jtc 				syntaxerr((char *) 0);
    109      1.1  jtc 			t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
    110      1.1  jtc 		}
    111      1.1  jtc 		REJECT;
    112      1.1  jtc 	}
    113      1.1  jtc 	return (t);
    114      1.1  jtc }
    115      1.1  jtc 
    116      1.1  jtc static struct op *
    117      1.1  jtc c_list()
    118      1.1  jtc {
    119      1.1  jtc 	register struct op *t, *p, *tl = NULL;
    120      1.1  jtc 	register int c;
    121      1.1  jtc 
    122      1.1  jtc 	t = andor();
    123      1.1  jtc 	if (t != NULL) {
    124      1.1  jtc 		while ((c = token(0)) == ';' || c == '&' || c == COPROC ||
    125  1.1.1.3  jtc 		       (c == '\n' && (multiline.on || inalias(source))))
    126      1.1  jtc 		{
    127      1.1  jtc 			if (c == '&' || c == COPROC) {
    128      1.1  jtc 				int type = c == '&' ? TASYNC : TCOPROC;
    129      1.1  jtc 				if (tl)
    130      1.1  jtc 					tl->right = block(type, tl->right,
    131      1.1  jtc 							  NOBLOCK, NOWORDS);
    132      1.1  jtc 				else
    133      1.1  jtc 					t = block(type, t, NOBLOCK, NOWORDS);
    134      1.1  jtc 			}
    135      1.1  jtc 			if ((p = andor()) == NULL)
    136      1.1  jtc 				return (t);
    137      1.1  jtc 			if (tl == NULL)
    138      1.1  jtc 				t = tl = block(TLIST, t, p, NOWORDS);
    139      1.1  jtc 			else
    140      1.1  jtc 				tl = tl->right = block(TLIST, tl->right, p, NOWORDS);
    141      1.1  jtc 		}
    142      1.1  jtc 		REJECT;
    143      1.1  jtc 	}
    144      1.1  jtc 	return (t);
    145      1.1  jtc }
    146      1.1  jtc 
    147      1.1  jtc static struct ioword *
    148      1.1  jtc synio(cf)
    149      1.1  jtc 	int cf;
    150      1.1  jtc {
    151      1.1  jtc 	register struct ioword *iop;
    152      1.1  jtc 	int ishere;
    153      1.1  jtc 
    154      1.1  jtc 	if (tpeek(cf) != REDIR)
    155      1.1  jtc 		return NULL;
    156      1.1  jtc 	ACCEPT;
    157      1.1  jtc 	iop = yylval.iop;
    158      1.1  jtc 	ishere = (iop->flag&IOTYPE) == IOHERE;
    159      1.1  jtc 	musthave(LWORD, ishere ? HEREDELIM : 0);
    160      1.1  jtc 	if (ishere) {
    161      1.1  jtc 		iop->delim = yylval.cp;
    162      1.1  jtc 		if (*ident != 0) /* unquoted */
    163      1.1  jtc 			iop->flag |= IOEVAL;
    164      1.1  jtc 		if (herep >= &heres[HERES])
    165      1.1  jtc 			yyerror("too many <<'s\n");
    166      1.1  jtc 		*herep++ = iop;
    167      1.1  jtc 	} else
    168      1.1  jtc 		iop->name = yylval.cp;
    169      1.1  jtc 	return iop;
    170      1.1  jtc }
    171      1.1  jtc 
    172      1.1  jtc static void
    173      1.1  jtc musthave(c, cf)
    174      1.1  jtc 	int c, cf;
    175      1.1  jtc {
    176      1.1  jtc 	if ((token(cf)) != c)
    177      1.1  jtc 		syntaxerr((char *) 0);
    178      1.1  jtc }
    179      1.1  jtc 
    180      1.1  jtc static struct op *
    181      1.1  jtc nested(type, smark, emark)
    182      1.1  jtc 	int type, smark, emark;
    183      1.1  jtc {
    184      1.1  jtc 	register struct op *t;
    185      1.1  jtc 	struct multiline_state old_multiline;
    186      1.1  jtc 
    187      1.1  jtc 	multiline_push(&old_multiline, smark);
    188      1.1  jtc 	t = c_list();
    189      1.1  jtc 	musthave(emark, KEYWORD|ALIAS);
    190      1.1  jtc 	multiline_pop(&old_multiline);
    191      1.1  jtc 	return (block(type, t, NOBLOCK, NOWORDS));
    192      1.1  jtc }
    193      1.1  jtc 
    194      1.1  jtc static struct op *
    195      1.1  jtc get_command(cf)
    196      1.1  jtc 	int cf;
    197      1.1  jtc {
    198      1.1  jtc 	register struct op *t;
    199      1.1  jtc 	register int c, iopn = 0, syniocf;
    200      1.1  jtc 	struct ioword *iop, **iops;
    201      1.1  jtc 	XPtrV args, vars;
    202      1.1  jtc 	struct multiline_state old_multiline;
    203      1.1  jtc 
    204      1.1  jtc 	iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1),
    205      1.1  jtc 					ATEMP);
    206      1.1  jtc 	XPinit(args, 16);
    207      1.1  jtc 	XPinit(vars, 16);
    208      1.1  jtc 
    209      1.1  jtc 	if (multiline.on)
    210      1.1  jtc 		cf = CONTIN;
    211      1.1  jtc 	syniocf = KEYWORD|ALIAS;
    212      1.1  jtc 	switch (c = token(cf|KEYWORD|ALIAS|VARASN)) {
    213      1.1  jtc 	  default:
    214      1.1  jtc 		REJECT;
    215      1.1  jtc 		afree((void*) iops, ATEMP);
    216      1.1  jtc 		XPfree(args);
    217      1.1  jtc 		XPfree(vars);
    218      1.1  jtc 		return NULL; /* empty line */
    219      1.1  jtc 
    220      1.1  jtc 	  case LWORD:
    221      1.1  jtc 	  case REDIR:
    222      1.1  jtc 		REJECT;
    223      1.1  jtc 		syniocf &= ~(KEYWORD|ALIAS);
    224      1.1  jtc 		t = newtp(TCOM);
    225      1.1  jtc 		while (1) {
    226      1.1  jtc 			cf = (t->u.evalflags ? ARRAYVAR : 0)
    227      1.1  jtc 			     | (XPsize(args) == 0 ? ALIAS|VARASN : CMDWORD);
    228      1.1  jtc 			switch (tpeek(cf)) {
    229      1.1  jtc 			  case REDIR:
    230      1.1  jtc 				if (iopn >= NUFILE)
    231      1.1  jtc 					yyerror("too many redirections\n");
    232      1.1  jtc 				iops[iopn++] = synio(cf);
    233      1.1  jtc 				break;
    234      1.1  jtc 
    235      1.1  jtc 			  case LWORD:
    236      1.1  jtc 				ACCEPT;
    237      1.1  jtc 				/* the iopn == 0 and XPsize(vars) == 0 are
    238      1.1  jtc 				 * dubious but at&t ksh acts this way
    239      1.1  jtc 				 */
    240      1.1  jtc 				if (iopn == 0 && XPsize(vars) == 0
    241      1.1  jtc 				    && XPsize(args) == 0
    242      1.1  jtc 				    && assign_command(ident))
    243      1.1  jtc 					t->u.evalflags = DOVACHECK;
    244      1.1  jtc 				if ((XPsize(args) == 0 || Flag(FKEYWORD))
    245      1.1  jtc 				    && is_wdvarassign(yylval.cp))
    246      1.1  jtc 					XPput(vars, yylval.cp);
    247      1.1  jtc 				else
    248      1.1  jtc 					XPput(args, yylval.cp);
    249      1.1  jtc 				break;
    250      1.1  jtc 
    251      1.1  jtc 			  case '(':
    252      1.1  jtc 				/* Check for "> foo (echo hi)", which at&t ksh
    253      1.1  jtc 				 * allows (not POSIX, but not disallowed)
    254      1.1  jtc 				 */
    255      1.1  jtc 				afree(t, ATEMP);
    256      1.1  jtc 				if (XPsize(args) == 0 && XPsize(vars) == 0) {
    257      1.1  jtc 					ACCEPT;
    258      1.1  jtc 					goto Subshell;
    259      1.1  jtc 				}
    260      1.1  jtc 				/* Must be a function */
    261      1.1  jtc 				if (iopn != 0 || XPsize(args) != 1
    262      1.1  jtc 				    || XPsize(vars) != 0)
    263      1.1  jtc 					syntaxerr((char *) 0);
    264      1.1  jtc 				ACCEPT;
    265      1.1  jtc 				/*(*/
    266      1.1  jtc 				musthave(')', 0);
    267      1.1  jtc 				t = function_body(XPptrv(args)[0], FALSE);
    268      1.1  jtc 				goto Leave;
    269      1.1  jtc 
    270      1.1  jtc 			  default:
    271      1.1  jtc 				goto Leave;
    272      1.1  jtc 			}
    273      1.1  jtc 		}
    274      1.1  jtc 	  Leave:
    275      1.1  jtc 		break;
    276      1.1  jtc 
    277      1.1  jtc 	  Subshell:
    278      1.1  jtc 	  case '(':
    279      1.1  jtc 		t = nested(TPAREN, '(', ')');
    280      1.1  jtc 		break;
    281      1.1  jtc 
    282      1.1  jtc 	  case '{': /*}*/
    283      1.1  jtc 		t = nested(TBRACE, '{', '}');
    284      1.1  jtc 		break;
    285      1.1  jtc 
    286  1.1.1.2  jtc #ifdef KSH
    287      1.1  jtc 	  case MDPAREN:
    288      1.1  jtc 	  {
    289      1.1  jtc 		static const char let_cmd[] = { CHAR, 'l', CHAR, 'e',
    290      1.1  jtc 						CHAR, 't', EOS };
    291      1.1  jtc 		syniocf &= ~(KEYWORD|ALIAS);
    292      1.1  jtc 		t = newtp(TCOM);
    293      1.1  jtc 		ACCEPT;
    294      1.1  jtc 		XPput(args, wdcopy(let_cmd, ATEMP));
    295      1.1  jtc 		musthave(LWORD,LETEXPR);
    296      1.1  jtc 		XPput(args, yylval.cp);
    297      1.1  jtc 		break;
    298      1.1  jtc 	  }
    299  1.1.1.2  jtc #endif /* KSH */
    300      1.1  jtc 
    301      1.1  jtc #ifdef KSH
    302      1.1  jtc 	  case DBRACKET: /* [[ .. ]] */
    303      1.1  jtc 		syniocf &= ~(KEYWORD|ALIAS);
    304      1.1  jtc 		t = newtp(TDBRACKET);
    305      1.1  jtc 		ACCEPT;
    306      1.1  jtc 		{
    307      1.1  jtc 			Test_env te;
    308      1.1  jtc 
    309      1.1  jtc 			te.flags = TEF_DBRACKET;
    310      1.1  jtc 			te.pos.av = &args;
    311      1.1  jtc 			te.isa = dbtestp_isa;
    312      1.1  jtc 			te.getopnd = dbtestp_getopnd;
    313      1.1  jtc 			te.eval = dbtestp_eval;
    314      1.1  jtc 			te.error = dbtestp_error;
    315      1.1  jtc 
    316      1.1  jtc 			test_parse(&te);
    317      1.1  jtc 		}
    318      1.1  jtc 		break;
    319      1.1  jtc #endif /* KSH */
    320      1.1  jtc 
    321      1.1  jtc 	  case FOR:
    322      1.1  jtc 	  case SELECT:
    323      1.1  jtc 		t = newtp((c == FOR) ? TFOR : TSELECT);
    324      1.1  jtc 		musthave(LWORD, ARRAYVAR);
    325      1.1  jtc 		if (!is_wdvarname(yylval.cp, TRUE))
    326      1.1  jtc 			yyerror("%s: bad identifier\n",
    327      1.1  jtc 				c == FOR ? "for" : "select");
    328      1.1  jtc 		t->str = str_save(ident, ATEMP);
    329      1.1  jtc 		multiline_push(&old_multiline, c);
    330      1.1  jtc 		t->vars = wordlist();
    331      1.1  jtc 		t->left = dogroup();
    332      1.1  jtc 		multiline_pop(&old_multiline);
    333      1.1  jtc 		break;
    334      1.1  jtc 
    335      1.1  jtc 	  case WHILE:
    336      1.1  jtc 	  case UNTIL:
    337      1.1  jtc 		multiline_push(&old_multiline, c);
    338      1.1  jtc 		t = newtp((c == WHILE) ? TWHILE : TUNTIL);
    339      1.1  jtc 		t->left = c_list();
    340      1.1  jtc 		t->right = dogroup();
    341      1.1  jtc 		multiline_pop(&old_multiline);
    342      1.1  jtc 		break;
    343      1.1  jtc 
    344      1.1  jtc 	  case CASE:
    345      1.1  jtc 		t = newtp(TCASE);
    346      1.1  jtc 		musthave(LWORD, 0);
    347      1.1  jtc 		t->str = yylval.cp;
    348      1.1  jtc 		multiline_push(&old_multiline, c);
    349      1.1  jtc 		t->left = caselist();
    350      1.1  jtc 		multiline_pop(&old_multiline);
    351      1.1  jtc 		break;
    352      1.1  jtc 
    353      1.1  jtc 	  case IF:
    354      1.1  jtc 		multiline_push(&old_multiline, c);
    355      1.1  jtc 		t = newtp(TIF);
    356      1.1  jtc 		t->left = c_list();
    357      1.1  jtc 		t->right = thenpart();
    358      1.1  jtc 		musthave(FI, KEYWORD|ALIAS);
    359      1.1  jtc 		multiline_pop(&old_multiline);
    360      1.1  jtc 		break;
    361      1.1  jtc 
    362      1.1  jtc 	  case BANG:
    363      1.1  jtc 		syniocf &= ~(KEYWORD|ALIAS);
    364      1.1  jtc 		t = pipeline(0);
    365      1.1  jtc 		if (t == (struct op *) 0)
    366      1.1  jtc 			syntaxerr((char *) 0);
    367      1.1  jtc 		t = block(TBANG, NOBLOCK, t, NOWORDS);
    368      1.1  jtc 		break;
    369      1.1  jtc 
    370      1.1  jtc 	  case TIME:
    371      1.1  jtc 		syniocf &= ~(KEYWORD|ALIAS);
    372      1.1  jtc 		t = pipeline(0);
    373      1.1  jtc 		t = block(TTIME, t, NOBLOCK, NOWORDS);
    374      1.1  jtc 		break;
    375      1.1  jtc 
    376      1.1  jtc 	  case FUNCTION:
    377      1.1  jtc 		musthave(LWORD, 0);
    378      1.1  jtc 		t = function_body(yylval.cp, TRUE);
    379      1.1  jtc 		break;
    380      1.1  jtc 	}
    381      1.1  jtc 
    382      1.1  jtc 	while ((iop = synio(syniocf)) != NULL) {
    383      1.1  jtc 		if (iopn >= NUFILE)
    384      1.1  jtc 			yyerror("too many redirections\n");
    385      1.1  jtc 		iops[iopn++] = iop;
    386      1.1  jtc 	}
    387      1.1  jtc 
    388      1.1  jtc 	if (iopn == 0) {
    389      1.1  jtc 		afree((void*) iops, ATEMP);
    390      1.1  jtc 		t->ioact = NULL;
    391      1.1  jtc 	} else {
    392      1.1  jtc 		iops[iopn++] = NULL;
    393      1.1  jtc 		iops = (struct ioword **) aresize((void*) iops,
    394      1.1  jtc 					sizeofN(struct ioword *, iopn), ATEMP);
    395      1.1  jtc 		t->ioact = iops;
    396      1.1  jtc 	}
    397      1.1  jtc 
    398      1.1  jtc 	if (t->type == TCOM || t->type == TDBRACKET) {
    399      1.1  jtc 		XPput(args, NULL);
    400      1.1  jtc 		t->args = (char **) XPclose(args);
    401      1.1  jtc 		XPput(vars, NULL);
    402      1.1  jtc 		t->vars = (char **) XPclose(vars);
    403      1.1  jtc 	} else {
    404      1.1  jtc 		XPfree(args);
    405      1.1  jtc 		XPfree(vars);
    406      1.1  jtc 	}
    407      1.1  jtc 
    408      1.1  jtc 	return t;
    409      1.1  jtc }
    410      1.1  jtc 
    411      1.1  jtc static struct op *
    412      1.1  jtc dogroup()
    413      1.1  jtc {
    414      1.1  jtc 	register int c;
    415      1.1  jtc 	register struct op *list;
    416      1.1  jtc 
    417      1.1  jtc 	c = token(CONTIN|KEYWORD|ALIAS);
    418      1.1  jtc 	/* A {...} can be used instead of do...done for for/select loops
    419      1.1  jtc 	 * but not for while/until loops - we don't need to check if it
    420      1.1  jtc 	 * is a while loop because it would have been parsed as part of
    421      1.1  jtc 	 * the conditional command list...
    422      1.1  jtc 	 */
    423      1.1  jtc 	if (c == DO)
    424      1.1  jtc 		c = DONE;
    425      1.1  jtc 	else if (c == '{')
    426      1.1  jtc 		c = '}';
    427      1.1  jtc 	else
    428      1.1  jtc 		syntaxerr((char *) 0);
    429      1.1  jtc 	list = c_list();
    430      1.1  jtc 	musthave(c, KEYWORD|ALIAS);
    431      1.1  jtc 	return list;
    432      1.1  jtc }
    433      1.1  jtc 
    434      1.1  jtc static struct op *
    435      1.1  jtc thenpart()
    436      1.1  jtc {
    437      1.1  jtc 	register struct op *t;
    438      1.1  jtc 
    439      1.1  jtc 	musthave(THEN, KEYWORD|ALIAS);
    440      1.1  jtc 	t = newtp(0);
    441      1.1  jtc 	t->left = c_list();
    442      1.1  jtc 	if (t->left == NULL)
    443      1.1  jtc 		syntaxerr((char *) 0);
    444      1.1  jtc 	t->right = elsepart();
    445      1.1  jtc 	return (t);
    446      1.1  jtc }
    447      1.1  jtc 
    448      1.1  jtc static struct op *
    449      1.1  jtc elsepart()
    450      1.1  jtc {
    451      1.1  jtc 	register struct op *t;
    452      1.1  jtc 
    453      1.1  jtc 	switch (token(KEYWORD|ALIAS|VARASN)) {
    454      1.1  jtc 	  case ELSE:
    455      1.1  jtc 		if ((t = c_list()) == NULL)
    456      1.1  jtc 			syntaxerr((char *) 0);
    457      1.1  jtc 		return (t);
    458      1.1  jtc 
    459      1.1  jtc 	  case ELIF:
    460      1.1  jtc 		t = newtp(TELIF);
    461      1.1  jtc 		t->left = c_list();
    462      1.1  jtc 		t->right = thenpart();
    463      1.1  jtc 		return (t);
    464      1.1  jtc 
    465      1.1  jtc 	  default:
    466      1.1  jtc 		REJECT;
    467      1.1  jtc 	}
    468      1.1  jtc 	return NULL;
    469      1.1  jtc }
    470      1.1  jtc 
    471      1.1  jtc static struct op *
    472      1.1  jtc caselist()
    473      1.1  jtc {
    474      1.1  jtc 	register struct op *t, *tl;
    475      1.1  jtc 	int c;
    476      1.1  jtc 
    477      1.1  jtc 	c = token(CONTIN|KEYWORD|ALIAS);
    478      1.1  jtc 	/* A {...} can be used instead of in...esac for case statements */
    479      1.1  jtc 	if (c == IN)
    480      1.1  jtc 		c = ESAC;
    481      1.1  jtc 	else if (c == '{')
    482      1.1  jtc 		c = '}';
    483      1.1  jtc 	else
    484      1.1  jtc 		syntaxerr((char *) 0);
    485      1.1  jtc 	t = tl = NULL;
    486      1.1  jtc 	while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) { /* no ALIAS here */
    487      1.1  jtc 		struct op *tc = casepart(c);
    488      1.1  jtc 		if (tl == NULL)
    489      1.1  jtc 			t = tl = tc, tl->right = NULL;
    490      1.1  jtc 		else
    491      1.1  jtc 			tl->right = tc, tl = tc;
    492      1.1  jtc 	}
    493      1.1  jtc 	musthave(c, KEYWORD|ALIAS);
    494      1.1  jtc 	return (t);
    495      1.1  jtc }
    496      1.1  jtc 
    497      1.1  jtc static struct op *
    498      1.1  jtc casepart(endtok)
    499      1.1  jtc 	int endtok;
    500      1.1  jtc {
    501      1.1  jtc 	register struct op *t;
    502      1.1  jtc 	register int c;
    503      1.1  jtc 	XPtrV ptns;
    504      1.1  jtc 
    505      1.1  jtc 	XPinit(ptns, 16);
    506      1.1  jtc 	t = newtp(TPAT);
    507      1.1  jtc 	c = token(CONTIN|KEYWORD); /* no ALIAS here */
    508      1.1  jtc 	if (c != '(')
    509      1.1  jtc 		REJECT;
    510      1.1  jtc 	do {
    511      1.1  jtc 		musthave(LWORD, 0);
    512      1.1  jtc 		XPput(ptns, yylval.cp);
    513      1.1  jtc 	} while ((c = token(0)) == '|');
    514      1.1  jtc 	REJECT;
    515      1.1  jtc 	XPput(ptns, NULL);
    516      1.1  jtc 	t->vars = (char **) XPclose(ptns);
    517      1.1  jtc 	musthave(')', 0);
    518      1.1  jtc 
    519      1.1  jtc 	t->left = c_list();
    520      1.1  jtc 	if ((tpeek(CONTIN|KEYWORD|ALIAS)) != endtok)
    521      1.1  jtc 		musthave(BREAK, CONTIN|KEYWORD|ALIAS);
    522      1.1  jtc 	return (t);
    523      1.1  jtc }
    524      1.1  jtc 
    525      1.1  jtc static struct op *
    526      1.1  jtc function_body(name, ksh_func)
    527      1.1  jtc 	char *name;
    528      1.1  jtc 	int ksh_func;	/* function foo { ... } vs foo() { .. } */
    529      1.1  jtc {
    530      1.1  jtc 	XString xs;
    531      1.1  jtc 	char *xp, *p;
    532      1.1  jtc 	struct op *t;
    533      1.1  jtc 	int old_func_parse;
    534      1.1  jtc 
    535      1.1  jtc 	Xinit(xs, xp, 16, ATEMP);
    536      1.1  jtc 	for (p = name; ; ) {
    537      1.1  jtc 		if ((*p == EOS && Xlength(xs, xp) == 0)
    538      1.1  jtc 		    || (*p != EOS && *p != CHAR && *p != QCHAR
    539      1.1  jtc 			&& *p != OQUOTE && *p != CQUOTE))
    540      1.1  jtc 		{
    541      1.1  jtc 			p = snptreef((char *) 0, 32, "%S", name);
    542      1.1  jtc 			yyerror("%s: invalid function name\n", p);
    543      1.1  jtc 		}
    544      1.1  jtc 		Xcheck(xs, xp);
    545      1.1  jtc 		if (*p == EOS) {
    546      1.1  jtc 			Xput(xs, xp, '\0');
    547      1.1  jtc 			break;
    548      1.1  jtc 		} else if (*p == CHAR || *p == QCHAR) {
    549      1.1  jtc 			Xput(xs, xp, p[1]);
    550      1.1  jtc 			p += 2;
    551      1.1  jtc 		} else
    552      1.1  jtc 			p++;	/* OQUOTE/CQUOTE */
    553      1.1  jtc 	}
    554      1.1  jtc 	t = newtp(TFUNCT);
    555      1.1  jtc 	t->str = Xclose(xs, xp);
    556      1.1  jtc 	t->u.ksh_func = ksh_func;
    557      1.1  jtc 
    558      1.1  jtc 	/* Note that POSIX allows only compound statements after foo(), sh and
    559      1.1  jtc 	 * at&t ksh allow any command, go with the later since it shouldn't
    560      1.1  jtc 	 * break anything.  However, for function foo, at&t ksh only accepts
    561      1.1  jtc 	 * an open-brace.
    562      1.1  jtc 	 */
    563      1.1  jtc 	if (ksh_func) {
    564      1.1  jtc 		musthave('{', CONTIN|KEYWORD|ALIAS); /* } */
    565      1.1  jtc 		REJECT;
    566      1.1  jtc 	}
    567      1.1  jtc 
    568      1.1  jtc 	old_func_parse = e->flags & EF_FUNC_PARSE;
    569      1.1  jtc 	e->flags |= EF_FUNC_PARSE;
    570      1.1  jtc 	if ((t->left = get_command(CONTIN)) == (struct op *) 0) {
    571      1.1  jtc 		/* create empty command so foo(): will work */
    572      1.1  jtc 		t->left = newtp(TCOM);
    573      1.1  jtc 		t->args = (char **) alloc(sizeof(char *), ATEMP);
    574      1.1  jtc 		t->args[0] = (char *) 0;
    575      1.1  jtc 		t->vars = (char **) alloc(sizeof(char *), ATEMP);
    576      1.1  jtc 		t->vars[0] = (char *) 0;
    577      1.1  jtc 	}
    578      1.1  jtc 	if (!old_func_parse)
    579      1.1  jtc 		e->flags &= ~EF_FUNC_PARSE;
    580      1.1  jtc 
    581      1.1  jtc 	return t;
    582      1.1  jtc }
    583      1.1  jtc 
    584      1.1  jtc static char **
    585      1.1  jtc wordlist()
    586      1.1  jtc {
    587      1.1  jtc 	register int c;
    588      1.1  jtc 	XPtrV args;
    589      1.1  jtc 
    590      1.1  jtc 	XPinit(args, 16);
    591      1.1  jtc 	if ((c = token(CONTIN|KEYWORD|ALIAS)) != IN) {
    592      1.1  jtc 		if (c != ';') /* non-POSIX, but at&t ksh accepts a ; here */
    593      1.1  jtc 			REJECT;
    594      1.1  jtc 		return NULL;
    595      1.1  jtc 	}
    596      1.1  jtc 	while ((c = token(0)) == LWORD)
    597      1.1  jtc 		XPput(args, yylval.cp);
    598      1.1  jtc 	if (c != '\n' && c != ';')
    599      1.1  jtc 		syntaxerr((char *) 0);
    600      1.1  jtc 	if (XPsize(args) == 0) {
    601      1.1  jtc 		XPfree(args);
    602      1.1  jtc 		return NULL;
    603      1.1  jtc 	} else {
    604      1.1  jtc 		XPput(args, NULL);
    605      1.1  jtc 		return (char **) XPclose(args);
    606      1.1  jtc 	}
    607      1.1  jtc }
    608      1.1  jtc 
    609      1.1  jtc /*
    610      1.1  jtc  * supporting functions
    611      1.1  jtc  */
    612      1.1  jtc 
    613      1.1  jtc static struct op *
    614      1.1  jtc block(type, t1, t2, wp)
    615      1.1  jtc 	int type;
    616      1.1  jtc 	struct op *t1, *t2;
    617      1.1  jtc 	char **wp;
    618      1.1  jtc {
    619      1.1  jtc 	register struct op *t;
    620      1.1  jtc 
    621      1.1  jtc 	t = newtp(type);
    622      1.1  jtc 	t->left = t1;
    623      1.1  jtc 	t->right = t2;
    624      1.1  jtc 	t->vars = wp;
    625      1.1  jtc 	return (t);
    626      1.1  jtc }
    627      1.1  jtc 
    628      1.1  jtc const	struct tokeninfo {
    629      1.1  jtc 	const char *name;
    630      1.1  jtc 	short	val;
    631      1.1  jtc 	short	reserved;
    632      1.1  jtc } tokentab[] = {
    633      1.1  jtc 	/* Reserved words */
    634      1.1  jtc 	{ "if",		IF,	TRUE },
    635      1.1  jtc 	{ "then",	THEN,	TRUE },
    636      1.1  jtc 	{ "else",	ELSE,	TRUE },
    637      1.1  jtc 	{ "elif",	ELIF,	TRUE },
    638      1.1  jtc 	{ "fi",		FI,	TRUE },
    639      1.1  jtc 	{ "case",	CASE,	TRUE },
    640      1.1  jtc 	{ "esac",	ESAC,	TRUE },
    641      1.1  jtc 	{ "for",	FOR,	TRUE },
    642      1.1  jtc #ifdef KSH
    643      1.1  jtc 	{ "select",	SELECT,	TRUE },
    644      1.1  jtc #endif /* KSH */
    645      1.1  jtc 	{ "while",	WHILE,	TRUE },
    646      1.1  jtc 	{ "until",	UNTIL,	TRUE },
    647      1.1  jtc 	{ "do",		DO,	TRUE },
    648      1.1  jtc 	{ "done",	DONE,	TRUE },
    649      1.1  jtc 	{ "in",		IN,	TRUE },
    650      1.1  jtc 	{ "function",	FUNCTION, TRUE },
    651      1.1  jtc 	{ "time",	TIME,	TRUE },
    652      1.1  jtc 	{ "{",		'{',	TRUE },
    653      1.1  jtc 	{ "}",		'}',	TRUE },
    654      1.1  jtc 	{ "!",		BANG,	TRUE },
    655      1.1  jtc #ifdef KSH
    656      1.1  jtc 	{ "[[",		DBRACKET, TRUE },
    657      1.1  jtc #endif /* KSH */
    658      1.1  jtc 	/* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */
    659      1.1  jtc 	{ "&&",		LOGAND,	FALSE },
    660      1.1  jtc 	{ "||",		LOGOR,	FALSE },
    661      1.1  jtc 	{ ";;",		BREAK,	FALSE },
    662      1.1  jtc #ifdef KSH
    663  1.1.1.2  jtc 	{ "((",		MDPAREN, FALSE },
    664      1.1  jtc 	{ "|&",		COPROC,	FALSE },
    665      1.1  jtc #endif /* KSH */
    666      1.1  jtc 	/* and some special cases... */
    667      1.1  jtc 	{ "newline",	'\n',	FALSE },
    668      1.1  jtc 	{ 0 }
    669      1.1  jtc };
    670      1.1  jtc 
    671      1.1  jtc void
    672      1.1  jtc initkeywords()
    673      1.1  jtc {
    674      1.1  jtc 	register struct tokeninfo const *tt;
    675      1.1  jtc 	register struct tbl *p;
    676      1.1  jtc 
    677      1.1  jtc 	tinit(&keywords, APERM, 32); /* must be 2^n (currently 20 keywords) */
    678      1.1  jtc 	for (tt = tokentab; tt->name; tt++) {
    679      1.1  jtc 		if (tt->reserved) {
    680      1.1  jtc 			p = tenter(&keywords, tt->name, hash(tt->name));
    681      1.1  jtc 			p->flag |= DEFINED|ISSET;
    682      1.1  jtc 			p->type = CKEYWD;
    683      1.1  jtc 			p->val.i = tt->val;
    684      1.1  jtc 		}
    685      1.1  jtc 	}
    686      1.1  jtc }
    687      1.1  jtc 
    688      1.1  jtc static void
    689      1.1  jtc syntaxerr(what)
    690      1.1  jtc 	const char *what;
    691      1.1  jtc {
    692      1.1  jtc 	char redir[6];	/* 2<<- is the longest redirection, I think */
    693      1.1  jtc 	const char *s;
    694      1.1  jtc 	struct tokeninfo const *tt;
    695      1.1  jtc 	int c;
    696      1.1  jtc 
    697      1.1  jtc 	if (!what)
    698      1.1  jtc 		what = "unexpected";
    699      1.1  jtc 	REJECT;
    700      1.1  jtc 	c = token(0);
    701      1.1  jtc     Again:
    702      1.1  jtc 	switch (c) {
    703      1.1  jtc 	case 0:
    704      1.1  jtc 		if (multiline.on && multiline.start_token) {
    705      1.1  jtc 			multiline.on = FALSE; /* avoid infinate loops */
    706      1.1  jtc 			c = multiline.start_token;
    707      1.1  jtc 			source->errline = multiline.start_line;
    708      1.1  jtc 			what = "unmatched";
    709      1.1  jtc 			goto Again;
    710      1.1  jtc 		}
    711      1.1  jtc 		/* don't quote the EOF */
    712      1.1  jtc 		yyerror("syntax error: unexpected EOF\n");
    713      1.1  jtc 		/*NOTREACHED*/
    714      1.1  jtc 
    715      1.1  jtc 	case LWORD:
    716      1.1  jtc 		s = snptreef((char *) 0, 32, "%S", yylval.cp);
    717      1.1  jtc 		break;
    718      1.1  jtc 
    719      1.1  jtc 	case REDIR:
    720      1.1  jtc 		s = snptreef(redir, sizeof(redir), "%R", yylval.iop);
    721      1.1  jtc 		break;
    722      1.1  jtc 
    723      1.1  jtc 	default:
    724      1.1  jtc 		for (tt = tokentab; tt->name; tt++)
    725      1.1  jtc 			if (tt->val == c)
    726      1.1  jtc 			    break;
    727      1.1  jtc 		if (tt->name)
    728      1.1  jtc 			s = tt->name;
    729      1.1  jtc 		else {
    730      1.1  jtc 			if (c > 0 && c < 256) {
    731      1.1  jtc 				redir[0] = c;
    732      1.1  jtc 				redir[1] = '\0';
    733      1.1  jtc 			} else
    734      1.1  jtc 				shf_snprintf(redir, sizeof(redir),
    735      1.1  jtc 					"?%d", c);
    736      1.1  jtc 			s = redir;
    737      1.1  jtc 		}
    738      1.1  jtc 	}
    739      1.1  jtc 	yyerror("syntax error: `%s' %s\n", s, what);
    740      1.1  jtc }
    741      1.1  jtc 
    742      1.1  jtc static void
    743      1.1  jtc multiline_push(save, tok)
    744      1.1  jtc 	struct multiline_state *save;
    745      1.1  jtc 	int tok;
    746      1.1  jtc {
    747      1.1  jtc 	*save = multiline;
    748      1.1  jtc 	multiline.on = TRUE;
    749      1.1  jtc 	multiline.start_token = tok;
    750      1.1  jtc 	multiline.start_line = source->line;
    751      1.1  jtc }
    752      1.1  jtc 
    753      1.1  jtc static void
    754      1.1  jtc multiline_pop(saved)
    755      1.1  jtc 	struct multiline_state *saved;
    756      1.1  jtc {
    757      1.1  jtc 	multiline = *saved;
    758      1.1  jtc }
    759      1.1  jtc 
    760      1.1  jtc static struct op *
    761      1.1  jtc newtp(type)
    762      1.1  jtc 	int type;
    763      1.1  jtc {
    764      1.1  jtc 	register struct op *t;
    765      1.1  jtc 
    766      1.1  jtc 	t = (struct op *) alloc(sizeof(*t), ATEMP);
    767      1.1  jtc 	t->type = type;
    768      1.1  jtc 	t->u.evalflags = 0;
    769      1.1  jtc 	t->args = t->vars = NULL;
    770      1.1  jtc 	t->ioact = NULL;
    771      1.1  jtc 	t->left = t->right = NULL;
    772      1.1  jtc 	t->str = NULL;
    773      1.1  jtc 	return (t);
    774      1.1  jtc }
    775      1.1  jtc 
    776      1.1  jtc struct op *
    777      1.1  jtc compile(s)
    778      1.1  jtc 	Source *s;
    779      1.1  jtc {
    780      1.1  jtc 	yynerrs = 0;
    781      1.1  jtc 	multiline.on = s->type == SSTRING;
    782      1.1  jtc 	multiline.start_token = 0;
    783      1.1  jtc 	multiline.start_line = 0;
    784      1.1  jtc 	herep = heres;
    785      1.1  jtc 	source = s;
    786      1.1  jtc 	yyparse();
    787      1.1  jtc 	return outtree;
    788      1.1  jtc }
    789      1.1  jtc 
    790      1.1  jtc /* This kludge exists to take care of sh/at&t ksh oddity in which
    791      1.1  jtc  * the arguments of alias/export/readonly/typeset have no field
    792      1.1  jtc  * splitting, file globbing, or (normal) tilde expansion done.
    793      1.1  jtc  * at&t ksh seems to do something similar to this since
    794      1.1  jtc  *	$ touch a=a; typeset a=[ab]; echo "$a"
    795      1.1  jtc  *	a=[ab]
    796      1.1  jtc  *	$ x=typeset; $x a=[ab]; echo "$a"
    797      1.1  jtc  *	a=a
    798      1.1  jtc  *	$
    799      1.1  jtc  */
    800      1.1  jtc static int
    801      1.1  jtc assign_command(s)
    802      1.1  jtc 	char *s;
    803      1.1  jtc {
    804      1.1  jtc 	char c = *s;
    805      1.1  jtc 
    806      1.1  jtc 	if (Flag(FPOSIX) || !*s)
    807      1.1  jtc 		return 0;
    808      1.1  jtc 	return     (c == 'a' && strcmp(s, "alias") == 0)
    809      1.1  jtc 		|| (c == 'e' && strcmp(s, "export") == 0)
    810      1.1  jtc 		|| (c == 'r' && strcmp(s, "readonly") == 0)
    811      1.1  jtc 		|| (c == 't' && strcmp(s, "typeset") == 0);
    812  1.1.1.3  jtc }
    813  1.1.1.3  jtc 
    814  1.1.1.3  jtc /* Check if we are in the middle of reading an alias */
    815  1.1.1.3  jtc static int
    816  1.1.1.3  jtc inalias(s)
    817  1.1.1.3  jtc 	struct source *s;
    818  1.1.1.3  jtc {
    819  1.1.1.3  jtc 	for (; s && s->type == SALIAS; s = s->next)
    820  1.1.1.3  jtc 		if (!(s->flags & SF_ALIASEND))
    821  1.1.1.3  jtc 			return 1;
    822  1.1.1.3  jtc 	return 0;
    823      1.1  jtc }
    824      1.1  jtc 
    825      1.1  jtc 
    826      1.1  jtc #ifdef KSH
    827      1.1  jtc /* Order important - indexed by Test_meta values
    828      1.1  jtc  * Note that ||, &&, ( and ) can't appear in as unquoted strings
    829      1.1  jtc  * in normal shell input, so these can be interpreted unambiguously
    830      1.1  jtc  * in the evaluation pass.
    831      1.1  jtc  */
    832      1.1  jtc static const char dbtest_or[] = { CHAR, '|', CHAR, '|', EOS };
    833      1.1  jtc static const char dbtest_and[] = { CHAR, '&', CHAR, '&', EOS };
    834      1.1  jtc static const char dbtest_not[] = { CHAR, '!', EOS };
    835      1.1  jtc static const char dbtest_oparen[] = { CHAR, '(', EOS };
    836      1.1  jtc static const char dbtest_cparen[] = { CHAR, ')', EOS };
    837      1.1  jtc const char *const dbtest_tokens[] = {
    838      1.1  jtc 			dbtest_or, dbtest_and, dbtest_not,
    839      1.1  jtc 			dbtest_oparen, dbtest_cparen
    840      1.1  jtc 		};
    841      1.1  jtc const char db_close[] = { CHAR, ']', CHAR, ']', EOS };
    842      1.1  jtc const char db_lthan[] = { CHAR, '<', EOS };
    843      1.1  jtc const char db_gthan[] = { CHAR, '>', EOS };
    844      1.1  jtc 
    845      1.1  jtc /* Test if the current token is a whatever.  Accepts the current token if
    846      1.1  jtc  * it is.  Returns 0 if it is not, non-zero if it is (in the case of
    847      1.1  jtc  * TM_UNOP and TM_BINOP, the returned value is a Test_op).
    848      1.1  jtc  */
    849      1.1  jtc static int
    850      1.1  jtc dbtestp_isa(te, meta)
    851      1.1  jtc 	Test_env *te;
    852      1.1  jtc 	Test_meta meta;
    853      1.1  jtc {
    854      1.1  jtc 	int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN));
    855      1.1  jtc 	int uqword = 0;
    856      1.1  jtc 	char *save = (char *) 0;
    857      1.1  jtc 	int ret = 0;
    858      1.1  jtc 
    859      1.1  jtc 	/* unquoted word? */
    860      1.1  jtc 	uqword = c == LWORD && *ident;
    861      1.1  jtc 
    862      1.1  jtc 	if (meta == TM_OR)
    863      1.1  jtc 		ret = c == LOGOR;
    864      1.1  jtc 	else if (meta == TM_AND)
    865      1.1  jtc 		ret = c == LOGAND;
    866      1.1  jtc 	else if (meta == TM_NOT)
    867      1.1  jtc 		ret = uqword && strcmp(yylval.cp, dbtest_tokens[(int) TM_NOT]) == 0;
    868      1.1  jtc 	else if (meta == TM_OPAREN)
    869      1.1  jtc 		ret = c == '(' /*)*/;
    870      1.1  jtc 	else if (meta == TM_CPAREN)
    871      1.1  jtc 		ret = c == /*(*/ ')';
    872      1.1  jtc 	else if (meta == TM_UNOP || meta == TM_BINOP) {
    873      1.1  jtc 		if (meta == TM_BINOP && c == REDIR
    874      1.1  jtc 		    && (yylval.iop->flag == IOREAD
    875      1.1  jtc 			|| yylval.iop->flag == IOWRITE))
    876      1.1  jtc 		{
    877      1.1  jtc 			ret = 1;
    878      1.1  jtc 			save = wdcopy(yylval.iop->flag == IOREAD ?
    879      1.1  jtc 				db_lthan : db_gthan, ATEMP);
    880      1.1  jtc 		} else if (uqword && (ret = (int) test_isop(te, meta, ident)))
    881      1.1  jtc 			save = yylval.cp;
    882      1.1  jtc 	} else /* meta == TM_END */
    883      1.1  jtc 		ret = uqword && strcmp(yylval.cp, db_close) == 0;
    884      1.1  jtc 	if (ret) {
    885      1.1  jtc 		ACCEPT;
    886      1.1  jtc 		if (meta != TM_END) {
    887      1.1  jtc 			if (!save)
    888      1.1  jtc 				save = wdcopy(dbtest_tokens[(int) meta], ATEMP);
    889      1.1  jtc 			XPput(*te->pos.av, save);
    890      1.1  jtc 		}
    891      1.1  jtc 	}
    892      1.1  jtc 	return ret;
    893      1.1  jtc }
    894      1.1  jtc 
    895      1.1  jtc static const char *
    896      1.1  jtc dbtestp_getopnd(te, op, do_eval)
    897      1.1  jtc 	Test_env *te;
    898      1.1  jtc 	Test_op op;
    899      1.1  jtc 	int do_eval;
    900      1.1  jtc {
    901      1.1  jtc 	int c = tpeek(ARRAYVAR);
    902      1.1  jtc 
    903      1.1  jtc 	if (c != LWORD)
    904      1.1  jtc 		return (const char *) 0;
    905      1.1  jtc 
    906      1.1  jtc 	ACCEPT;
    907      1.1  jtc 	XPput(*te->pos.av, yylval.cp);
    908      1.1  jtc 
    909      1.1  jtc 	return null;
    910      1.1  jtc }
    911      1.1  jtc 
    912      1.1  jtc static int
    913      1.1  jtc dbtestp_eval(te, op, opnd1, opnd2, do_eval)
    914      1.1  jtc 	Test_env *te;
    915      1.1  jtc 	Test_op op;
    916      1.1  jtc 	const char *opnd1;
    917      1.1  jtc 	const char *opnd2;
    918      1.1  jtc 	int do_eval;
    919      1.1  jtc {
    920      1.1  jtc 	return 1;
    921      1.1  jtc }
    922      1.1  jtc 
    923      1.1  jtc static void
    924      1.1  jtc dbtestp_error(te, offset, msg)
    925      1.1  jtc 	Test_env *te;
    926      1.1  jtc 	int offset;
    927      1.1  jtc 	const char *msg;
    928      1.1  jtc {
    929      1.1  jtc 	te->flags |= TEF_ERROR;
    930      1.1  jtc 
    931      1.1  jtc 	if (offset < 0) {
    932      1.1  jtc 		REJECT;
    933      1.1  jtc 		/* Kludgy to say the least... */
    934      1.1  jtc 		symbol = LWORD;
    935      1.1  jtc 		yylval.cp = *(XPptrv(*te->pos.av) + XPsize(*te->pos.av)
    936      1.1  jtc 				+ offset);
    937      1.1  jtc 	}
    938      1.1  jtc 	syntaxerr(msg);
    939      1.1  jtc }
    940      1.1  jtc #endif /* KSH */
    941