1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2012 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * David Korn <dgk@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22 * UNIX shell
23 *
24 * S. R. Bourne
25 * Rewritten by David Korn
26 * AT&T Labs
27 *
28 * This is the parser for a shell language
29 */
30
31 #if KSHELL
32 #include "defs.h"
33 #else
34 #include <shell.h>
35 #include <ctype.h>
36 #endif
37 #include <fcin.h>
38 #include <error.h>
39 #include "shlex.h"
40 #include "history.h"
41 #include "builtins.h"
42 #include "test.h"
43 #include "history.h"
44
45 #define HERE_MEM SF_BUFSIZE /* size of here-docs kept in memory */
46
47 #if CDT_VERSION < 20111111L
48 #define hash nvlink.hl._hash
49 #else
50 #define hash nvlink.lh.__hash
51 #endif
52
53 /* These routines are local to this module */
54
55 static Shnode_t *makeparent(Lex_t*, int, Shnode_t*);
56 static Shnode_t *makelist(Lex_t*, int, Shnode_t*, Shnode_t*);
57 static struct argnod *qscan(struct comnod*, int);
58 static struct ionod *inout(Lex_t*,struct ionod*, int);
59 static Shnode_t *sh_cmd(Lex_t*,int,int);
60 static Shnode_t *term(Lex_t*,int);
61 static Shnode_t *list(Lex_t*,int);
62 static struct regnod *syncase(Lex_t*,int);
63 static Shnode_t *item(Lex_t*,int);
64 static Shnode_t *simple(Lex_t*,int, struct ionod*);
65 static int skipnl(Lex_t*,int);
66 static Shnode_t *test_expr(Lex_t*,int);
67 static Shnode_t *test_and(Lex_t*);
68 static Shnode_t *test_or(Lex_t*);
69 static Shnode_t *test_primary(Lex_t*);
70
71 #define sh_getlineno(lp) (lp->lastline)
72
73 #ifndef NIL
74 # define NIL(type) ((type)0)
75 #endif /* NIL */
76 #define CNTL(x) ((x)&037)
77
78
79 #if !KSHELL
80 static struct stdata
81 {
82 struct slnod *staklist;
83 int cmdline;
84 } st;
85 #endif
86
87 static int opt_get;
88 static int loop_level;
89 static struct argnod *label_list;
90 static struct argnod *label_last;
91
92 #define getnode(type) ((Shnode_t*)stakalloc(sizeof(struct type)))
93
94 #if SHOPT_KIA
95 #include "path.h"
96 /*
97 * write out entities for each item in the list
98 * type=='V' for variable assignment lists
99 * Otherwise type is determined by the command */
writedefs(Lex_t * lexp,struct argnod * arglist,int line,int type,struct argnod * cmd)100 static unsigned long writedefs(Lex_t *lexp,struct argnod *arglist, int line, int type, struct argnod *cmd)
101 {
102 register struct argnod *argp = arglist;
103 register char *cp;
104 register int n,eline;
105 int width=0;
106 unsigned long r=0;
107 static char atbuff[20];
108 int justify=0;
109 char *attribute = atbuff;
110 unsigned long parent=lexp->script;
111 if(type==0)
112 {
113 parent = lexp->current;
114 type = 'v';
115 switch(*argp->argval)
116 {
117 case 'a':
118 type='p';
119 justify = 'a';
120 break;
121 case 'e':
122 *attribute++ = 'x';
123 break;
124 case 'r':
125 *attribute++ = 'r';
126 break;
127 case 'l':
128 break;
129 }
130 while(argp = argp->argnxt.ap)
131 {
132 if((n= *(cp=argp->argval))!='-' && n!='+')
133 break;
134 if(cp[1]==n)
135 break;
136 while((n= *++cp))
137 {
138 if(isdigit(n))
139 width = 10*width + n-'0';
140 else if(n=='L' || n=='R' || n =='Z')
141 justify=n;
142 else
143 *attribute++ = n;
144 }
145 }
146 }
147 else if(cmd)
148 parent=kiaentity(lexp,sh_argstr(cmd),-1,'p',-1,-1,lexp->unknown,'b',0,"");
149 *attribute = 0;
150 while(argp)
151 {
152 if((cp=strchr(argp->argval,'='))||(cp=strchr(argp->argval,'?')))
153 n = cp-argp->argval;
154 else
155 n = strlen(argp->argval);
156 eline = lexp->sh->inlineno-(lexp->token==NL);
157 r=kiaentity(lexp,argp->argval,n,type,line,eline,parent,justify,width,atbuff);
158 sfprintf(lexp->kiatmp,"p;%..64d;v;%..64d;%d;%d;s;\n",lexp->current,r,line,eline);
159 argp = argp->argnxt.ap;
160 }
161 return(r);
162 }
163 #endif /* SHOPT_KIA */
164
typeset_order(const char * str,int line)165 static void typeset_order(const char *str,int line)
166 {
167 register int c,n=0;
168 unsigned const char *cp=(unsigned char*)str;
169 static unsigned char *table;
170 if(*cp!='+' && *cp!='-')
171 return;
172 if(!table)
173 {
174 table = calloc(1,256);
175 for(cp=(unsigned char*)"bflmnprstuxACHS";c = *cp; cp++)
176 table[c] = 1;
177 for(cp=(unsigned char*)"aiEFLRXhTZ";c = *cp; cp++)
178 table[c] = 2;
179 for(c='0'; c <='9'; c++)
180 table[c] = 3;
181 }
182 for(cp=(unsigned char*)str; c= *cp++; n=table[c])
183 {
184 if(table[c] < n)
185 errormsg(SH_DICT,ERROR_warn(0),e_lextypeset,line,str);
186 }
187 }
188
189 /*
190 * add type definitions when compiling with -n
191 */
check_typedef(struct comnod * tp)192 static void check_typedef(struct comnod *tp)
193 {
194 char *cp=0;
195 if(tp->comtyp&COMSCAN)
196 {
197 struct argnod *ap = tp->comarg;
198 while(ap = ap->argnxt.ap)
199 {
200 if(!(ap->argflag&ARG_RAW) || memcmp(ap->argval,"--",2))
201 break;
202 if(sh_isoption(SH_NOEXEC))
203 typeset_order(ap->argval,tp->comline);
204 if(memcmp(ap->argval,"-T",2)==0)
205 {
206 if(ap->argval[2])
207 cp = ap->argval+2;
208 else if((ap->argnxt.ap)->argflag&ARG_RAW)
209 cp = (ap->argnxt.ap)->argval;
210 if(cp)
211 break;
212 }
213 }
214 }
215 else
216 {
217 struct dolnod *dp = (struct dolnod*)tp->comarg;
218 char **argv = dp->dolval + dp->dolbot+1;
219 while((cp= *argv++) && memcmp(cp,"--",2))
220 {
221 if(sh_isoption(SH_NOEXEC))
222 typeset_order(cp,tp->comline);
223 if(memcmp(cp,"-T",2)==0)
224 {
225 if(cp[2])
226 cp = cp+2;
227 else
228 cp = *argv;
229 break;
230 }
231 }
232 }
233 if(cp)
234 {
235 Namval_t *mp=(Namval_t*)tp->comnamp ,*bp;
236 bp = sh_addbuiltin(cp, (Shbltin_f)mp->nvalue.bfp, (void*)0);
237 nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
238 }
239 }
240
241 /*
242 * Make a parent node for fork() or io-redirection
243 */
makeparent(Lex_t * lp,int flag,Shnode_t * child)244 static Shnode_t *makeparent(Lex_t *lp, int flag, Shnode_t *child)
245 {
246 register Shnode_t *par = getnode(forknod);
247 par->fork.forktyp = flag;
248 par->fork.forktre = child;
249 par->fork.forkio = 0;
250 par->fork.forkline = sh_getlineno(lp)-1;
251 return(par);
252 }
253
paramsub(const char * str)254 static int paramsub(const char *str)
255 {
256 register int c,sub=0,lit=0;
257 while(c= *str++)
258 {
259 if(c=='$' && !lit)
260 {
261 if(*str=='(')
262 return(0);
263 if(sub)
264 continue;
265 if(*str=='{')
266 str++;
267 if(!isdigit(*str) && strchr("?#@*!$ ",*str)==0)
268 return(1);
269 }
270 else if(c=='`')
271 return(0);
272 else if(c=='[' && !lit)
273 sub++;
274 else if(c==']' && !lit)
275 sub--;
276 else if(c=='\'')
277 lit = !lit;
278 }
279 return(0);
280 }
281
getanode(Lex_t * lp,struct argnod * ap)282 static Shnode_t *getanode(Lex_t *lp, struct argnod *ap)
283 {
284 register Shnode_t *t = getnode(arithnod);
285 t->ar.artyp = TARITH;
286 t->ar.arline = sh_getlineno(lp);
287 t->ar.arexpr = ap;
288 if(ap->argflag&ARG_RAW)
289 t->ar.arcomp = sh_arithcomp(lp->sh,ap->argval);
290 else
291 {
292 if(sh_isoption(SH_NOEXEC) && (ap->argflag&ARG_MAC) && paramsub(ap->argval))
293 errormsg(SH_DICT,ERROR_warn(0),e_lexwarnvar,lp->sh->inlineno);
294 t->ar.arcomp = 0;
295 }
296 return(t);
297 }
298
299 /*
300 * Make a node corresponding to a command list
301 */
makelist(Lex_t * lexp,int type,Shnode_t * l,Shnode_t * r)302 static Shnode_t *makelist(Lex_t *lexp, int type, Shnode_t *l, Shnode_t *r)
303 {
304 register Shnode_t *t;
305 if(!l || !r)
306 sh_syntax(lexp);
307 else
308 {
309 if((type&COMMSK) == TTST)
310 t = getnode(tstnod);
311 else
312 t = getnode(lstnod);
313 t->lst.lsttyp = type;
314 t->lst.lstlef = l;
315 t->lst.lstrit = r;
316 }
317 return(t);
318 }
319
320 /*
321 * entry to shell parser
322 * Flag can be the union of SH_EOF|SH_NL
323 */
324
sh_parse(Shell_t * shp,Sfio_t * iop,int flag)325 void *sh_parse(Shell_t *shp, Sfio_t *iop, int flag)
326 {
327 register Shnode_t *t;
328 Lex_t *lexp = (Lex_t*)shp->lex_context;
329 Fcin_t sav_input;
330 struct argnod *sav_arg = lexp->arg;
331 int sav_prompt = shp->nextprompt;
332 if(shp->binscript && (sffileno(iop)==shp->infd || (flag&SH_FUNEVAL)))
333 return((void*)sh_trestore(shp,iop));
334 fcsave(&sav_input);
335 shp->st.staklist = 0;
336 lexp->noreserv = 0;
337 lexp->heredoc = 0;
338 lexp->inlineno = shp->inlineno;
339 lexp->firstline = shp->st.firstline;
340 shp->nextprompt = 1;
341 loop_level = 0;
342 label_list = label_last = 0;
343 if(sh_isoption(SH_INTERACTIVE))
344 sh_onstate(SH_INTERACTIVE);
345 if(sh_isoption(SH_VERBOSE))
346 sh_onstate(SH_VERBOSE);
347 sh_lexopen(lexp,shp,0);
348 if(fcfopen(iop) < 0)
349 return(NIL(void*));
350 if(fcfile())
351 {
352 char *cp = fcfirst();
353 if( cp[0]==CNTL('k') && cp[1]==CNTL('s') && cp[2]==CNTL('h') && cp[3]==0)
354 {
355 int version;
356 fcseek(4);
357 fcgetc(version);
358 fcclose();
359 fcrestore(&sav_input);
360 lexp->arg = sav_arg;
361 if(version > 3)
362 errormsg(SH_DICT,ERROR_exit(1),e_lexversion);
363 if(sffileno(iop)==shp->infd || (flag&SH_FUNEVAL))
364 shp->binscript = 1;
365 sfgetc(iop);
366 t = sh_trestore(shp,iop);
367 if(flag&SH_NL)
368 {
369 Shnode_t *tt;
370 while(1)
371 {
372 if(!(tt = sh_trestore(shp,iop)))
373 break;
374 t =makelist(lexp,TLST, t, tt);
375 }
376 }
377 return((void*)t);
378 }
379 }
380 flag &= ~SH_FUNEVAL;
381 if((flag&SH_NL) && (shp->inlineno=error_info.line+shp->st.firstline)==0)
382 shp->inlineno=1;
383 #if KSHELL
384 shp->nextprompt = 2;
385 #endif
386 t = sh_cmd(lexp,(flag&SH_EOF)?EOFSYM:'\n',SH_SEMI|SH_EMPTY|(flag&SH_NL));
387 fcclose();
388 fcrestore(&sav_input);
389 lexp->arg = sav_arg;
390 /* unstack any completed alias expansions */
391 if((sfset(iop,0,0)&SF_STRING) && !sfreserve(iop,0,-1))
392 {
393 Sfio_t *sp = sfstack(iop,NULL);
394 if(sp)
395 sfclose(sp);
396 }
397 shp->nextprompt = sav_prompt;
398 if(flag&SH_NL)
399 {
400 shp->st.firstline = lexp->firstline;
401 shp->inlineno = lexp->inlineno;
402 }
403 stkseek(shp->stk,0);
404 return((void*)t);
405 }
406
407 /*
408 * This routine parses up the matching right parenthesis and returns
409 * the parse tree
410 */
sh_dolparen(Lex_t * lp)411 Shnode_t *sh_dolparen(Lex_t* lp)
412 {
413 register Shnode_t *t=0;
414 Sfio_t *sp = fcfile();
415 int line = lp->sh->inlineno;
416 lp->sh->inlineno = error_info.line+lp->sh->st.firstline;
417 sh_lexopen(lp,lp->sh,1);
418 lp->comsub = 1;
419 switch(sh_lex(lp))
420 {
421 /* ((...)) arithmetic expression */
422 case EXPRSYM:
423 t = getanode(lp,lp->arg);
424 break;
425 case LPAREN:
426 t = sh_cmd(lp,RPAREN,SH_NL|SH_EMPTY);
427 break;
428 case LBRACE:
429 t = sh_cmd(lp,RBRACE,SH_NL|SH_EMPTY);
430 break;
431 }
432 lp->comsub = 0;
433 if(!sp && (sp=fcfile()))
434 {
435 /*
436 * This code handles the case where string has been converted
437 * to a file by an alias setup
438 */
439 register int c;
440 char *cp;
441 if(fcgetc(c) > 0)
442 fcseek(-1);
443 cp = fcseek(0);
444 fcclose();
445 fcsopen(cp);
446 sfclose(sp);
447 }
448 lp->sh->inlineno = line;
449 return(t);
450 }
451
452 /*
453 * remove temporary files and stacks
454 */
455
sh_freeup(Shell_t * shp)456 void sh_freeup(Shell_t *shp)
457 {
458 if(shp->st.staklist)
459 sh_funstaks(shp->st.staklist,-1);
460 shp->st.staklist = 0;
461 }
462
463 /*
464 * increase reference count for each stack in function list when flag>0
465 * decrease reference count for each stack in function list when flag<=0
466 * stack is freed when reference count is zero
467 */
468
sh_funstaks(register struct slnod * slp,int flag)469 void sh_funstaks(register struct slnod *slp,int flag)
470 {
471 register struct slnod *slpold;
472 while(slpold=slp)
473 {
474 if(slp->slchild)
475 sh_funstaks(slp->slchild,flag);
476 slp = slp->slnext;
477 if(flag<=0)
478 stakdelete(slpold->slptr);
479 else
480 staklink(slpold->slptr);
481 }
482 }
483 /*
484 * cmd
485 * empty
486 * list
487 * list & [ cmd ]
488 * list [ ; cmd ]
489 */
490
sh_cmd(Lex_t * lexp,register int sym,int flag)491 static Shnode_t *sh_cmd(Lex_t *lexp, register int sym, int flag)
492 {
493 register Shnode_t *left, *right;
494 register int type = FINT|FAMP;
495 if(sym==NL)
496 lexp->lasttok = 0;
497 left = list(lexp,flag);
498 if(lexp->token==NL)
499 {
500 if(flag&SH_NL)
501 lexp->token=';';
502 }
503 else if(!left && !(flag&SH_EMPTY))
504 sh_syntax(lexp);
505 switch(lexp->token)
506 {
507 case COOPSYM: /* set up a cooperating process */
508 type |= (FPIN|FPOU|FPCL|FCOOP);
509 /* FALLTHROUGH */
510 case '&':
511 if(left)
512 {
513 /* (...)& -> {...;} & */
514 if(left->tre.tretyp==TPAR)
515 left = left->par.partre;
516 left = makeparent(lexp,TFORK|type, left);
517 }
518 /* FALLTHROUGH */
519 case ';':
520 if(!left)
521 sh_syntax(lexp);
522 if(right=sh_cmd(lexp,sym,flag|SH_EMPTY))
523 left=makelist(lexp,TLST, left, right);
524 break;
525 case EOFSYM:
526 if(sym==NL)
527 break;
528 /* FALLTHROUGH */
529 default:
530 if(sym && sym!=lexp->token)
531 {
532 if(sym!=ELSESYM || (lexp->token!=ELIFSYM && lexp->token!=FISYM))
533 sh_syntax(lexp);
534 }
535 }
536 return(left);
537 }
538
539 /*
540 * list
541 * term
542 * list && term
543 * list || term
544 * unfortunately, these are equal precedence
545 */
list(Lex_t * lexp,register int flag)546 static Shnode_t *list(Lex_t *lexp, register int flag)
547 {
548 register Shnode_t *t = term(lexp,flag);
549 register int token;
550 while(t && ((token=lexp->token)==ANDFSYM || token==ORFSYM))
551 t = makelist(lexp,(token==ANDFSYM?TAND:TORF), t, term(lexp,SH_NL|SH_SEMI));
552 return(t);
553 }
554
555 /*
556 * term
557 * item
558 * item | term
559 */
term(Lex_t * lexp,register int flag)560 static Shnode_t *term(Lex_t *lexp,register int flag)
561 {
562 register Shnode_t *t;
563 register int token;
564 if(flag&SH_NL)
565 token = skipnl(lexp,flag);
566 else
567 token = sh_lex(lexp);
568 /* check to see if pipeline is to be timed */
569 if(token==TIMESYM || token==NOTSYM)
570 {
571 t = getnode(parnod);
572 t->par.partyp=TTIME;
573 if(lexp->token==NOTSYM)
574 t->par.partyp |= COMSCAN;
575 t->par.partre = term(lexp,0);
576 }
577 #if SHOPT_COSHELL
578 else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && (lexp->token=='|' || lexp->token==PIPESYM2))
579 #else
580 else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && lexp->token=='|')
581 #endif /* SHOPT_COSHELL */
582 {
583 register Shnode_t *tt;
584 int showme = t->tre.tretyp&FSHOWME;
585 t = makeparent(lexp,TFORK|FPOU,t);
586 #if SHOPT_COSHELL
587 if(lexp->token==PIPESYM2)
588 t->tre.tretyp |= FALTPIPE;
589 #endif /* SHOPT_COSHELL */
590 if(tt=term(lexp,SH_NL))
591 {
592 switch(tt->tre.tretyp&COMMSK)
593 {
594 case TFORK:
595 tt->tre.tretyp |= FPIN|FPCL;
596 break;
597 case TFIL:
598 tt->lst.lstlef->tre.tretyp |= FPIN|FPCL;
599 break;
600 default:
601 tt= makeparent(lexp,TSETIO|FPIN|FPCL,tt);
602 }
603 t=makelist(lexp,TFIL,t,tt);
604 t->tre.tretyp |= showme;
605 }
606 else if(lexp->token)
607 sh_syntax(lexp);
608 }
609 return(t);
610 }
611
612 /*
613 * case statement
614 */
syncase(Lex_t * lexp,register int esym)615 static struct regnod* syncase(Lex_t *lexp,register int esym)
616 {
617 register int tok = skipnl(lexp,0);
618 register struct regnod *r;
619 if(tok==esym)
620 return(NIL(struct regnod*));
621 r = (struct regnod*)stakalloc(sizeof(struct regnod));
622 r->regptr=0;
623 r->regflag=0;
624 if(tok==LPAREN)
625 skipnl(lexp,0);
626 while(1)
627 {
628 if(!lexp->arg)
629 sh_syntax(lexp);
630 lexp->arg->argnxt.ap=r->regptr;
631 r->regptr = lexp->arg;
632 if((tok=sh_lex(lexp))==RPAREN)
633 break;
634 else if(tok=='|')
635 sh_lex(lexp);
636 else
637 sh_syntax(lexp);
638 }
639 r->regcom=sh_cmd(lexp,0,SH_NL|SH_EMPTY|SH_SEMI);
640 if((tok=lexp->token)==BREAKCASESYM)
641 r->regnxt=syncase(lexp,esym);
642 else if(tok==FALLTHRUSYM)
643 {
644 r->regflag++;
645 r->regnxt=syncase(lexp,esym);
646 }
647 else
648 {
649 if(tok!=esym && tok!=EOFSYM)
650 sh_syntax(lexp);
651 r->regnxt=0;
652 }
653 if(lexp->token==EOFSYM)
654 return(NIL(struct regnod*));
655 return(r);
656 }
657
658 /*
659 * This routine creates the parse tree for the arithmetic for
660 * When called, shlex.arg contains the string inside ((...))
661 * When the first argument is missing, a while node is returned
662 * Otherise a list containing an arithmetic command and a while
663 * is returned.
664 */
arithfor(Lex_t * lexp,register Shnode_t * tf)665 static Shnode_t *arithfor(Lex_t *lexp,register Shnode_t *tf)
666 {
667 register Shnode_t *t, *tw = tf;
668 register int offset;
669 register struct argnod *argp;
670 register int n;
671 Stk_t *stkp = lexp->sh->stk;
672 int argflag = lexp->arg->argflag;
673 /* save current input */
674 Fcin_t sav_input;
675 fcsave(&sav_input);
676 fcsopen(lexp->arg->argval);
677 /* split ((...)) into three expressions */
678 for(n=0; ; n++)
679 {
680 register int c;
681 argp = (struct argnod*)stkseek(stkp,ARGVAL);
682 argp->argnxt.ap = 0;
683 argp->argchn.cp = 0;
684 argp->argflag = argflag;
685 if(n==2)
686 break;
687 /* copy up to ; onto the stack */
688 sh_lexskip(lexp,';',1,ST_NESTED);
689 offset = stktell(stkp)-1;
690 if((c=fcpeek(-1))!=';')
691 break;
692 /* remove trailing white space */
693 while(offset>ARGVAL && ((c= *stkptr(stkp,offset-1)),isspace(c)))
694 offset--;
695 /* check for empty initialization expression */
696 if(offset==ARGVAL && n==0)
697 continue;
698 stkseek(stkp,offset);
699 /* check for empty condition and treat as while((1)) */
700 if(offset==ARGVAL)
701 sfputc(stkp,'1');
702 argp = (struct argnod*)stkfreeze(stkp,1);
703 t = getanode(lexp,argp);
704 if(n==0)
705 tf = makelist(lexp,TLST,t,tw);
706 else
707 tw->wh.whtre = t;
708 }
709 while((offset=fcpeek(0)) && isspace(offset))
710 fcseek(1);
711 stakputs(fcseek(0));
712 argp = (struct argnod*)stakfreeze(1);
713 fcrestore(&sav_input);
714 if(n<2)
715 {
716 lexp->token = RPAREN|SYMREP;
717 sh_syntax(lexp);
718 }
719 /* check whether the increment is present */
720 if(*argp->argval)
721 {
722 t = getanode(lexp,argp);
723 tw->wh.whinc = (struct arithnod*)t;
724 }
725 else
726 tw->wh.whinc = 0;
727 sh_lexopen(lexp, lexp->sh,1);
728 if((n=sh_lex(lexp))==NL)
729 n = skipnl(lexp,0);
730 else if(n==';')
731 n = sh_lex(lexp);
732 if(n!=DOSYM && n!=LBRACE)
733 sh_syntax(lexp);
734 tw->wh.dotre = sh_cmd(lexp,n==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
735 tw->wh.whtyp = TWH;
736 return(tf);
737
738 }
739
funct(Lex_t * lexp)740 static Shnode_t *funct(Lex_t *lexp)
741 {
742 Shell_t *shp = lexp->sh;
743 register Shnode_t *t;
744 register int flag;
745 struct slnod *volatile slp=0;
746 Stak_t *savstak;
747 Sfoff_t first, last;
748 struct functnod *volatile fp;
749 Sfio_t *iop;
750 #if SHOPT_KIA
751 unsigned long current = lexp->current;
752 #endif /* SHOPT_KIA */
753 int nargs=0,size=0,jmpval, saveloop=loop_level;
754 struct argnod *savelabel = label_last;
755 struct checkpt buff;
756 int save_optget = opt_get;
757 void *in_mktype = shp->mktype;
758 shp->mktype = 0;
759 opt_get = 0;
760 t = getnode(functnod);
761 t->funct.functline = shp->inlineno;
762 t->funct.functtyp=TFUN;
763 t->funct.functargs = 0;
764 if(!(flag = (lexp->token==FUNCTSYM)))
765 t->funct.functtyp |= FPOSIX;
766 else if(sh_lex(lexp))
767 sh_syntax(lexp);
768 if(!(iop=fcfile()))
769 {
770 iop = sfopen(NIL(Sfio_t*),fcseek(0),"s");
771 fcclose();
772 fcfopen(iop);
773 }
774 t->funct.functloc = first = fctell();
775 if(!shp->st.filename || sffileno(iop)<0)
776 {
777 if(fcfill() >= 0)
778 fcseek(-1);
779 if(sh_isstate(SH_HISTORY) && shp->gd->hist_ptr)
780 t->funct.functloc = sfseek(shp->gd->hist_ptr->histfp,(off_t)0,SEEK_CUR);
781 else
782 {
783 /* copy source to temporary file */
784 t->funct.functloc = 0;
785 if(lexp->sh->heredocs)
786 t->funct.functloc = sfseek(lexp->sh->heredocs,(Sfoff_t)0, SEEK_END);
787 else
788 lexp->sh->heredocs = sftmp(HERE_MEM);
789 lexp->sh->funlog = lexp->sh->heredocs;
790 t->funct.functtyp |= FPIN;
791 }
792 }
793 t->funct.functnam= (char*)lexp->arg->argval;
794 #if SHOPT_KIA
795 if(lexp->kiafile)
796 lexp->current = kiaentity(lexp,t->funct.functnam,-1,'p',-1,-1,lexp->script,'p',0,"");
797 #endif /* SHOPT_KIA */
798 if(flag)
799 {
800 lexp->token = sh_lex(lexp);
801 #if SHOPT_BASH
802 if(lexp->token == LPAREN)
803 {
804 if((lexp->token = sh_lex(lexp)) == RPAREN)
805 t->funct.functtyp |= FPOSIX;
806 else
807 sh_syntax(lexp);
808 }
809 #endif
810 }
811 if(t->funct.functtyp&FPOSIX)
812 skipnl(lexp,0);
813 else
814 {
815 if(lexp->token==0)
816 {
817 struct comnod *ac;
818 char *cp, **argv, **argv0;
819 int c;
820 t->funct.functargs = ac = (struct comnod*)simple(lexp,SH_NOIO|SH_FUNDEF,NIL(struct ionod*));
821 if(ac->comset || (ac->comtyp&COMSCAN))
822 errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,lexp->sh->inlineno);
823 argv0 = argv = ((struct dolnod*)ac->comarg)->dolval+ARG_SPARE;
824 while(cp= *argv++)
825 {
826 size += strlen(cp)+1;
827 if((c = mbchar(cp)) && isaletter(c))
828 while(c=mbchar(cp), isaname(c));
829 }
830 if(c)
831 errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,lexp->sh->inlineno);
832 nargs = argv-argv0;
833 size += sizeof(struct dolnod)+(nargs+ARG_SPARE)*sizeof(char*);
834 if(shp->shcomp && memcmp(".sh.math.",t->funct.functnam,9)==0)
835 {
836 Namval_t *np= nv_open(t->funct.functnam,shp->fun_tree,NV_ADD|NV_VARNAME);
837 np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
838 memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
839 np->nvalue.rp->argc = ((struct dolnod*)ac->comarg)->dolnum;
840 }
841 }
842 while(lexp->token==NL)
843 lexp->token = sh_lex(lexp);
844 }
845 if((flag && lexp->token!=LBRACE) || lexp->token==EOFSYM)
846 sh_syntax(lexp);
847 sh_pushcontext(shp,&buff,1);
848 jmpval = sigsetjmp(buff.buff,0);
849 if(jmpval == 0)
850 {
851 /* create a new stak frame to compile the command */
852 savstak = stakcreate(STAK_SMALL);
853 savstak = stakinstall(savstak, 0);
854 slp = (struct slnod*)stakalloc(sizeof(struct slnod)+sizeof(struct functnod));
855 slp->slchild = 0;
856 slp->slnext = shp->st.staklist;
857 shp->st.staklist = 0;
858 t->funct.functstak = (struct slnod*)slp;
859 /*
860 * store the pathname of function definition file on stack
861 * in name field of fake for node
862 */
863 fp = (struct functnod*)(slp+1);
864 fp->functtyp = TFUN|FAMP;
865 fp->functnam = 0;
866 fp->functargs = 0;
867 fp->functline = t->funct.functline;
868 if(shp->st.filename)
869 fp->functnam = stakcopy(shp->st.filename);
870 loop_level = 0;
871 label_last = label_list;
872 if(size)
873 {
874 struct dolnod *dp = (struct dolnod*)stakalloc(size);
875 char *cp, *sp, **argv, **old = ((struct dolnod*)t->funct.functargs->comarg)->dolval+1;
876 argv = ((char**)(dp->dolval))+1;
877 dp->dolnum = ((struct dolnod*)t->funct.functargs->comarg)->dolnum;
878 t->funct.functargs->comarg = (struct argnod*)dp;
879 for(cp=(char*)&argv[nargs]; sp= *old++; cp++)
880 {
881 *argv++ = cp;
882 cp = strcopy(cp,sp);
883 }
884 *argv = 0;
885 }
886 if(!flag && lexp->token==0)
887 {
888 /* copy current word token to current stak frame */
889 struct argnod *ap;
890 flag = ARGVAL + strlen(lexp->arg->argval);
891 ap = (struct argnod*)stakalloc(flag);
892 memcpy(ap,lexp->arg,flag);
893 lexp->arg = ap;
894 }
895 t->funct.functtre = item(lexp,SH_NOIO);
896 }
897 else if(shp->shcomp)
898 exit(1);
899 sh_popcontext(shp,&buff);
900 loop_level = saveloop;
901 label_last = savelabel;
902 /* restore the old stack */
903 if(slp)
904 {
905 slp->slptr = stakinstall(savstak,0);
906 slp->slchild = shp->st.staklist;
907 }
908 #if SHOPT_KIA
909 lexp->current = current;
910 #endif /* SHOPT_KIA */
911 if(jmpval)
912 {
913 if(slp && slp->slptr)
914 {
915 shp->st.staklist = slp->slnext;
916 stakdelete(slp->slptr);
917 }
918 siglongjmp(*shp->jmplist,jmpval);
919 }
920 shp->st.staklist = (struct slnod*)slp;
921 last = fctell();
922 fp->functline = (last-first);
923 fp->functtre = t;
924 shp->mktype = in_mktype;
925 if(lexp->sh->funlog)
926 {
927 if(fcfill()>0)
928 fcseek(-1);
929 lexp->sh->funlog = 0;
930 }
931 #if SHOPT_KIA
932 if(lexp->kiafile)
933 kiaentity(lexp,t->funct.functnam,-1,'p',t->funct.functline,shp->inlineno-1,lexp->current,'p',0,"");
934 #endif /* SHOPT_KIA */
935 t->funct.functtyp |= opt_get;
936 opt_get = save_optget;
937 return(t);
938 }
939
940 /*
941 * Compound assignment
942 */
assign(Lex_t * lexp,register struct argnod * ap,int type)943 static struct argnod *assign(Lex_t *lexp, register struct argnod *ap, int type)
944 {
945 register int n;
946 register Shnode_t *t, **tp;
947 register struct comnod *ac;
948 Stk_t *stkp = lexp->sh->stk;
949 int array=0, index=0;
950 Namval_t *np;
951 n = strlen(ap->argval)-1;
952 if(ap->argval[n]!='=')
953 sh_syntax(lexp);
954 if(ap->argval[n-1]=='+')
955 {
956 ap->argval[n--]=0;
957 array = ARG_APPEND;
958 type |= NV_APPEND;
959 }
960 /* shift right */
961 while(n > 0)
962 {
963 ap->argval[n] = ap->argval[n-1];
964 n--;
965 }
966 *ap->argval=0;
967 t = getnode(fornod);
968 t->for_.fornam = (char*)(ap->argval+1);
969 t->for_.fortyp = sh_getlineno(lexp);
970 tp = &t->for_.fortre;
971 ap->argchn.ap = (struct argnod*)t;
972 ap->argflag &= ARG_QUOTED;
973 ap->argflag |= array;
974 lexp->assignok = SH_ASSIGN;
975 if(type==NV_ARRAY)
976 {
977 lexp->noreserv = 1;
978 lexp->assignok = 0;
979 }
980 else
981 lexp->aliasok = 2;
982 array= (type==NV_ARRAY)?SH_ARRAY:0;
983 if((n=skipnl(lexp,0))==RPAREN || n==LPAREN)
984 {
985 struct argnod *ar,*aq,**settail;
986 ac = (struct comnod*)getnode(comnod);
987 memset((void*)ac,0,sizeof(*ac));
988 comarray:
989 settail= &ac->comset;
990 ac->comline = sh_getlineno(lexp);
991 while(n==LPAREN)
992 {
993 ar = (struct argnod*)stkseek(stkp,ARGVAL);
994 ar->argflag= ARG_ASSIGN;
995 sfprintf(stkp,"[%d]=",index++);
996 if(aq=ac->comarg)
997 {
998 ac->comarg = aq->argnxt.ap;
999 sfprintf(stkp,"%s",aq->argval);
1000 ar->argflag |= aq->argflag;
1001 }
1002 ar = (struct argnod*)stkfreeze(stkp,1);
1003 ar->argnxt.ap = 0;
1004 if(!aq)
1005 ar = assign(lexp,ar,0);
1006 ar->argflag |= ARG_MESSAGE;
1007 *settail = ar;
1008 settail = &(ar->argnxt.ap);
1009 if(aq)
1010 continue;
1011 while((n = skipnl(lexp,0))==0)
1012 {
1013 ar = (struct argnod*)stkseek(stkp,ARGVAL);
1014 ar->argflag= ARG_ASSIGN;
1015 sfprintf(stkp,"[%d]=",index++);
1016 stakputs(lexp->arg->argval);
1017 ar = (struct argnod*)stkfreeze(stkp,1);
1018 ar->argnxt.ap = 0;
1019 ar->argflag = lexp->arg->argflag;
1020 *settail = ar;
1021 settail = &(ar->argnxt.ap);
1022 }
1023 }
1024 }
1025 else if(n && n!=FUNCTSYM)
1026 sh_syntax(lexp);
1027 else if(type!=NV_ARRAY && n!=FUNCTSYM && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)|| np==SYSDOT)))
1028 {
1029 array=SH_ARRAY;
1030 if(fcgetc(n)==LPAREN)
1031 {
1032 int c;
1033 if(fcgetc(c)==RPAREN)
1034 {
1035 lexp->token = SYMRES;
1036 array = 0;
1037 }
1038 else
1039 fcseek(-2);
1040 }
1041 else if(n>0)
1042 fcseek(-1);
1043 if(array && type==NV_TYPE)
1044 {
1045 struct argnod *arg = lexp->arg;
1046 n = lexp->token;
1047 if(path_search(lexp->sh,lexp->arg->argval,NIL(Pathcomp_t**),1) && (np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && nv_isattr(np,BLT_DCL))
1048 {
1049 lexp->token = n;
1050 lexp->arg = arg;
1051 array = 0;
1052 }
1053 else
1054 sh_syntax(lexp);
1055 }
1056 }
1057 lexp->noreserv = 0;
1058 while(1)
1059 {
1060 if((n=lexp->token)==RPAREN)
1061 break;
1062 if(n==FUNCTSYM || n==SYMRES)
1063 ac = (struct comnod*)funct(lexp);
1064 else
1065 ac = (struct comnod*)simple(lexp,SH_NOIO|SH_ASSIGN|type|array,NIL(struct ionod*));
1066 if((n=lexp->token)==RPAREN)
1067 break;
1068 if(n!=NL && n!=';')
1069 {
1070 if(array && n==LPAREN)
1071 goto comarray;
1072 sh_syntax(lexp);
1073 }
1074 lexp->assignok = SH_ASSIGN;
1075 if((n=skipnl(lexp,0)) || array)
1076 {
1077 if(n==RPAREN)
1078 break;
1079 if(array || n!=FUNCTSYM)
1080 sh_syntax(lexp);
1081 }
1082 if((n!=FUNCTSYM) && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)||np==SYSDOT)))
1083 {
1084 struct argnod *arg = lexp->arg;
1085 if(n!=0)
1086 sh_syntax(lexp);
1087 /* check for sys5 style function */
1088 if(sh_lex(lexp)!=LPAREN || sh_lex(lexp)!=RPAREN)
1089 {
1090 lexp->arg = arg;
1091 lexp->token = 0;
1092 sh_syntax(lexp);
1093 }
1094 lexp->arg = arg;
1095 lexp->token = SYMRES;
1096 }
1097 t = makelist(lexp,TLST,(Shnode_t*)ac,t);
1098 *tp = t;
1099 tp = &t->lst.lstrit;
1100 }
1101 *tp = (Shnode_t*)ac;
1102 lexp->assignok = 0;
1103 return(ap);
1104 }
1105
1106 /*
1107 * item
1108 *
1109 * ( cmd ) [ < in ] [ > out ]
1110 * word word* [ < in ] [ > out ]
1111 * if ... then ... else ... fi
1112 * for ... while ... do ... done
1113 * case ... in ... esac
1114 * begin ... end
1115 */
1116
item(Lex_t * lexp,int flag)1117 static Shnode_t *item(Lex_t *lexp,int flag)
1118 {
1119 register Shnode_t *t;
1120 register struct ionod *io;
1121 register int tok = (lexp->token&0xff);
1122 int savwdval = lexp->lasttok;
1123 int savline = lexp->lastline;
1124 int showme=0, comsub;
1125 if(!(flag&SH_NOIO) && (tok=='<' || tok=='>' || lexp->token==IOVNAME))
1126 io=inout(lexp,NIL(struct ionod*),1);
1127 else
1128 io=0;
1129 if((tok=lexp->token) && tok!=EOFSYM && tok!=FUNCTSYM)
1130 {
1131 lexp->lastline = sh_getlineno(lexp);
1132 lexp->lasttok = lexp->token;
1133 }
1134 switch(tok)
1135 {
1136 /* [[ ... ]] test expression */
1137 case BTESTSYM:
1138 t = test_expr(lexp,ETESTSYM);
1139 t->tre.tretyp &= ~TTEST;
1140 break;
1141 /* ((...)) arithmetic expression */
1142 case EXPRSYM:
1143 t = getanode(lexp,lexp->arg);
1144 sh_lex(lexp);
1145 goto done;
1146
1147 /* case statement */
1148 case CASESYM:
1149 {
1150 int savetok = lexp->lasttok;
1151 int saveline = lexp->lastline;
1152 t = getnode(swnod);
1153 if(sh_lex(lexp))
1154 sh_syntax(lexp);
1155 t->sw.swarg=lexp->arg;
1156 t->sw.swtyp=TSW;
1157 t->sw.swio = 0;
1158 t->sw.swtyp |= FLINENO;
1159 t->sw.swline = lexp->sh->inlineno;
1160 if((tok=skipnl(lexp,0))!=INSYM && tok!=LBRACE)
1161 sh_syntax(lexp);
1162 if(!(t->sw.swlst=syncase(lexp,tok==INSYM?ESACSYM:RBRACE)) && lexp->token==EOFSYM)
1163 {
1164 lexp->lasttok = savetok;
1165 lexp->lastline = saveline;
1166 sh_syntax(lexp);
1167 }
1168 break;
1169 }
1170
1171 /* if statement */
1172 case IFSYM:
1173 {
1174 register Shnode_t *tt;
1175 t = getnode(ifnod);
1176 t->if_.iftyp=TIF;
1177 t->if_.iftre=sh_cmd(lexp,THENSYM,SH_NL);
1178 t->if_.thtre=sh_cmd(lexp,ELSESYM,SH_NL|SH_SEMI);
1179 tok = lexp->token;
1180 t->if_.eltre=(tok==ELSESYM?sh_cmd(lexp,FISYM,SH_NL|SH_SEMI):
1181 (tok==ELIFSYM?(lexp->token=IFSYM, tt=item(lexp,SH_NOIO)):0));
1182 if(tok==ELIFSYM)
1183 {
1184 if(!tt || tt->tre.tretyp!=TSETIO)
1185 goto done;
1186 t->if_.eltre = tt->fork.forktre;
1187 tt->fork.forktre = t;
1188 t = tt;
1189 goto done;
1190 }
1191 break;
1192 }
1193
1194 /* for and select statement */
1195 case FORSYM:
1196 case SELECTSYM:
1197 {
1198 t = getnode(fornod);
1199 t->for_.fortyp=(lexp->token==FORSYM?TFOR:TSELECT);
1200 t->for_.forlst=0;
1201 t->for_.forline = lexp->sh->inlineno;
1202 if(sh_lex(lexp))
1203 {
1204 if(lexp->token!=EXPRSYM || t->for_.fortyp!=TFOR)
1205 sh_syntax(lexp);
1206 /* arithmetic for */
1207 t = arithfor(lexp,t);
1208 break;
1209 }
1210 t->for_.fornam=(char*) lexp->arg->argval;
1211 t->for_.fortyp |= FLINENO;
1212 #if SHOPT_KIA
1213 if(lexp->kiafile)
1214 writedefs(lexp,lexp->arg,lexp->sh->inlineno,'v',NIL(struct argnod*));
1215 #endif /* SHOPT_KIA */
1216 while((tok=sh_lex(lexp))==NL);
1217 if(tok==INSYM)
1218 {
1219 if(sh_lex(lexp))
1220 {
1221 if(lexp->token != NL && lexp->token !=';')
1222 sh_syntax(lexp);
1223 /* some Linux scripts assume this */
1224 if(sh_isoption(SH_NOEXEC))
1225 errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,lexp->sh->inlineno-(lexp->token=='\n'));
1226 t->for_.forlst = (struct comnod*)getnode(comnod);
1227 (t->for_.forlst)->comarg = 0;
1228 (t->for_.forlst)->comset = 0;
1229 (t->for_.forlst)->comnamp = 0;
1230 (t->for_.forlst)->comnamq = 0;
1231 (t->for_.forlst)->comstate = 0;
1232 (t->for_.forlst)->comio = 0;
1233 (t->for_.forlst)->comtyp = 0;
1234 }
1235 else
1236 t->for_.forlst=(struct comnod*)simple(lexp,SH_NOIO,NIL(struct ionod*));
1237 if(lexp->token != NL && lexp->token !=';')
1238 sh_syntax(lexp);
1239 tok = skipnl(lexp,0);
1240 }
1241 /* 'for i;do cmd' is valid syntax */
1242 else if(tok==';')
1243 while((tok=sh_lex(lexp))==NL);
1244 if(tok!=DOSYM && tok!=LBRACE)
1245 sh_syntax(lexp);
1246 loop_level++;
1247 t->for_.fortre=sh_cmd(lexp,tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
1248 if(--loop_level==0)
1249 label_last = label_list;
1250 break;
1251 }
1252
1253 /* This is the code for parsing function definitions */
1254 case FUNCTSYM:
1255 return(funct(lexp));
1256
1257 #if SHOPT_NAMESPACE
1258 case NSPACESYM:
1259 t = getnode(functnod);
1260 t->funct.functtyp=TNSPACE;
1261 t->funct.functargs = 0;
1262 t->funct.functloc = 0;
1263 if(sh_lex(lexp))
1264 sh_syntax(lexp);
1265 t->funct.functnam=(char*) lexp->arg->argval;
1266 while((tok=sh_lex(lexp))==NL);
1267 if(tok!=LBRACE)
1268 sh_syntax(lexp);
1269 t->funct.functtre = sh_cmd(lexp,RBRACE,SH_NL);
1270 break;
1271 #endif /* SHOPT_NAMESPACE */
1272
1273 /* while and until */
1274 case WHILESYM:
1275 case UNTILSYM:
1276 t = getnode(whnod);
1277 t->wh.whtyp=(lexp->token==WHILESYM ? TWH : TUN);
1278 loop_level++;
1279 t->wh.whtre = sh_cmd(lexp,DOSYM,SH_NL);
1280 t->wh.dotre = sh_cmd(lexp,DONESYM,SH_NL|SH_SEMI);
1281 if(--loop_level==0)
1282 label_last = label_list;
1283 t->wh.whinc = 0;
1284 break;
1285
1286 case LABLSYM:
1287 {
1288 register struct argnod *argp = label_list;
1289 while(argp)
1290 {
1291 if(strcmp(argp->argval,lexp->arg->argval)==0)
1292 errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax3,lexp->sh->inlineno,argp->argval);
1293 argp = argp->argnxt.ap;
1294 }
1295 lexp->arg->argnxt.ap = label_list;
1296 label_list = lexp->arg;
1297 label_list->argchn.len = sh_getlineno(lexp);
1298 label_list->argflag = loop_level;
1299 skipnl(lexp,flag);
1300 if(!(t = item(lexp,SH_NL)))
1301 sh_syntax(lexp);
1302 tok = (t->tre.tretyp&(COMSCAN|COMSCAN-1));
1303 if(sh_isoption(SH_NOEXEC) && tok!=TWH && tok!=TUN && tok!=TFOR && tok!=TSELECT)
1304 errormsg(SH_DICT,ERROR_warn(0),e_lexlabignore,label_list->argchn.len,label_list->argval);
1305 return(t);
1306 }
1307
1308 /* command group with {...} */
1309 case LBRACE:
1310 comsub = lexp->comsub;
1311 lexp->comsub = 0;
1312 t = sh_cmd(lexp,RBRACE,SH_NL|SH_SEMI);
1313 lexp->comsub = comsub;
1314 break;
1315
1316 case LPAREN:
1317 t = getnode(parnod);
1318 t->par.partre=sh_cmd(lexp,RPAREN,SH_NL|SH_SEMI);
1319 t->par.partyp=TPAR;
1320 break;
1321
1322 #if SHOPT_COSHELL
1323 case '&':
1324 if(tok=sh_lex(lexp))
1325 {
1326 if(tok!=NL)
1327 sh_syntax(lexp);
1328 t = getnode(comnod);
1329 memset(t,0,sizeof(struct comnod));
1330 t->com.comline = sh_getlineno(lexp);
1331 }
1332 else
1333 t = (Shnode_t*)simple(lexp,SH_NOIO,NIL(struct ionod*));
1334 t->com.comtyp |= FAMP;
1335 if(lexp->token=='&' || lexp->token=='|')
1336 sh_syntax(lexp);
1337 return(t);
1338 break;
1339 #endif /* SHOPT_COSHELL */
1340 default:
1341 if(io==0)
1342 return(0);
1343 /* FALLTHROUGH */
1344
1345 case ';':
1346 if(io==0)
1347 {
1348 if(!(flag&SH_SEMI))
1349 return(0);
1350 if(sh_lex(lexp)==';')
1351 sh_syntax(lexp);
1352 showme = FSHOWME;
1353 }
1354 /* FALLTHROUGH */
1355 case 0:
1356 t = (Shnode_t*)simple(lexp,flag,io);
1357 if(t->com.comarg && lexp->intypeset)
1358 check_typedef(&t->com);
1359 lexp->intypeset = 0;
1360 lexp->inexec = 0;
1361 t->tre.tretyp |= showme;
1362 return(t);
1363 }
1364 sh_lex(lexp);
1365 if(io=inout(lexp,io,0))
1366 {
1367 if((tok=t->tre.tretyp&COMMSK) != TFORK)
1368 tok = TSETIO;
1369 t=makeparent(lexp,tok,t);
1370 t->tre.treio=io;
1371 }
1372 done:
1373 lexp->lasttok = savwdval;
1374 lexp->lastline = savline;
1375 return(t);
1376 }
1377
process_sub(Lex_t * lexp,int tok)1378 static struct argnod *process_sub(Lex_t *lexp,int tok)
1379 {
1380 struct argnod *argp;
1381 Shnode_t *t;
1382 int mode = (tok==OPROCSYM);
1383 t = sh_cmd(lexp,RPAREN,SH_NL);
1384 argp = (struct argnod*)stkalloc(lexp->sh->stk,sizeof(struct argnod));
1385 *argp->argval = 0;
1386 argp->argchn.ap = (struct argnod*)makeparent(lexp,mode?TFORK|FPIN|FAMP|FPCL:TFORK|FPOU,t);
1387 argp->argflag = (ARG_EXP|mode);
1388 return(argp);
1389 }
1390
1391
1392 /*
1393 * This is for a simple command, for list, or compound assignment
1394 */
simple(Lex_t * lexp,int flag,struct ionod * io)1395 static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io)
1396 {
1397 register struct comnod *t;
1398 register struct argnod *argp;
1399 register int tok;
1400 Stk_t *stkp = lexp->sh->stk;
1401 struct argnod **argtail;
1402 struct argnod **settail;
1403 int cmdarg=0;
1404 int argno = 0;
1405 int assignment = 0;
1406 int key_on = (!(flag&SH_NOIO) && sh_isoption(SH_KEYWORD));
1407 int associative=0;
1408 if((argp=lexp->arg) && (argp->argflag&ARG_ASSIGN) && argp->argval[0]=='[')
1409 {
1410 flag |= SH_ARRAY;
1411 associative = 1;
1412 }
1413 t = (struct comnod*)getnode(comnod);
1414 t->comio=io; /*initial io chain*/
1415 /* set command line number for error messages */
1416 t->comline = sh_getlineno(lexp);
1417 argtail = &(t->comarg);
1418 t->comset = 0;
1419 t->comnamp = 0;
1420 t->comnamq = 0;
1421 t->comstate = 0;
1422 settail = &(t->comset);
1423 while(lexp->token==0)
1424 {
1425 argp = lexp->arg;
1426 if(*argp->argval==LBRACE && (flag&SH_FUNDEF) && argp->argval[1]==0)
1427 {
1428 lexp->token = LBRACE;
1429 break;
1430 }
1431 if(associative && argp->argval[0]!='[')
1432 sh_syntax(lexp);
1433 /* check for assignment argument */
1434 if((argp->argflag&ARG_ASSIGN) && assignment!=2)
1435 {
1436 *settail = argp;
1437 settail = &(argp->argnxt.ap);
1438 lexp->assignok = (flag&SH_ASSIGN)?SH_ASSIGN:1;
1439 if(assignment)
1440 {
1441 struct argnod *ap=argp;
1442 char *last, *cp;
1443 if(assignment==1)
1444 {
1445 last = strchr(argp->argval,'=');
1446 if(last && (last[-1]==']'|| (last[-1]=='+' && last[-2]==']')) && (cp=strchr(argp->argval,'[')) && (cp < last) && cp[-1]!='.')
1447 last = cp;
1448 stkseek(stkp,ARGVAL);
1449 sfwrite(stkp,argp->argval,last-argp->argval);
1450 ap=(struct argnod*)stkfreeze(stkp,1);
1451 ap->argflag = ARG_RAW;
1452 ap->argchn.ap = 0;
1453 }
1454 *argtail = ap;
1455 argtail = &(ap->argnxt.ap);
1456 if(argno>=0)
1457 argno++;
1458 }
1459 else /* alias substitutions allowed */
1460 lexp->aliasok = 1;
1461 }
1462 else
1463 {
1464 if(!(argp->argflag&ARG_RAW))
1465 argno = -1;
1466 if(argno>=0 && argno++==cmdarg && !(flag&SH_ARRAY) && *argp->argval!='/')
1467 {
1468 /* check for builtin command */
1469 Namval_t *np=nv_bfsearch(argp->argval,lexp->sh->fun_tree, (Namval_t**)&t->comnamq,(char**)0);
1470 if(cmdarg==0)
1471 t->comnamp = (void*)np;
1472 if(np && is_abuiltin(np))
1473 {
1474 if(nv_isattr(np,BLT_DCL))
1475 {
1476 assignment = 1+(*argp->argval=='a');
1477 if(np==SYSTYPESET)
1478 lexp->intypeset = 1;
1479 key_on = 1;
1480 }
1481 else if(np==SYSCOMMAND)
1482 cmdarg++;
1483 else if(np==SYSEXEC)
1484 lexp->inexec = 1;
1485 else if(np->nvalue.bfp==(Nambfp_f)b_getopts)
1486 opt_get |= FOPTGET;
1487 }
1488 }
1489 if((flag&NV_COMVAR) && !assignment)
1490 sh_syntax(lexp);
1491 *argtail = argp;
1492 argtail = &(argp->argnxt.ap);
1493 if(!(lexp->assignok=key_on) && !(flag&SH_NOIO) && sh_isoption(SH_NOEXEC))
1494 lexp->assignok = SH_COMPASSIGN;
1495 lexp->aliasok = 0;
1496 }
1497 retry:
1498 tok = sh_lex(lexp);
1499 if(tok==LABLSYM && (flag&SH_ASSIGN))
1500 lexp->token = tok = 0;
1501 if((tok==IPROCSYM || tok==OPROCSYM))
1502 {
1503 argp = process_sub(lexp,tok);
1504 argno = -1;
1505 *argtail = argp;
1506 argtail = &(argp->argnxt.ap);
1507 goto retry;
1508 }
1509 if(tok==LPAREN)
1510 {
1511 if(argp->argflag&ARG_ASSIGN)
1512 {
1513 int intypeset = lexp->intypeset;
1514 int type = 0;
1515 lexp->intypeset = 0;
1516 if(t->comnamp==SYSTYPESET)
1517 {
1518 struct argnod *ap;
1519 for(ap=t->comarg->argnxt.ap;ap;ap=ap->argnxt.ap)
1520 {
1521 if(*ap->argval!='-')
1522 break;
1523 if(strchr(ap->argval,'T'))
1524 type = NV_TYPE;
1525 else if(strchr(ap->argval,'a'))
1526 type = NV_ARRAY;
1527 else if(strchr(ap->argval,'C'))
1528 type = NV_COMVAR;
1529 else
1530 continue;
1531 break;
1532 }
1533 }
1534 argp = assign(lexp,argp,type);
1535 lexp->intypeset = intypeset;
1536 if(associative)
1537 lexp->assignok |= SH_ASSIGN;
1538 goto retry;
1539 }
1540 else if(argno==1 && !t->comset)
1541 {
1542 /* SVR2 style function */
1543 if(!(flag&SH_ARRAY) && sh_lex(lexp) == RPAREN)
1544 {
1545 lexp->arg = argp;
1546 return(funct(lexp));
1547 }
1548 lexp->token = LPAREN;
1549 }
1550 }
1551 else if(flag&SH_ASSIGN)
1552 {
1553 if(tok==RPAREN)
1554 break;
1555 else if(tok==NL && (flag&SH_ARRAY))
1556 {
1557 lexp->comp_assign = 2;
1558 goto retry;
1559 }
1560
1561 }
1562 if(!(flag&SH_NOIO))
1563 {
1564 if(io)
1565 {
1566 while(io->ionxt)
1567 io = io->ionxt;
1568 io->ionxt = inout(lexp,(struct ionod*)0,0);
1569 }
1570 else
1571 t->comio = io = inout(lexp,(struct ionod*)0,0);
1572 }
1573 }
1574 *argtail = 0;
1575 t->comtyp = TCOM;
1576 #if SHOPT_KIA
1577 if(lexp->kiafile && !(flag&SH_NOIO))
1578 {
1579 register Namval_t *np=(Namval_t*)t->comnamp;
1580 unsigned long r=0;
1581 int line = t->comline;
1582 argp = t->comarg;
1583 if(np)
1584 r = kiaentity(lexp,nv_name(np),-1,'p',-1,0,lexp->unknown,'b',0,"");
1585 else if(argp)
1586 r = kiaentity(lexp,sh_argstr(argp),-1,'p',-1,0,lexp->unknown,'c',0,"");
1587 if(r>0)
1588 sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;c;\n",lexp->current,r,line,line);
1589 if(t->comset && argno==0)
1590 writedefs(lexp,t->comset,line,'v',t->comarg);
1591 else if(np && nv_isattr(np,BLT_DCL))
1592 writedefs(lexp,argp,line,0,NIL(struct argnod*));
1593 else if(argp && strcmp(argp->argval,"read")==0)
1594 writedefs(lexp,argp,line,0,NIL(struct argnod*));
1595 #if 0
1596 else if(argp && strcmp(argp->argval,"unset")==0)
1597 writedefs(lexp,argp,line,'u',NIL(struct argnod*));
1598 #endif
1599 else if(argp && *argp->argval=='.' && argp->argval[1]==0 && (argp=argp->argnxt.ap))
1600 {
1601 r = kiaentity(lexp,sh_argstr(argp),-1,'p',0,0,lexp->script,'d',0,"");
1602 sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;d;\n",lexp->current,r,line,line);
1603 }
1604 }
1605 #endif /* SHOPT_KIA */
1606 if(t->comnamp && (argp=t->comarg->argnxt.ap))
1607 {
1608 Namval_t *np=(Namval_t*)t->comnamp;
1609 if((np==SYSBREAK || np==SYSCONT) && (argp->argflag&ARG_RAW) && !isdigit(*argp->argval))
1610 {
1611 register char *cp = argp->argval;
1612 /* convert break/continue labels to numbers */
1613 tok = 0;
1614 for(argp=label_list;argp!=label_last;argp=argp->argnxt.ap)
1615 {
1616 if(strcmp(cp,argp->argval))
1617 continue;
1618 tok = loop_level-argp->argflag;
1619 if(tok>=1)
1620 {
1621 argp = t->comarg->argnxt.ap;
1622 if(tok>9)
1623 {
1624 argp->argval[1] = '0'+tok%10;
1625 argp->argval[2] = 0;
1626 tok /= 10;
1627 }
1628 else
1629 argp->argval[1] = 0;
1630 *argp->argval = '0'+tok;
1631 }
1632 break;
1633 }
1634 if(sh_isoption(SH_NOEXEC) && tok==0)
1635 errormsg(SH_DICT,ERROR_warn(0),e_lexlabunknown,lexp->sh->inlineno-(lexp->token=='\n'),cp);
1636 }
1637 else if(sh_isoption(SH_NOEXEC) && np==SYSSET && ((tok= *argp->argval)=='-'||tok=='+') &&
1638 (argp->argval[1]==0||strchr(argp->argval,'k')))
1639 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,lexp->sh->inlineno-(lexp->token=='\n'),argp->argval);
1640 }
1641 /* expand argument list if possible */
1642 if(argno>0 && !(flag&(SH_ARRAY|NV_APPEND)))
1643 t->comarg = qscan(t,argno);
1644 else if(t->comarg)
1645 t->comtyp |= COMSCAN;
1646 lexp->aliasok = 0;
1647 return((Shnode_t*)t);
1648 }
1649
1650 /*
1651 * skip past newlines but issue prompt if interactive
1652 */
skipnl(Lex_t * lexp,int flag)1653 static int skipnl(Lex_t *lexp,int flag)
1654 {
1655 register int token;
1656 while((token=sh_lex(lexp))==NL);
1657 if(token==';' && !(flag&SH_SEMI))
1658 sh_syntax(lexp);
1659 return(token);
1660 }
1661
1662 /*
1663 * check for and process and i/o redirections
1664 * if flag>0 then an alias can be in the next word
1665 * if flag<0 only one redirection will be processed
1666 */
inout(Lex_t * lexp,struct ionod * lastio,int flag)1667 static struct ionod *inout(Lex_t *lexp,struct ionod *lastio,int flag)
1668 {
1669 register int iof = lexp->digits, token=lexp->token;
1670 register struct ionod *iop;
1671 Stk_t *stkp = lexp->sh->stk;
1672 char *iovname=0;
1673 register int errout=0;
1674 if(token==IOVNAME)
1675 {
1676 iovname=lexp->arg->argval+1;
1677 token= sh_lex(lexp);
1678 iof = 0;
1679 }
1680 switch(token&0xff)
1681 {
1682 case '<':
1683 if(token==IODOCSYM)
1684 iof |= (IODOC|IORAW);
1685 else if(token==IOMOV0SYM)
1686 iof |= IOMOV;
1687 else if(token==IORDWRSYMT)
1688 iof |= IORDW|IOREWRITE;
1689 else if(token==IORDWRSYM)
1690 iof |= IORDW;
1691 else if((token&SYMSHARP) == SYMSHARP)
1692 {
1693 int n;
1694 iof |= IOLSEEK;
1695 if(fcgetc(n)=='#')
1696 iof |= IOCOPY;
1697 else if(n>0)
1698 fcseek(-1);
1699 }
1700 break;
1701
1702 case '>':
1703 if(iof<0)
1704 {
1705 errout = 1;
1706 iof = 1;
1707 }
1708 iof |= IOPUT;
1709 if(token==IOAPPSYM)
1710 iof |= IOAPP;
1711 else if(token==IOMOV1SYM)
1712 iof |= IOMOV;
1713 else if(token==IOCLOBSYM)
1714 iof |= IOCLOB;
1715 else if((token&SYMSHARP) == SYMSHARP)
1716 iof |= IOLSEEK;
1717 else if((token&SYMSEMI) == SYMSEMI)
1718 iof |= IOREWRITE;
1719 break;
1720
1721 default:
1722 return(lastio);
1723 }
1724 lexp->digits=0;
1725 iop=(struct ionod*) stkalloc(stkp,sizeof(struct ionod));
1726 iop->iodelim = 0;
1727 if(token=sh_lex(lexp))
1728 {
1729 if(token==RPAREN && (iof&IOLSEEK) && lexp->comsub)
1730 {
1731 lexp->arg = (struct argnod*)stkalloc(stkp,sizeof(struct argnod)+3);
1732 strcpy(lexp->arg->argval,"CUR");
1733 lexp->arg->argflag = ARG_RAW;
1734 iof |= IOARITH;
1735 fcseek(-1);
1736 }
1737 else if(token==EXPRSYM && (iof&IOLSEEK))
1738 iof |= IOARITH;
1739 else if(((token==IPROCSYM && !(iof&IOPUT)) || (token==OPROCSYM && (iof&IOPUT))) && !(iof&(IOLSEEK|IOREWRITE|IOMOV|IODOC)))
1740 {
1741 lexp->arg = process_sub(lexp,token);
1742 iof |= IOPROCSUB;
1743 }
1744 else
1745 sh_syntax(lexp);
1746 }
1747 if( (iof&IOPROCSUB) && !(iof&IOLSEEK))
1748 iop->ioname= (char*)lexp->arg->argchn.ap;
1749 else
1750 iop->ioname=lexp->arg->argval;
1751 iop->iovname = iovname;
1752 if(iof&IODOC)
1753 {
1754 if(lexp->digits==2)
1755 {
1756 iof |= IOSTRG;
1757 if(!(lexp->arg->argflag&ARG_RAW))
1758 iof &= ~IORAW;
1759 }
1760 else
1761 {
1762 if(!lexp->sh->heredocs)
1763 lexp->sh->heredocs = sftmp(HERE_MEM);
1764 iop->iolst=lexp->heredoc;
1765 lexp->heredoc=iop;
1766 if(lexp->arg->argflag&ARG_QUOTED)
1767 iof |= IOQUOTE;
1768 if(lexp->digits==3)
1769 iof |= IOLSEEK;
1770 if(lexp->digits)
1771 iof |= IOSTRIP;
1772 }
1773 }
1774 else
1775 {
1776 iop->iolst = 0;
1777 if(lexp->arg->argflag&ARG_RAW)
1778 iof |= IORAW;
1779 }
1780 iop->iofile=iof;
1781 if(flag>0)
1782 /* allow alias substitutions and parameter assignments */
1783 lexp->aliasok = lexp->assignok = 1;
1784 #if SHOPT_KIA
1785 if(lexp->kiafile)
1786 {
1787 int n = lexp->sh->inlineno-(lexp->token=='\n');
1788 if(!(iof&IOMOV))
1789 {
1790 unsigned long r=kiaentity(lexp,(iof&IORAW)?sh_fmtq(iop->ioname):iop->ioname,-1,'f',0,0,lexp->script,'f',0,"");
1791 sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;%c;%d\n",lexp->current,r,n,n,(iof&IOPUT)?((iof&IOAPP)?'a':'w'):((iof&IODOC)?'h':'r'),iof&IOUFD);
1792 }
1793 }
1794 #endif /* SHOPT_KIA */
1795 if(flag>=0)
1796 {
1797 struct ionod *ioq=iop;
1798 sh_lex(lexp);
1799 if(errout)
1800 {
1801 /* redirect standard output to standard error */
1802 ioq = (struct ionod*)stkalloc(stkp,sizeof(struct ionod));
1803 memset(ioq,0,sizeof(*ioq));
1804 ioq->ioname = "1";
1805 ioq->iolst = 0;
1806 ioq->iodelim = 0;
1807 ioq->iofile = IORAW|IOPUT|IOMOV|2;
1808 iop->ionxt=ioq;
1809 }
1810 ioq->ionxt=inout(lexp,lastio,flag);
1811 }
1812 else
1813 iop->ionxt=0;
1814 return(iop);
1815 }
1816
1817 /*
1818 * convert argument chain to argument list when no special arguments
1819 */
1820
qscan(struct comnod * ac,int argn)1821 static struct argnod *qscan(struct comnod *ac,int argn)
1822 {
1823 register char **cp;
1824 register struct argnod *ap;
1825 register struct dolnod* dp;
1826 register int special=0;
1827 /* special hack for test -t compatibility */
1828 if((Namval_t*)ac->comnamp==SYSTEST)
1829 special = 2;
1830 else if(*(ac->comarg->argval)=='[' && ac->comarg->argval[1]==0)
1831 special = 3;
1832 if(special)
1833 {
1834 ap = ac->comarg->argnxt.ap;
1835 if(argn==(special+1) && ap->argval[1]==0 && *ap->argval=='!')
1836 ap = ap->argnxt.ap;
1837 else if(argn!=special)
1838 special=0;
1839 }
1840 if(special)
1841 {
1842 const char *message;
1843 if(strcmp(ap->argval,"-t"))
1844 {
1845 message = "line %d: Invariant test";
1846 special=0;
1847 }
1848 else
1849 {
1850 message = "line %d: -t requires argument";
1851 argn++;
1852 }
1853 if(sh_isoption(SH_NOEXEC))
1854 errormsg(SH_DICT,ERROR_warn(0),message,ac->comline);
1855 }
1856 /* leave space for an extra argument at the front */
1857 dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
1858 cp = dp->dolval+ARG_SPARE;
1859 dp->dolnum = argn;
1860 dp->dolbot = ARG_SPARE;
1861 ap = ac->comarg;
1862 while(ap)
1863 {
1864 *cp++ = ap->argval;
1865 ap = ap->argnxt.ap;
1866 }
1867 if(special==3)
1868 {
1869 cp[0] = cp[-1];
1870 cp[-1] = "1";
1871 cp++;
1872 }
1873 else if(special)
1874 *cp++ = "1";
1875 *cp = 0;
1876 return((struct argnod*)dp);
1877 }
1878
test_expr(Lex_t * lp,int sym)1879 static Shnode_t *test_expr(Lex_t *lp,int sym)
1880 {
1881 register Shnode_t *t = test_or(lp);
1882 if(lp->token!=sym)
1883 sh_syntax(lp);
1884 return(t);
1885 }
1886
test_or(Lex_t * lp)1887 static Shnode_t *test_or(Lex_t *lp)
1888 {
1889 register Shnode_t *t = test_and(lp);
1890 while(lp->token==ORFSYM)
1891 t = makelist(lp,TORF|TTEST,t,test_and(lp));
1892 return(t);
1893 }
1894
test_and(Lex_t * lp)1895 static Shnode_t *test_and(Lex_t *lp)
1896 {
1897 register Shnode_t *t = test_primary(lp);
1898 while(lp->token==ANDFSYM)
1899 t = makelist(lp,TAND|TTEST,t,test_primary(lp));
1900 return(t);
1901 }
1902
1903 /*
1904 * convert =~ into == ~(E)
1905 */
ere_match(void)1906 static void ere_match(void)
1907 {
1908 Sfio_t *base, *iop = sfopen((Sfio_t*)0," ~(E)","s");
1909 register int c;
1910 while( fcgetc(c),(c==' ' || c=='\t'));
1911 if(c)
1912 fcseek(-1);
1913 if(!(base=fcfile()))
1914 base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
1915 fcclose();
1916 sfstack(base,iop);
1917 fcfopen(base);
1918 }
1919
test_primary(Lex_t * lexp)1920 static Shnode_t *test_primary(Lex_t *lexp)
1921 {
1922 register struct argnod *arg;
1923 register Shnode_t *t;
1924 register int num,token;
1925 token = skipnl(lexp,0);
1926 num = lexp->digits;
1927 switch(token)
1928 {
1929 case '(':
1930 t = test_expr(lexp,')');
1931 t = makelist(lexp,TTST|TTEST|TPAREN ,t, (Shnode_t*)pointerof(lexp->sh->inlineno));
1932 break;
1933 case '!':
1934 if(!(t = test_primary(lexp)))
1935 sh_syntax(lexp);
1936 t->tre.tretyp |= TNEGATE;
1937 return(t);
1938 case TESTUNOP:
1939 if(sh_lex(lexp))
1940 sh_syntax(lexp);
1941 #if SHOPT_KIA
1942 if(lexp->kiafile && !strchr("sntzoOG",num))
1943 {
1944 int line = lexp->sh->inlineno- (lexp->token==NL);
1945 unsigned long r;
1946 r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->script,'t',0,"");
1947 sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
1948 }
1949 #endif /* SHOPT_KIA */
1950 t = makelist(lexp,TTST|TTEST|TUNARY|(num<<TSHIFT),
1951 (Shnode_t*)lexp->arg,(Shnode_t*)lexp->arg);
1952 t->tst.tstline = lexp->sh->inlineno;
1953 break;
1954 /* binary test operators */
1955 case 0:
1956 arg = lexp->arg;
1957 if((token=sh_lex(lexp))==TESTBINOP)
1958 {
1959 num = lexp->digits;
1960 if(num==TEST_REP)
1961 {
1962 ere_match();
1963 num = TEST_PEQ;
1964 }
1965 }
1966 else if(token=='<')
1967 num = TEST_SLT;
1968 else if(token=='>')
1969 num = TEST_SGT;
1970 else if(token==ANDFSYM||token==ORFSYM||token==ETESTSYM||token==RPAREN)
1971 {
1972 t = makelist(lexp,TTST|TTEST|TUNARY|('n'<<TSHIFT),
1973 (Shnode_t*)arg,(Shnode_t*)arg);
1974 t->tst.tstline = lexp->sh->inlineno;
1975 return(t);
1976 }
1977 else
1978 sh_syntax(lexp);
1979 #if SHOPT_KIA
1980 if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
1981 {
1982 int line = lexp->sh->inlineno- (lexp->token==NL);
1983 unsigned long r;
1984 r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
1985 sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
1986 }
1987 #endif /* SHOPT_KIA */
1988 if(sh_lex(lexp))
1989 sh_syntax(lexp);
1990 if(num&TEST_PATTERN)
1991 {
1992 if(lexp->arg->argflag&(ARG_EXP|ARG_MAC))
1993 num &= ~TEST_PATTERN;
1994 }
1995 t = getnode(tstnod);
1996 t->lst.lsttyp = TTST|TTEST|TBINARY|(num<<TSHIFT);
1997 t->lst.lstlef = (Shnode_t*)arg;
1998 t->lst.lstrit = (Shnode_t*)lexp->arg;
1999 t->tst.tstline = lexp->sh->inlineno;
2000 #if SHOPT_KIA
2001 if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
2002 {
2003 int line = lexp->sh->inlineno-(lexp->token==NL);
2004 unsigned long r;
2005 r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
2006 sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
2007 }
2008 #endif /* SHOPT_KIA */
2009 break;
2010 default:
2011 return(0);
2012 }
2013 skipnl(lexp,0);
2014 return(t);
2015 }
2016
2017 #if SHOPT_KIA
2018 /*
2019 * return an entity checksum
2020 * The entity is created if it doesn't exist
2021 */
kiaentity(Lex_t * lexp,const char * name,int len,int type,int first,int last,unsigned long parent,int pkind,int width,const char * attr)2022 unsigned long kiaentity(Lex_t *lexp,const char *name,int len,int type,int first,int last,unsigned long parent, int pkind, int width, const char *attr)
2023 {
2024 Stk_t *stkp = lexp->sh->stk;
2025 Namval_t *np;
2026 long offset = stktell(stkp);
2027 sfputc(stkp,type);
2028 if(len>0)
2029 sfwrite(stkp,name,len);
2030 else
2031 {
2032 if(type=='p')
2033 sfputr(stkp,path_basename(name),0);
2034 else
2035 sfputr(stkp,name,0);
2036 }
2037 np = nv_search(stakptr(offset),lexp->entity_tree,NV_ADD);
2038 stkseek(stkp,offset);
2039 np->nvalue.i = pkind;
2040 nv_setsize(np,width);
2041 if(!nv_isattr(np,NV_TAGGED) && first>=0)
2042 {
2043 nv_onattr(np,NV_TAGGED);
2044 if(!pkind)
2045 pkind = '0';
2046 if(len>0)
2047 sfprintf(lexp->kiafile,"%..64d;%c;%.*s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,len,name,first,last,parent,lexp->fscript,pkind,width,attr);
2048 else
2049 sfprintf(lexp->kiafile,"%..64d;%c;%s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,name,first,last,parent,lexp->fscript,pkind,width,attr);
2050 }
2051 return(np->hash);
2052 }
2053
kia_add(register Namval_t * np,void * data)2054 static void kia_add(register Namval_t *np, void *data)
2055 {
2056 char *name = nv_name(np);
2057 Lex_t *lp = (Lex_t*)data;
2058 NOT_USED(data);
2059 kiaentity(lp,name+1,-1,*name,0,-1,(*name=='p'?lp->unknown:lp->script),np->nvalue.i,nv_size(np),"");
2060 }
2061
kiaclose(Lex_t * lexp)2062 int kiaclose(Lex_t *lexp)
2063 {
2064 register off_t off1,off2;
2065 register int n;
2066 if(lexp->kiafile)
2067 {
2068 unsigned long r = kiaentity(lexp,lexp->scriptname,-1,'p',-1,lexp->sh->inlineno-1,0,'s',0,"");
2069 kiaentity(lexp,lexp->scriptname,-1,'p',1,lexp->sh->inlineno-1,r,'s',0,"");
2070 kiaentity(lexp,lexp->scriptname,-1,'f',1,lexp->sh->inlineno-1,r,'s',0,"");
2071 nv_scan(lexp->entity_tree,kia_add,(void*)lexp,NV_TAGGED,0);
2072 off1 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
2073 sfseek(lexp->kiatmp,(off_t)0,SEEK_SET);
2074 sfmove(lexp->kiatmp,lexp->kiafile,SF_UNBOUND,-1);
2075 off2 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
2076 #ifdef SF_BUFCONST
2077 if(off2==off1)
2078 n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin));
2079 else
2080 n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nRELATIONSHIP;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin),(Sflong_t)off1,(size_t)(off2-off1));
2081 if(off2 >= INT_MAX)
2082 off2 = -(n+12);
2083 sfprintf(lexp->kiafile,"%010.10lld;%010d\n",(Sflong_t)off2+10, n+12);
2084 #else
2085 if(off2==off1)
2086 n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin);
2087 else
2088 n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nRELATIONSHIP;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin,off1,off2-off1);
2089 sfprintf(lexp->kiafile,"%010d;%010d\n",off2+10, n+12);
2090 #endif
2091 }
2092 return(sfclose(lexp->kiafile));
2093 }
2094 #endif /* SHOPT_KIA */
2095