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