1 /*
2 * parse.c - parser
3 *
4 * This file is part of zsh, the Z shell.
5 *
6 * Copyright (c) 1992-1997 Paul Falstad
7 * All rights reserved.
8 *
9 * Permission is hereby granted, without written agreement and without
10 * license or royalty fees, to use, copy, modify, and distribute this
11 * software and to distribute modified versions of this software for any
12 * purpose, provided that the above copyright notice and the following
13 * two paragraphs appear in all copies of this software.
14 *
15 * In no event shall Paul Falstad or the Zsh Development Group be liable
16 * to any party for direct, indirect, special, incidental, or consequential
17 * damages arising out of the use of this software and its documentation,
18 * even if Paul Falstad and the Zsh Development Group have been advised of
19 * the possibility of such damage.
20 *
21 * Paul Falstad and the Zsh Development Group specifically disclaim any
22 * warranties, including, but not limited to, the implied warranties of
23 * merchantability and fitness for a particular purpose. The software
24 * provided hereunder is on an "as is" basis, and Paul Falstad and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
27 *
28 */
29
30 #include "zsh.mdh"
31 #include "parse.pro"
32
33 /* != 0 if we are about to read a command word */
34
35 /**/
36 mod_export int incmdpos;
37
38 /**/
39 int aliasspaceflag;
40
41 /* != 0 if we are in the middle of a [[ ... ]] */
42
43 /**/
44 mod_export int incond;
45
46 /* != 0 if we are after a redirection (for ctxtlex only) */
47
48 /**/
49 mod_export int inredir;
50
51 /*
52 * 1 if we are about to read a case pattern
53 * -1 if we are not quite sure
54 * 0 otherwise
55 */
56
57 /**/
58 int incasepat;
59
60 /* != 0 if we just read a newline */
61
62 /**/
63 int isnewlin;
64
65 /* != 0 if we are after a for keyword */
66
67 /**/
68 int infor;
69
70 /* != 0 if we are after a repeat keyword; if it's nonzero it's a 1-based index
71 * of the current token from the last-seen command position */
72
73 /**/
74 int inrepeat_; /* trailing underscore because of name clash with Zle/zle_vi.c */
75
76 /* != 0 if parsing arguments of typeset etc. */
77
78 /**/
79 mod_export int intypeset;
80
81 /* list of here-documents */
82
83 /**/
84 struct heredocs *hdocs;
85
86
87 #define YYERROR(O) { tok = LEXERR; ecused = (O); return 0; }
88 #define YYERRORV(O) { tok = LEXERR; ecused = (O); return; }
89 #define COND_ERROR(X,Y) \
90 do { \
91 zwarn(X,Y); \
92 herrflush(); \
93 if (noerrs != 2) \
94 errflag |= ERRFLAG_ERROR; \
95 YYERROR(ecused) \
96 } while(0)
97
98
99 /*
100 * Word code.
101 *
102 * The parser now produces word code, reducing memory consumption compared
103 * to the nested structs we had before.
104 *
105 * Word code layout:
106 *
107 * WC_END
108 * - end of program code
109 *
110 * WC_LIST
111 * - data contains type (sync, ...)
112 * - followed by code for this list
113 * - if not (type & Z_END), followed by next WC_LIST
114 *
115 * WC_SUBLIST
116 * - data contains type (&&, ||, END) and flags (coprog, not)
117 * - followed by code for sublist
118 * - if not (type == END), followed by next WC_SUBLIST
119 *
120 * WC_PIPE
121 * - data contains type (end, mid) and LINENO
122 * - if not (type == END), followed by offset to next WC_PIPE
123 * - followed by command
124 * - if not (type == END), followed by next WC_PIPE
125 *
126 * WC_REDIR
127 * - must precede command-code (or WC_ASSIGN)
128 * - data contains type (<, >, ...)
129 * - followed by fd1 and name from struct redir
130 * - for the extended form {var}>... where the fd is assigned
131 * to var, there is an extra item to contain var
132 *
133 * WC_ASSIGN
134 * - data contains type (scalar, array) and number of array-elements
135 * - followed by name and value
136 * Note variant for WC_TYPESET assignments: WC_ASSIGN_INC indicates
137 * a name with no equals, not an =+ which isn't valid here.
138 *
139 * WC_SIMPLE
140 * - data contains the number of arguments (plus command)
141 * - followed by strings
142 *
143 * WC_TYPESET
144 * Variant of WC_SIMPLE used when TYPESET reserved word found.
145 * - data contains the number of string arguments (plus command)
146 * - followed by strings
147 * - followed by number of assignments
148 * - followed by assignments if non-zero number.
149 *
150 * WC_SUBSH
151 * - data unused
152 * - followed by list
153 *
154 * WC_CURSH
155 * - data unused
156 * - followed by list
157 *
158 * WC_TIMED
159 * - data contains type (followed by pipe or not)
160 * - if (type == PIPE), followed by pipe
161 *
162 * WC_FUNCDEF
163 * - data contains offset to after body
164 * - followed by number of names
165 * - followed by names
166 * - followed by offset to first string
167 * - followed by length of string table
168 * - followed by number of patterns for body
169 * - followed by codes for body
170 * - followed by strings for body
171 *
172 * WC_FOR
173 * - data contains type (list, ...) and offset to after body
174 * - if (type == COND), followed by init, cond, advance expressions
175 * - else if (type == PPARAM), followed by param name
176 * - else if (type == LIST), followed by param name, num strings, strings
177 * - followed by body
178 *
179 * WC_SELECT
180 * - data contains type (list, ...) and offset to after body
181 * - if (type == PPARAM), followed by param name
182 * - else if (type == LIST), followed by param name, num strings, strings
183 * - followed by body
184 *
185 * WC_WHILE
186 * - data contains type (while, until) and offset to after body
187 * - followed by condition
188 * - followed by body
189 *
190 * WC_REPEAT
191 * - data contains offset to after body
192 * - followed by number-string
193 * - followed by body
194 *
195 * WC_CASE
196 * - first CASE is always of type HEAD, data contains offset to esac
197 * - after that CASEs of type OR (;;), AND (;&) and TESTAND (;|),
198 * data is offset to next case
199 * - each OR/AND/TESTAND case is followed by pattern, pattern-number, list
200 *
201 * WC_IF
202 * - first IF is of type HEAD, data contains offset to fi
203 * - after that IFs of type IF, ELIF, ELSE, data is offset to next
204 * - each non-HEAD is followed by condition (only IF, ELIF) and body
205 *
206 * WC_COND
207 * - data contains type
208 * - if (type == AND/OR), data contains offset to after this one,
209 * followed by two CONDs
210 * - else if (type == NOT), followed by COND
211 * - else if (type == MOD), followed by name and strings
212 * - else if (type == MODI), followed by name, left, right
213 * - else if (type == STR[N]EQ), followed by left, right, pattern-number
214 * - else if (has two args) followed by left, right
215 * - else followed by string
216 *
217 * WC_ARITH
218 * - followed by string (there's only one)
219 *
220 * WC_AUTOFN
221 * - only used by the autoload builtin
222 *
223 * Lists and sublists may also be simplified, indicated by the presence
224 * of the Z_SIMPLE or WC_SUBLIST_SIMPLE flags. In this case they are only
225 * followed by a slot containing the line number, not by a WC_SUBLIST or
226 * WC_PIPE, respectively. The real advantage of simplified lists and
227 * sublists is that they can be executed faster, see exec.c. In the
228 * parser, the test if a list can be simplified is done quite simply
229 * by passing a int* around which gets set to non-zero if the thing
230 * just parsed is `cmplx', i.e. may need to be run by forking or
231 * some such.
232 *
233 * In each of the above, strings are encoded as one word code. For empty
234 * strings this is the bit pattern 11x, the lowest bit is non-zero if the
235 * string contains tokens and zero otherwise (this is true for the other
236 * ways to encode strings, too). For short strings (one to three
237 * characters), this is the marker 01x with the 24 bits above that
238 * containing the characters. Longer strings are encoded as the offset
239 * into the strs character array stored in the eprog struct shifted by
240 * two and ored with the bit pattern 0x.
241 * The ecstrcode() function that adds the code for a string uses a simple
242 * binary tree of strings already added so that long strings are encoded
243 * only once.
244 *
245 * Note also that in the eprog struct the pattern, code, and string
246 * arrays all point to the same memory block.
247 *
248 *
249 * To make things even faster in future versions, we could not only
250 * test if the strings contain tokens, but instead what kind of
251 * expansions need to be done on strings. In the execution code we
252 * could then use these flags for a specialized version of prefork()
253 * to avoid a lot of string parsing and some more string duplication.
254 */
255
256 /**/
257 int eclen, ecused, ecnpats;
258 /**/
259 Wordcode ecbuf;
260 /**/
261 Eccstr ecstrs;
262 /**/
263 int ecsoffs, ecssub, ecnfunc;
264
265 #define EC_INIT_SIZE 256
266 #define EC_DOUBLE_THRESHOLD 32768
267 #define EC_INCREMENT 1024
268
269 /* save parse context */
270
271 /**/
272 void
parse_context_save(struct parse_stack * ps,int toplevel)273 parse_context_save(struct parse_stack *ps, int toplevel)
274 {
275 (void)toplevel;
276
277 ps->incmdpos = incmdpos;
278 ps->aliasspaceflag = aliasspaceflag;
279 ps->incond = incond;
280 ps->inredir = inredir;
281 ps->incasepat = incasepat;
282 ps->isnewlin = isnewlin;
283 ps->infor = infor;
284 ps->inrepeat_ = inrepeat_;
285 ps->intypeset = intypeset;
286
287 ps->hdocs = hdocs;
288 ps->eclen = eclen;
289 ps->ecused = ecused;
290 ps->ecnpats = ecnpats;
291 ps->ecbuf = ecbuf;
292 ps->ecstrs = ecstrs;
293 ps->ecsoffs = ecsoffs;
294 ps->ecssub = ecssub;
295 ps->ecnfunc = ecnfunc;
296 ecbuf = NULL;
297 hdocs = NULL;
298 }
299
300 /* restore parse context */
301
302 /**/
303 void
parse_context_restore(const struct parse_stack * ps,int toplevel)304 parse_context_restore(const struct parse_stack *ps, int toplevel)
305 {
306 (void)toplevel;
307
308 if (ecbuf)
309 zfree(ecbuf, eclen);
310
311 incmdpos = ps->incmdpos;
312 aliasspaceflag = ps->aliasspaceflag;
313 incond = ps->incond;
314 inredir = ps->inredir;
315 incasepat = ps->incasepat;
316 isnewlin = ps->isnewlin;
317 infor = ps->infor;
318 inrepeat_ = ps->inrepeat_;
319 intypeset = ps->intypeset;
320
321 hdocs = ps->hdocs;
322 eclen = ps->eclen;
323 ecused = ps->ecused;
324 ecnpats = ps->ecnpats;
325 ecbuf = ps->ecbuf;
326 ecstrs = ps->ecstrs;
327 ecsoffs = ps->ecsoffs;
328 ecssub = ps->ecssub;
329 ecnfunc = ps->ecnfunc;
330
331 errflag &= ~ERRFLAG_ERROR;
332 }
333
334 /* Adjust pointers in here-doc structs. */
335
336 static void
ecadjusthere(int p,int d)337 ecadjusthere(int p, int d)
338 {
339 struct heredocs *h;
340
341 for (h = hdocs; h; h = h->next)
342 if (h->pc >= p)
343 h->pc += d;
344 }
345
346 /* Insert n free code-slots at position p. */
347
348 static void
ecispace(int p,int n)349 ecispace(int p, int n)
350 {
351 int m;
352
353 if ((eclen - ecused) < n) {
354 int a = (eclen < EC_DOUBLE_THRESHOLD ? eclen : EC_INCREMENT);
355
356 if (n > a) a = n;
357
358 ecbuf = (Wordcode) zrealloc((char *) ecbuf, (eclen + a) * sizeof(wordcode));
359 eclen += a;
360 }
361 if ((m = ecused - p) > 0)
362 memmove(ecbuf + p + n, ecbuf + p, m * sizeof(wordcode));
363 ecused += n;
364 ecadjusthere(p, n);
365 }
366
367 /* Add one wordcode. */
368
369 static int
ecadd(wordcode c)370 ecadd(wordcode c)
371 {
372 if ((eclen - ecused) < 1) {
373 int a = (eclen < EC_DOUBLE_THRESHOLD ? eclen : EC_INCREMENT);
374
375 ecbuf = (Wordcode) zrealloc((char *) ecbuf, (eclen + a) * sizeof(wordcode));
376 eclen += a;
377 }
378 ecbuf[ecused] = c;
379
380 return ecused++;
381 }
382
383 /* Delete a wordcode. */
384
385 static void
ecdel(int p)386 ecdel(int p)
387 {
388 int n = ecused - p - 1;
389
390 if (n > 0)
391 memmove(ecbuf + p, ecbuf + p + 1, n * sizeof(wordcode));
392 ecused--;
393 ecadjusthere(p, -1);
394 }
395
396 /* Build the wordcode for a string. */
397
398 static wordcode
ecstrcode(char * s)399 ecstrcode(char *s)
400 {
401 int l, t;
402
403 unsigned val = hasher(s);
404
405 if ((l = strlen(s) + 1) && l <= 4) {
406 t = has_token(s);
407 wordcode c = (t ? 3 : 2);
408 switch (l) {
409 case 4: c |= ((wordcode) STOUC(s[2])) << 19;
410 case 3: c |= ((wordcode) STOUC(s[1])) << 11;
411 case 2: c |= ((wordcode) STOUC(s[0])) << 3; break;
412 case 1: c = (t ? 7 : 6); break;
413 }
414 return c;
415 } else {
416 Eccstr p, *pp;
417 long cmp;
418
419 for (pp = &ecstrs; (p = *pp); ) {
420 if (!(cmp = p->nfunc - ecnfunc) && !(cmp = (((long)p->hashval) - ((long)val))) && !(cmp = strcmp(p->str, s))) {
421 return p->offs;
422 }
423 pp = (cmp < 0 ? &(p->left) : &(p->right));
424 }
425
426 t = has_token(s);
427
428 p = *pp = (Eccstr) zhalloc(sizeof(*p));
429 p->left = p->right = 0;
430 p->offs = ((ecsoffs - ecssub) << 2) | (t ? 1 : 0);
431 p->aoffs = ecsoffs;
432 p->str = s;
433 p->nfunc = ecnfunc;
434 p->hashval = val;
435 ecsoffs += l;
436
437 return p->offs;
438 }
439 }
440
441 #define ecstr(S) ecadd(ecstrcode(S))
442
443 #define par_save_list(C) \
444 do { \
445 int eu = ecused; \
446 par_list(C); \
447 if (eu == ecused) ecadd(WCB_END()); \
448 } while (0)
449 #define par_save_list1(C) \
450 do { \
451 int eu = ecused; \
452 par_list1(C); \
453 if (eu == ecused) ecadd(WCB_END()); \
454 } while (0)
455
456
457 /**/
458 mod_export void
init_parse_status(void)459 init_parse_status(void)
460 {
461 /*
462 * These variables are currently declared by the parser, so we
463 * initialise them here. Possibly they are more naturally declared
464 * by the lexical anaylser; however, as they are used for signalling
465 * between the two it's a bit ambiguous. We clear them when
466 * using the lexical analyser for strings as well as here.
467 */
468 incasepat = incond = inredir = infor = intypeset = 0;
469 inrepeat_ = 0;
470 incmdpos = 1;
471 }
472
473 /* Initialise wordcode buffer. */
474
475 /**/
476 void
init_parse(void)477 init_parse(void)
478 {
479 queue_signals();
480
481 if (ecbuf) zfree(ecbuf, eclen);
482
483 ecbuf = (Wordcode) zalloc((eclen = EC_INIT_SIZE) * sizeof(wordcode));
484 ecused = 0;
485 ecstrs = NULL;
486 ecsoffs = ecnpats = 0;
487 ecssub = 0;
488 ecnfunc = 0;
489
490 init_parse_status();
491
492 unqueue_signals();
493 }
494
495 /* Build eprog. */
496
497 /* careful: copy_ecstr is from arg1 to arg2, unlike memcpy */
498
499 static void
copy_ecstr(Eccstr s,char * p)500 copy_ecstr(Eccstr s, char *p)
501 {
502 while (s) {
503 memcpy(p + s->aoffs, s->str, strlen(s->str) + 1);
504 copy_ecstr(s->left, p);
505 s = s->right;
506 }
507 }
508
509 static Eprog
bld_eprog(int heap)510 bld_eprog(int heap)
511 {
512 Eprog ret;
513 int l;
514
515 queue_signals();
516
517 ecadd(WCB_END());
518
519 ret = heap ? (Eprog) zhalloc(sizeof(*ret)) : (Eprog) zalloc(sizeof(*ret));
520 ret->len = ((ecnpats * sizeof(Patprog)) +
521 (ecused * sizeof(wordcode)) +
522 ecsoffs);
523 ret->npats = ecnpats;
524 ret->nref = heap ? -1 : 1;
525 ret->pats = heap ? (Patprog *) zhalloc(ret->len) :
526 (Patprog *) zshcalloc(ret->len);
527 ret->prog = (Wordcode) (ret->pats + ecnpats);
528 ret->strs = (char *) (ret->prog + ecused);
529 ret->shf = NULL;
530 ret->flags = heap ? EF_HEAP : EF_REAL;
531 ret->dump = NULL;
532 for (l = 0; l < ecnpats; l++)
533 ret->pats[l] = dummy_patprog1;
534 memcpy(ret->prog, ecbuf, ecused * sizeof(wordcode));
535 copy_ecstr(ecstrs, ret->strs);
536
537 zfree(ecbuf, eclen);
538 ecbuf = NULL;
539
540 unqueue_signals();
541
542 return ret;
543 }
544
545 /**/
546 mod_export int
empty_eprog(Eprog p)547 empty_eprog(Eprog p)
548 {
549 return (!p || !p->prog || *p->prog == WCB_END());
550 }
551
552 static void
clear_hdocs(void)553 clear_hdocs(void)
554 {
555 struct heredocs *p, *n;
556
557 for (p = hdocs; p; p = n) {
558 n = p->next;
559 zfree(p, sizeof(struct heredocs));
560 }
561 hdocs = NULL;
562 }
563
564 /*
565 * event : ENDINPUT
566 * | SEPER
567 * | sublist [ SEPER | AMPER | AMPERBANG ]
568 *
569 * cmdsubst indicates our event is part of a command-style
570 * substitution terminated by the token indicationg, usual closing
571 * parenthesis. In other cases endtok is ENDINPUT.
572 */
573
574 /**/
575 Eprog
parse_event(int endtok)576 parse_event(int endtok)
577 {
578 tok = ENDINPUT;
579 incmdpos = 1;
580 aliasspaceflag = 0;
581 zshlex();
582 init_parse();
583
584 if (!par_event(endtok)) {
585 clear_hdocs();
586 return NULL;
587 }
588 if (endtok != ENDINPUT) {
589 /* don't need to build an eprog for this */
590 return &dummy_eprog;
591 }
592 return bld_eprog(1);
593 }
594
595 /**/
596 int
par_event(int endtok)597 par_event(int endtok)
598 {
599 int r = 0, p, c = 0;
600
601 while (tok == SEPER) {
602 if (isnewlin > 0 && endtok == ENDINPUT)
603 return 0;
604 zshlex();
605 }
606 if (tok == ENDINPUT)
607 return 0;
608 if (tok == endtok)
609 return 1;
610
611 p = ecadd(0);
612
613 if (par_sublist(&c)) {
614 if (tok == ENDINPUT || tok == endtok) {
615 set_list_code(p, Z_SYNC, c);
616 r = 1;
617 } else if (tok == SEPER) {
618 set_list_code(p, Z_SYNC, c);
619 if (isnewlin <= 0 || endtok != ENDINPUT)
620 zshlex();
621 r = 1;
622 } else if (tok == AMPER) {
623 set_list_code(p, Z_ASYNC, c);
624 zshlex();
625 r = 1;
626 } else if (tok == AMPERBANG) {
627 set_list_code(p, (Z_ASYNC | Z_DISOWN), c);
628 zshlex();
629 r = 1;
630 }
631 }
632 if (!r) {
633 tok = LEXERR;
634 if (errflag) {
635 yyerror(0);
636 ecused--;
637 return 0;
638 }
639 yyerror(1);
640 herrflush();
641 if (noerrs != 2)
642 errflag |= ERRFLAG_ERROR;
643 ecused--;
644 return 0;
645 } else {
646 int oec = ecused;
647
648 if (!par_event(endtok)) {
649 ecused = oec;
650 ecbuf[p] |= wc_bdata(Z_END);
651 return errflag ? 0 : 1;
652 }
653 }
654 return 1;
655 }
656
657 /**/
658 mod_export Eprog
parse_list(void)659 parse_list(void)
660 {
661 int c = 0;
662
663 tok = ENDINPUT;
664 init_parse();
665 zshlex();
666 par_list(&c);
667 if (tok != ENDINPUT) {
668 clear_hdocs();
669 tok = LEXERR;
670 yyerror(0);
671 return NULL;
672 }
673 return bld_eprog(1);
674 }
675
676 /*
677 * This entry point is only used for bin_test, our attempt to
678 * provide compatibility with /bin/[ and /bin/test. Hence
679 * at this point condlex should always be set to testlex.
680 */
681
682 /**/
683 mod_export Eprog
parse_cond(void)684 parse_cond(void)
685 {
686 init_parse();
687
688 if (!par_cond()) {
689 clear_hdocs();
690 return NULL;
691 }
692 return bld_eprog(1);
693 }
694
695 /* This adds a list wordcode. The important bit about this is that it also
696 * tries to optimise this to a Z_SIMPLE list code. */
697
698 /**/
699 static void
set_list_code(int p,int type,int cmplx)700 set_list_code(int p, int type, int cmplx)
701 {
702 if (!cmplx && (type == Z_SYNC || type == (Z_SYNC | Z_END)) &&
703 WC_SUBLIST_TYPE(ecbuf[p + 1]) == WC_SUBLIST_END) {
704 int ispipe = !(WC_SUBLIST_FLAGS(ecbuf[p + 1]) & WC_SUBLIST_SIMPLE);
705 ecbuf[p] = WCB_LIST((type | Z_SIMPLE), ecused - 2 - p);
706 ecdel(p + 1);
707 if (ispipe)
708 ecbuf[p + 1] = WC_PIPE_LINENO(ecbuf[p + 1]);
709 } else
710 ecbuf[p] = WCB_LIST(type, 0);
711 }
712
713 /* The same for sublists. */
714
715 /**/
716 static void
set_sublist_code(int p,int type,int flags,int skip,int cmplx)717 set_sublist_code(int p, int type, int flags, int skip, int cmplx)
718 {
719 if (cmplx)
720 ecbuf[p] = WCB_SUBLIST(type, flags, skip);
721 else {
722 ecbuf[p] = WCB_SUBLIST(type, (flags | WC_SUBLIST_SIMPLE), skip);
723 ecbuf[p + 1] = WC_PIPE_LINENO(ecbuf[p + 1]);
724 }
725 }
726
727 /*
728 * list : { SEPER } [ sublist [ { SEPER | AMPER | AMPERBANG } list ] ]
729 */
730
731 /**/
732 static void
par_list(int * cmplx)733 par_list(int *cmplx)
734 {
735 int p, lp = -1, c;
736
737 rec:
738
739 while (tok == SEPER)
740 zshlex();
741
742 p = ecadd(0);
743 c = 0;
744
745 if (par_sublist(&c)) {
746 *cmplx |= c;
747 if (tok == SEPER || tok == AMPER || tok == AMPERBANG) {
748 if (tok != SEPER)
749 *cmplx = 1;
750 set_list_code(p, ((tok == SEPER) ? Z_SYNC :
751 (tok == AMPER) ? Z_ASYNC :
752 (Z_ASYNC | Z_DISOWN)), c);
753 incmdpos = 1;
754 do {
755 zshlex();
756 } while (tok == SEPER);
757 lp = p;
758 goto rec;
759 } else
760 set_list_code(p, (Z_SYNC | Z_END), c);
761 } else {
762 ecused--;
763 if (lp >= 0)
764 ecbuf[lp] |= wc_bdata(Z_END);
765 }
766 }
767
768 /**/
769 static void
par_list1(int * cmplx)770 par_list1(int *cmplx)
771 {
772 int p = ecadd(0), c = 0;
773
774 if (par_sublist(&c)) {
775 set_list_code(p, (Z_SYNC | Z_END), c);
776 *cmplx |= c;
777 } else
778 ecused--;
779 }
780
781 /*
782 * sublist : sublist2 [ ( DBAR | DAMPER ) { SEPER } sublist ]
783 */
784
785 /**/
786 static int
par_sublist(int * cmplx)787 par_sublist(int *cmplx)
788 {
789 int f, p, c = 0;
790
791 p = ecadd(0);
792
793 if ((f = par_sublist2(&c)) != -1) {
794 int e = ecused;
795
796 *cmplx |= c;
797 if (tok == DBAR || tok == DAMPER) {
798 enum lextok qtok = tok;
799 int sl;
800
801 cmdpush(tok == DBAR ? CS_CMDOR : CS_CMDAND);
802 zshlex();
803 while (tok == SEPER)
804 zshlex();
805 sl = par_sublist(cmplx);
806 set_sublist_code(p, (sl ? (qtok == DBAR ?
807 WC_SUBLIST_OR : WC_SUBLIST_AND) :
808 WC_SUBLIST_END),
809 f, (e - 1 - p), c);
810 cmdpop();
811 } else {
812 if (tok == AMPER || tok == AMPERBANG) {
813 c = 1;
814 *cmplx |= c;
815 }
816 set_sublist_code(p, WC_SUBLIST_END, f, (e - 1 - p), c);
817 }
818 return 1;
819 } else {
820 ecused--;
821 return 0;
822 }
823 }
824
825 /*
826 * sublist2 : [ COPROC | BANG ] pline
827 */
828
829 /**/
830 static int
par_sublist2(int * cmplx)831 par_sublist2(int *cmplx)
832 {
833 int f = 0;
834
835 if (tok == COPROC) {
836 *cmplx = 1;
837 f |= WC_SUBLIST_COPROC;
838 zshlex();
839 } else if (tok == BANG) {
840 *cmplx = 1;
841 f |= WC_SUBLIST_NOT;
842 zshlex();
843 }
844 if (!par_pline(cmplx) && !f)
845 return -1;
846
847 return f;
848 }
849
850 /*
851 * pline : cmd [ ( BAR | BARAMP ) { SEPER } pline ]
852 */
853
854 /**/
855 static int
par_pline(int * cmplx)856 par_pline(int *cmplx)
857 {
858 int p;
859 zlong line = toklineno;
860
861 p = ecadd(0);
862
863 if (!par_cmd(cmplx, 0)) {
864 ecused--;
865 return 0;
866 }
867 if (tok == BAR) {
868 *cmplx = 1;
869 cmdpush(CS_PIPE);
870 zshlex();
871 while (tok == SEPER)
872 zshlex();
873 ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0));
874 ecispace(p + 1, 1);
875 ecbuf[p + 1] = ecused - 1 - p;
876 if (!par_pline(cmplx)) {
877 tok = LEXERR;
878 }
879 cmdpop();
880 return 1;
881 } else if (tok == BARAMP) {
882 int r;
883
884 for (r = p + 1; wc_code(ecbuf[r]) == WC_REDIR;
885 r += WC_REDIR_WORDS(ecbuf[r]));
886
887 ecispace(r, 3);
888 ecbuf[r] = WCB_REDIR(REDIR_MERGEOUT);
889 ecbuf[r + 1] = 2;
890 ecbuf[r + 2] = ecstrcode("1");
891
892 *cmplx = 1;
893 cmdpush(CS_ERRPIPE);
894 zshlex();
895 while (tok == SEPER)
896 zshlex();
897 ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0));
898 ecispace(p + 1, 1);
899 ecbuf[p + 1] = ecused - 1 - p;
900 if (!par_pline(cmplx)) {
901 tok = LEXERR;
902 }
903 cmdpop();
904 return 1;
905 } else {
906 ecbuf[p] = WCB_PIPE(WC_PIPE_END, (line >= 0 ? line + 1 : 0));
907 return 1;
908 }
909 }
910
911 /*
912 * cmd : { redir } ( for | case | if | while | repeat |
913 * subsh | funcdef | time | dinbrack | dinpar | simple ) { redir }
914 *
915 * zsh_construct is passed through to par_subsh(), q.v.
916 */
917
918 /**/
919 static int
par_cmd(int * cmplx,int zsh_construct)920 par_cmd(int *cmplx, int zsh_construct)
921 {
922 int r, nr = 0;
923
924 r = ecused;
925
926 if (IS_REDIROP(tok)) {
927 *cmplx = 1;
928 while (IS_REDIROP(tok)) {
929 nr += par_redir(&r, NULL);
930 }
931 }
932 switch (tok) {
933 case FOR:
934 cmdpush(CS_FOR);
935 par_for(cmplx);
936 cmdpop();
937 break;
938 case FOREACH:
939 cmdpush(CS_FOREACH);
940 par_for(cmplx);
941 cmdpop();
942 break;
943 case SELECT:
944 *cmplx = 1;
945 cmdpush(CS_SELECT);
946 par_for(cmplx);
947 cmdpop();
948 break;
949 case CASE:
950 cmdpush(CS_CASE);
951 par_case(cmplx);
952 cmdpop();
953 break;
954 case IF:
955 par_if(cmplx);
956 break;
957 case WHILE:
958 cmdpush(CS_WHILE);
959 par_while(cmplx);
960 cmdpop();
961 break;
962 case UNTIL:
963 cmdpush(CS_UNTIL);
964 par_while(cmplx);
965 cmdpop();
966 break;
967 case REPEAT:
968 cmdpush(CS_REPEAT);
969 par_repeat(cmplx);
970 cmdpop();
971 break;
972 case INPAR:
973 *cmplx = 1;
974 cmdpush(CS_SUBSH);
975 par_subsh(cmplx, zsh_construct);
976 cmdpop();
977 break;
978 case INBRACE:
979 cmdpush(CS_CURSH);
980 par_subsh(cmplx, zsh_construct);
981 cmdpop();
982 break;
983 case FUNC:
984 cmdpush(CS_FUNCDEF);
985 par_funcdef(cmplx);
986 cmdpop();
987 break;
988 case DINBRACK:
989 cmdpush(CS_COND);
990 par_dinbrack();
991 cmdpop();
992 break;
993 case DINPAR:
994 ecadd(WCB_ARITH());
995 ecstr(tokstr);
996 zshlex();
997 break;
998 case TIME:
999 {
1000 static int inpartime = 0;
1001
1002 if (!inpartime) {
1003 *cmplx = 1;
1004 inpartime = 1;
1005 par_time();
1006 inpartime = 0;
1007 break;
1008 }
1009 }
1010 tok = STRING;
1011 /* fall through */
1012 default:
1013 {
1014 int sr;
1015
1016 if (!(sr = par_simple(cmplx, nr))) {
1017 if (!nr)
1018 return 0;
1019 } else {
1020 /* Take account of redirections */
1021 if (sr > 1) {
1022 *cmplx = 1;
1023 r += sr - 1;
1024 }
1025 }
1026 }
1027 break;
1028 }
1029 if (IS_REDIROP(tok)) {
1030 *cmplx = 1;
1031 while (IS_REDIROP(tok))
1032 (void)par_redir(&r, NULL);
1033 }
1034 incmdpos = 1;
1035 incasepat = 0;
1036 incond = 0;
1037 intypeset = 0;
1038 return 1;
1039 }
1040
1041 /*
1042 * for : ( FOR DINPAR expr SEMI expr SEMI expr DOUTPAR |
1043 * ( FOR[EACH] | SELECT ) name ( "in" wordlist | INPAR wordlist OUTPAR ) )
1044 * { SEPER } ( DO list DONE | INBRACE list OUTBRACE | list ZEND | list1 )
1045 */
1046
1047 /**/
1048 static void
par_for(int * cmplx)1049 par_for(int *cmplx)
1050 {
1051 int oecused = ecused, csh = (tok == FOREACH), p, sel = (tok == SELECT);
1052 int type;
1053
1054 p = ecadd(0);
1055
1056 incmdpos = 0;
1057 infor = tok == FOR ? 2 : 0;
1058 zshlex();
1059 if (tok == DINPAR) {
1060 zshlex();
1061 if (tok != DINPAR)
1062 YYERRORV(oecused);
1063 ecstr(tokstr);
1064 zshlex();
1065 if (tok != DINPAR)
1066 YYERRORV(oecused);
1067 ecstr(tokstr);
1068 zshlex();
1069 if (tok != DOUTPAR)
1070 YYERRORV(oecused);
1071 ecstr(tokstr);
1072 infor = 0;
1073 incmdpos = 1;
1074 zshlex();
1075 type = WC_FOR_COND;
1076 } else {
1077 int np = 0, n, posix_in, ona = noaliases, onc = nocorrect;
1078 infor = 0;
1079 if (tok != STRING || !isident(tokstr))
1080 YYERRORV(oecused);
1081 if (!sel)
1082 np = ecadd(0);
1083 n = 0;
1084 incmdpos = 1;
1085 noaliases = nocorrect = 1;
1086 for (;;) {
1087 n++;
1088 ecstr(tokstr);
1089 zshlex();
1090 if (tok != STRING || !strcmp(tokstr, "in") || sel)
1091 break;
1092 if (!isident(tokstr) || errflag)
1093 {
1094 noaliases = ona;
1095 nocorrect = onc;
1096 YYERRORV(oecused);
1097 }
1098 }
1099 noaliases = ona;
1100 nocorrect = onc;
1101 if (!sel)
1102 ecbuf[np] = n;
1103 posix_in = isnewlin;
1104 while (isnewlin)
1105 zshlex();
1106 if (tok == STRING && !strcmp(tokstr, "in")) {
1107 incmdpos = 0;
1108 zshlex();
1109 np = ecadd(0);
1110 n = par_wordlist();
1111 if (tok != SEPER)
1112 YYERRORV(oecused);
1113 ecbuf[np] = n;
1114 type = (sel ? WC_SELECT_LIST : WC_FOR_LIST);
1115 } else if (!posix_in && tok == INPAR) {
1116 incmdpos = 0;
1117 zshlex();
1118 np = ecadd(0);
1119 n = par_nl_wordlist();
1120 if (tok != OUTPAR)
1121 YYERRORV(oecused);
1122 ecbuf[np] = n;
1123 incmdpos = 1;
1124 zshlex();
1125 type = (sel ? WC_SELECT_LIST : WC_FOR_LIST);
1126 } else
1127 type = (sel ? WC_SELECT_PPARAM : WC_FOR_PPARAM);
1128 }
1129 incmdpos = 1;
1130 while (tok == SEPER)
1131 zshlex();
1132 if (tok == DOLOOP) {
1133 zshlex();
1134 par_save_list(cmplx);
1135 if (tok != DONE)
1136 YYERRORV(oecused);
1137 incmdpos = 0;
1138 zshlex();
1139 } else if (tok == INBRACE) {
1140 zshlex();
1141 par_save_list(cmplx);
1142 if (tok != OUTBRACE)
1143 YYERRORV(oecused);
1144 incmdpos = 0;
1145 zshlex();
1146 } else if (csh || isset(CSHJUNKIELOOPS)) {
1147 par_save_list(cmplx);
1148 if (tok != ZEND)
1149 YYERRORV(oecused);
1150 incmdpos = 0;
1151 zshlex();
1152 } else if (unset(SHORTLOOPS)) {
1153 YYERRORV(oecused);
1154 } else
1155 par_save_list1(cmplx);
1156
1157 ecbuf[p] = (sel ?
1158 WCB_SELECT(type, ecused - 1 - p) :
1159 WCB_FOR(type, ecused - 1 - p));
1160 }
1161
1162 /*
1163 * case : CASE STRING { SEPER } ( "in" | INBRACE )
1164 { { SEPER } STRING { BAR STRING } OUTPAR
1165 list [ DSEMI | SEMIAMP | SEMIBAR ] }
1166 { SEPER } ( "esac" | OUTBRACE )
1167 */
1168
1169 /**/
1170 static void
par_case(int * cmplx)1171 par_case(int *cmplx)
1172 {
1173 int oecused = ecused, brflag, p, pp, palts, type, nalts;
1174 int ona, onc;
1175
1176 p = ecadd(0);
1177
1178 incmdpos = 0;
1179 zshlex();
1180 if (tok != STRING)
1181 YYERRORV(oecused);
1182 ecstr(tokstr);
1183
1184 incmdpos = 1;
1185 ona = noaliases;
1186 onc = nocorrect;
1187 noaliases = nocorrect = 1;
1188 zshlex();
1189 while (tok == SEPER)
1190 zshlex();
1191 if (!(tok == STRING && !strcmp(tokstr, "in")) && tok != INBRACE)
1192 {
1193 noaliases = ona;
1194 nocorrect = onc;
1195 YYERRORV(oecused);
1196 }
1197 brflag = (tok == INBRACE);
1198 incasepat = 1;
1199 incmdpos = 0;
1200 noaliases = ona;
1201 nocorrect = onc;
1202 zshlex();
1203
1204 for (;;) {
1205 char *str;
1206 int skip_zshlex;
1207
1208 while (tok == SEPER)
1209 zshlex();
1210 if (tok == OUTBRACE)
1211 break;
1212 if (tok == INPAR)
1213 zshlex();
1214 if (tok == BAR) {
1215 str = dupstring("");
1216 skip_zshlex = 1;
1217 } else {
1218 if (tok != STRING)
1219 YYERRORV(oecused);
1220 if (!strcmp(tokstr, "esac"))
1221 break;
1222 str = dupstring(tokstr);
1223 skip_zshlex = 0;
1224 }
1225 type = WC_CASE_OR;
1226 pp = ecadd(0);
1227 palts = ecadd(0);
1228 nalts = 0;
1229 /*
1230 * Hack here.
1231 *
1232 * [Pause for astonished hubbub to subside.]
1233 *
1234 * The next token we get may be
1235 * - ")" or "|" if we're looking at an honest-to-god
1236 * "case" pattern, either because there's no opening
1237 * parenthesis, or because SH_GLOB is set and we
1238 * managed to grab an initial "(" to mark the start
1239 * of the case pattern.
1240 * - Something else --- we don't care what --- because
1241 * we're parsing a complete "(...)" as a complete
1242 * zsh pattern. In that case, we treat this as a
1243 * single instance of a case pattern but we pretend
1244 * we're doing proper case parsing --- in which the
1245 * parentheses and bar are in different words from
1246 * the string, so may be separated by whitespace.
1247 * So we quietly massage the whitespace and hope
1248 * no one noticed. This is horrible, but it's
1249 * unfortunately too difficult to combine traditional
1250 * zsh patterns with a properly parsed case pattern
1251 * without generating incompatibilities which aren't
1252 * all that popular (I've discovered).
1253 * - We can also end up with something other than ")" or "|"
1254 * just because we're looking at garbage.
1255 *
1256 * Because of the second case, what happens next might
1257 * be the start of the command after the pattern, so we
1258 * need to treat it as in command position. Luckily
1259 * this doesn't affect our ability to match a | or ) as
1260 * these are valid on command lines.
1261 */
1262 incasepat = -1;
1263 incmdpos = 1;
1264 if (!skip_zshlex)
1265 zshlex();
1266 for (;;) {
1267 if (tok == OUTPAR) {
1268 ecstr(str);
1269 ecadd(ecnpats++);
1270 nalts++;
1271
1272 incasepat = 0;
1273 incmdpos = 1;
1274 zshlex();
1275 break;
1276 } else if (tok == BAR) {
1277 ecstr(str);
1278 ecadd(ecnpats++);
1279 nalts++;
1280
1281 incasepat = 1;
1282 incmdpos = 0;
1283 } else {
1284 if (!nalts && str[0] == Inpar) {
1285 int pct = 0, sl;
1286 char *s;
1287
1288 for (s = str; *s; s++) {
1289 if (*s == Inpar)
1290 pct++;
1291 if (!pct)
1292 break;
1293 if (pct == 1) {
1294 if (*s == Bar || *s == Inpar)
1295 while (iblank(s[1]))
1296 chuck(s+1);
1297 if (*s == Bar || *s == Outpar)
1298 while (iblank(s[-1]) &&
1299 (s < str + 1 || s[-2] != Meta))
1300 chuck(--s);
1301 }
1302 if (*s == Outpar)
1303 pct--;
1304 }
1305 if (*s || pct || s == str)
1306 YYERRORV(oecused);
1307 /* Simplify pattern by removing surrounding (...) */
1308 sl = strlen(str);
1309 DPUTS(*str != Inpar || str[sl - 1] != Outpar,
1310 "BUG: strange case pattern");
1311 str[sl - 1] = '\0';
1312 chuck(str);
1313 ecstr(str);
1314 ecadd(ecnpats++);
1315 nalts++;
1316 break;
1317 }
1318 YYERRORV(oecused);
1319 }
1320
1321 zshlex();
1322 switch (tok) {
1323 case STRING:
1324 /* Normal case */
1325 str = dupstring(tokstr);
1326 zshlex();
1327 break;
1328
1329 case OUTPAR:
1330 case BAR:
1331 /* Empty string */
1332 str = dupstring("");
1333 break;
1334
1335 default:
1336 /* Oops. */
1337 YYERRORV(oecused);
1338 break;
1339 }
1340 }
1341 incasepat = 0;
1342 par_save_list(cmplx);
1343 if (tok == SEMIAMP)
1344 type = WC_CASE_AND;
1345 else if (tok == SEMIBAR)
1346 type = WC_CASE_TESTAND;
1347 ecbuf[pp] = WCB_CASE(type, ecused - 1 - pp);
1348 ecbuf[palts] = nalts;
1349 if ((tok == ESAC && !brflag) || (tok == OUTBRACE && brflag))
1350 break;
1351 if (tok != DSEMI && tok != SEMIAMP && tok != SEMIBAR)
1352 YYERRORV(oecused);
1353 incasepat = 1;
1354 incmdpos = 0;
1355 zshlex();
1356 }
1357 incmdpos = 1;
1358 incasepat = 0;
1359 zshlex();
1360
1361 ecbuf[p] = WCB_CASE(WC_CASE_HEAD, ecused - 1 - p);
1362 }
1363
1364 /*
1365 * if : { ( IF | ELIF ) { SEPER } ( INPAR list OUTPAR | list )
1366 { SEPER } ( THEN list | INBRACE list OUTBRACE | list1 ) }
1367 [ FI | ELSE list FI | ELSE { SEPER } INBRACE list OUTBRACE ]
1368 (you get the idea...?)
1369 */
1370
1371 /**/
1372 static void
par_if(int * cmplx)1373 par_if(int *cmplx)
1374 {
1375 int oecused = ecused, p, pp, type, usebrace = 0;
1376 enum lextok xtok;
1377 unsigned char nc;
1378
1379 p = ecadd(0);
1380
1381 for (;;) {
1382 xtok = tok;
1383 cmdpush(xtok == IF ? CS_IF : CS_ELIF);
1384 if (xtok == FI) {
1385 incmdpos = 0;
1386 zshlex();
1387 break;
1388 }
1389 zshlex();
1390 if (xtok == ELSE)
1391 break;
1392 while (tok == SEPER)
1393 zshlex();
1394 if (!(xtok == IF || xtok == ELIF)) {
1395 cmdpop();
1396 YYERRORV(oecused);
1397 }
1398 pp = ecadd(0);
1399 type = (xtok == IF ? WC_IF_IF : WC_IF_ELIF);
1400 par_save_list(cmplx);
1401 incmdpos = 1;
1402 if (tok == ENDINPUT) {
1403 cmdpop();
1404 YYERRORV(oecused);
1405 }
1406 while (tok == SEPER)
1407 zshlex();
1408 xtok = FI;
1409 nc = cmdstack[cmdsp - 1] == CS_IF ? CS_IFTHEN : CS_ELIFTHEN;
1410 if (tok == THEN) {
1411 usebrace = 0;
1412 cmdpop();
1413 cmdpush(nc);
1414 zshlex();
1415 par_save_list(cmplx);
1416 ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
1417 incmdpos = 1;
1418 cmdpop();
1419 } else if (tok == INBRACE) {
1420 usebrace = 1;
1421 cmdpop();
1422 cmdpush(nc);
1423 zshlex();
1424 par_save_list(cmplx);
1425 if (tok != OUTBRACE) {
1426 cmdpop();
1427 YYERRORV(oecused);
1428 }
1429 ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
1430 /* command word (else) allowed to follow immediately */
1431 zshlex();
1432 incmdpos = 1;
1433 if (tok == SEPER)
1434 break;
1435 cmdpop();
1436 } else if (unset(SHORTLOOPS)) {
1437 cmdpop();
1438 YYERRORV(oecused);
1439 } else {
1440 cmdpop();
1441 cmdpush(nc);
1442 par_save_list1(cmplx);
1443 ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
1444 incmdpos = 1;
1445 break;
1446 }
1447 }
1448 cmdpop();
1449 if (xtok == ELSE || tok == ELSE) {
1450 pp = ecadd(0);
1451 cmdpush(CS_ELSE);
1452 while (tok == SEPER)
1453 zshlex();
1454 if (tok == INBRACE && usebrace) {
1455 zshlex();
1456 par_save_list(cmplx);
1457 if (tok != OUTBRACE) {
1458 cmdpop();
1459 YYERRORV(oecused);
1460 }
1461 } else {
1462 par_save_list(cmplx);
1463 if (tok != FI) {
1464 cmdpop();
1465 YYERRORV(oecused);
1466 }
1467 }
1468 incmdpos = 0;
1469 ecbuf[pp] = WCB_IF(WC_IF_ELSE, ecused - 1 - pp);
1470 zshlex();
1471 cmdpop();
1472 }
1473 ecbuf[p] = WCB_IF(WC_IF_HEAD, ecused - 1 - p);
1474 }
1475
1476 /*
1477 * while : ( WHILE | UNTIL ) ( INPAR list OUTPAR | list ) { SEPER }
1478 ( DO list DONE | INBRACE list OUTBRACE | list ZEND )
1479 */
1480
1481 /**/
1482 static void
par_while(int * cmplx)1483 par_while(int *cmplx)
1484 {
1485 int oecused = ecused, p;
1486 int type = (tok == UNTIL ? WC_WHILE_UNTIL : WC_WHILE_WHILE);
1487
1488 p = ecadd(0);
1489 zshlex();
1490 par_save_list(cmplx);
1491 incmdpos = 1;
1492 while (tok == SEPER)
1493 zshlex();
1494 if (tok == DOLOOP) {
1495 zshlex();
1496 par_save_list(cmplx);
1497 if (tok != DONE)
1498 YYERRORV(oecused);
1499 incmdpos = 0;
1500 zshlex();
1501 } else if (tok == INBRACE) {
1502 zshlex();
1503 par_save_list(cmplx);
1504 if (tok != OUTBRACE)
1505 YYERRORV(oecused);
1506 incmdpos = 0;
1507 zshlex();
1508 } else if (isset(CSHJUNKIELOOPS)) {
1509 par_save_list(cmplx);
1510 if (tok != ZEND)
1511 YYERRORV(oecused);
1512 zshlex();
1513 } else if (unset(SHORTLOOPS)) {
1514 YYERRORV(oecused);
1515 } else
1516 par_save_list1(cmplx);
1517
1518 ecbuf[p] = WCB_WHILE(type, ecused - 1 - p);
1519 }
1520
1521 /*
1522 * repeat : REPEAT STRING { SEPER } ( DO list DONE | list1 )
1523 */
1524
1525 /**/
1526 static void
par_repeat(int * cmplx)1527 par_repeat(int *cmplx)
1528 {
1529 /* ### what to do about inrepeat_ here? */
1530 int oecused = ecused, p;
1531
1532 p = ecadd(0);
1533
1534 incmdpos = 0;
1535 zshlex();
1536 if (tok != STRING)
1537 YYERRORV(oecused);
1538 ecstr(tokstr);
1539 incmdpos = 1;
1540 zshlex();
1541 while (tok == SEPER)
1542 zshlex();
1543 if (tok == DOLOOP) {
1544 zshlex();
1545 par_save_list(cmplx);
1546 if (tok != DONE)
1547 YYERRORV(oecused);
1548 incmdpos = 0;
1549 zshlex();
1550 } else if (tok == INBRACE) {
1551 zshlex();
1552 par_save_list(cmplx);
1553 if (tok != OUTBRACE)
1554 YYERRORV(oecused);
1555 incmdpos = 0;
1556 zshlex();
1557 } else if (isset(CSHJUNKIELOOPS)) {
1558 par_save_list(cmplx);
1559 if (tok != ZEND)
1560 YYERRORV(oecused);
1561 zshlex();
1562 } else if (unset(SHORTLOOPS)) {
1563 YYERRORV(oecused);
1564 } else
1565 par_save_list1(cmplx);
1566
1567 ecbuf[p] = WCB_REPEAT(ecused - 1 - p);
1568 }
1569
1570 /*
1571 * subsh : INPAR list OUTPAR |
1572 * INBRACE list OUTBRACE [ "always" INBRACE list OUTBRACE ]
1573 *
1574 * With zsh_construct non-zero, we're doing a zsh special in which
1575 * the following token is not considered in command position. This
1576 * is used for arguments of anonymous functions.
1577 */
1578
1579 /**/
1580 static void
par_subsh(int * cmplx,int zsh_construct)1581 par_subsh(int *cmplx, int zsh_construct)
1582 {
1583 enum lextok otok = tok;
1584 int oecused = ecused, p, pp;
1585
1586 p = ecadd(0);
1587 /* Extra word only needed for always block */
1588 pp = ecadd(0);
1589 zshlex();
1590 par_list(cmplx);
1591 ecadd(WCB_END());
1592 if (tok != ((otok == INPAR) ? OUTPAR : OUTBRACE))
1593 YYERRORV(oecused);
1594 incmdpos = !zsh_construct;
1595 zshlex();
1596
1597 /* Optional always block. No intervening SEPERs allowed. */
1598 if (otok == INBRACE && tok == STRING && !strcmp(tokstr, "always")) {
1599 ecbuf[pp] = WCB_TRY(ecused - 1 - pp);
1600 incmdpos = 1;
1601 do {
1602 zshlex();
1603 } while (tok == SEPER);
1604
1605 if (tok != INBRACE)
1606 YYERRORV(oecused);
1607 cmdpop();
1608 cmdpush(CS_ALWAYS);
1609
1610 zshlex();
1611 par_save_list(cmplx);
1612 while (tok == SEPER)
1613 zshlex();
1614
1615 incmdpos = 1;
1616
1617 if (tok != OUTBRACE)
1618 YYERRORV(oecused);
1619 zshlex();
1620 ecbuf[p] = WCB_TRY(ecused - 1 - p);
1621 } else {
1622 ecbuf[p] = (otok == INPAR ? WCB_SUBSH(ecused - 1 - p) :
1623 WCB_CURSH(ecused - 1 - p));
1624 }
1625 }
1626
1627 /*
1628 * funcdef : FUNCTION wordlist [ INOUTPAR ] { SEPER }
1629 * ( list1 | INBRACE list OUTBRACE )
1630 */
1631
1632 /**/
1633 static void
par_funcdef(int * cmplx)1634 par_funcdef(int *cmplx)
1635 {
1636 int oecused = ecused, num = 0, onp, p, c = 0;
1637 int so, oecssub = ecssub;
1638 zlong oldlineno = lineno;
1639
1640 lineno = 0;
1641 nocorrect = 1;
1642 incmdpos = 0;
1643 zshlex();
1644
1645 p = ecadd(0);
1646 ecadd(0);
1647
1648 while (tok == STRING) {
1649 if ((*tokstr == Inbrace || *tokstr == '{') &&
1650 !tokstr[1]) {
1651 tok = INBRACE;
1652 break;
1653 }
1654 ecstr(tokstr);
1655 num++;
1656 zshlex();
1657 }
1658 ecadd(0);
1659 ecadd(0);
1660 ecadd(0);
1661
1662 nocorrect = 0;
1663 incmdpos = 1;
1664 if (tok == INOUTPAR)
1665 zshlex();
1666 while (tok == SEPER)
1667 zshlex();
1668
1669 ecnfunc++;
1670 ecssub = so = ecsoffs;
1671 onp = ecnpats;
1672 ecnpats = 0;
1673
1674 if (tok == INBRACE) {
1675 zshlex();
1676 par_list(&c);
1677 if (tok != OUTBRACE) {
1678 lineno += oldlineno;
1679 ecnpats = onp;
1680 ecssub = oecssub;
1681 YYERRORV(oecused);
1682 }
1683 if (num == 0) {
1684 /* Anonymous function, possibly with arguments */
1685 incmdpos = 0;
1686 }
1687 zshlex();
1688 } else if (unset(SHORTLOOPS)) {
1689 lineno += oldlineno;
1690 ecnpats = onp;
1691 ecssub = oecssub;
1692 YYERRORV(oecused);
1693 } else
1694 par_list1(&c);
1695
1696 ecadd(WCB_END());
1697 ecbuf[p + num + 2] = so - oecssub;
1698 ecbuf[p + num + 3] = ecsoffs - so;
1699 ecbuf[p + num + 4] = ecnpats;
1700 ecbuf[p + 1] = num;
1701
1702 ecnpats = onp;
1703 ecssub = oecssub;
1704 ecnfunc++;
1705
1706 ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p);
1707
1708 if (num == 0) {
1709 /* Unnamed function */
1710 int parg = ecadd(0);
1711 ecadd(0);
1712 while (tok == STRING) {
1713 ecstr(tokstr);
1714 num++;
1715 zshlex();
1716 }
1717 if (num > 0)
1718 *cmplx = 1;
1719 ecbuf[parg] = ecused - parg; /*?*/
1720 ecbuf[parg+1] = num;
1721 }
1722 lineno += oldlineno;
1723 }
1724
1725 /*
1726 * time : TIME sublist2
1727 */
1728
1729 /**/
1730 static void
par_time(void)1731 par_time(void)
1732 {
1733 int p, f, c = 0;
1734
1735 zshlex();
1736
1737 p = ecadd(0);
1738 ecadd(0);
1739 if ((f = par_sublist2(&c)) < 0) {
1740 ecused--;
1741 ecbuf[p] = WCB_TIMED(WC_TIMED_EMPTY);
1742 } else {
1743 ecbuf[p] = WCB_TIMED(WC_TIMED_PIPE);
1744 set_sublist_code(p + 1, WC_SUBLIST_END, f, ecused - 2 - p, c);
1745 }
1746 }
1747
1748 /*
1749 * dinbrack : DINBRACK cond DOUTBRACK
1750 */
1751
1752 /**/
1753 static void
par_dinbrack(void)1754 par_dinbrack(void)
1755 {
1756 int oecused = ecused;
1757
1758 incond = 1;
1759 incmdpos = 0;
1760 zshlex();
1761 par_cond();
1762 if (tok != DOUTBRACK)
1763 YYERRORV(oecused);
1764 incond = 0;
1765 incmdpos = 1;
1766 zshlex();
1767 }
1768
1769 /*
1770 * simple : { COMMAND | EXEC | NOGLOB | NOCORRECT | DASH }
1771 { STRING | ENVSTRING | ENVARRAY wordlist OUTPAR | redir }
1772 [ INOUTPAR { SEPER } ( list1 | INBRACE list OUTBRACE ) ]
1773 *
1774 * Returns 0 if no code, else 1 plus the number of code words
1775 * used up by redirections.
1776 */
1777
1778 /**/
1779 static int
par_simple(int * cmplx,int nr)1780 par_simple(int *cmplx, int nr)
1781 {
1782 int oecused = ecused, isnull = 1, r, argc = 0, p, isfunc = 0, sr = 0;
1783 int c = *cmplx, nrediradd, assignments = 0, ppost = 0, is_typeset = 0;
1784 char *hasalias = input_hasalias();
1785 wordcode postassigns = 0;
1786
1787 r = ecused;
1788 for (;;) {
1789 if (tok == NOCORRECT) {
1790 *cmplx = c = 1;
1791 nocorrect = 1;
1792 } else if (tok == ENVSTRING) {
1793 char *ptr, *name, *str;
1794
1795 name = tokstr;
1796 for (ptr = tokstr;
1797 *ptr && *ptr != Inbrack && *ptr != '=' && *ptr != '+';
1798 ptr++);
1799 if (*ptr == Inbrack) skipparens(Inbrack, Outbrack, &ptr);
1800 if (*ptr == '+') {
1801 *ptr++ = '\0';
1802 ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_INC, 0));
1803 } else
1804 ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_NEW, 0));
1805
1806 if (*ptr == '=') {
1807 *ptr = '\0';
1808 str = ptr + 1;
1809 } else
1810 equalsplit(tokstr, &str);
1811 for (ptr = str; *ptr; ptr++) {
1812 /*
1813 * We can't treat this as "simple" if it contains
1814 * expansions that require process substitution, since then
1815 * we need process handling.
1816 */
1817 if (ptr[1] == Inpar &&
1818 (*ptr == Equals || *ptr == Inang || *ptr == OutangProc)) {
1819 *cmplx = 1;
1820 break;
1821 }
1822 }
1823 ecstr(name);
1824 ecstr(str);
1825 isnull = 0;
1826 assignments = 1;
1827 } else if (tok == ENVARRAY) {
1828 int oldcmdpos = incmdpos, n, type2;
1829
1830 /*
1831 * We consider array setting cmplx because it can
1832 * contain process substitutions, which need a valid job.
1833 */
1834 *cmplx = c = 1;
1835 p = ecadd(0);
1836 incmdpos = 0;
1837 if ((type2 = strlen(tokstr) - 1) && tokstr[type2] == '+') {
1838 tokstr[type2] = '\0';
1839 type2 = WC_ASSIGN_INC;
1840 } else
1841 type2 = WC_ASSIGN_NEW;
1842 ecstr(tokstr);
1843 cmdpush(CS_ARRAY);
1844 zshlex();
1845 n = par_nl_wordlist();
1846 ecbuf[p] = WCB_ASSIGN(WC_ASSIGN_ARRAY, type2, n);
1847 cmdpop();
1848 if (tok != OUTPAR)
1849 YYERROR(oecused);
1850 incmdpos = oldcmdpos;
1851 isnull = 0;
1852 assignments = 1;
1853 } else if (IS_REDIROP(tok)) {
1854 *cmplx = c = 1;
1855 nr += par_redir(&r, NULL);
1856 continue;
1857 } else
1858 break;
1859 zshlex();
1860 if (!hasalias)
1861 hasalias = input_hasalias();
1862 }
1863 if (tok == AMPER || tok == AMPERBANG)
1864 YYERROR(oecused);
1865
1866 p = ecadd(WCB_SIMPLE(0));
1867
1868 for (;;) {
1869 if (tok == STRING || tok == TYPESET) {
1870 int redir_var = 0;
1871
1872 *cmplx = 1;
1873 incmdpos = 0;
1874
1875 if (tok == TYPESET)
1876 intypeset = is_typeset = 1;
1877
1878 if (!isset(IGNOREBRACES) && *tokstr == Inbrace)
1879 {
1880 /* Look for redirs of the form {var}>file etc. */
1881 char *eptr = tokstr + strlen(tokstr) - 1;
1882 char *ptr = eptr;
1883
1884 if (*ptr == Outbrace && ptr > tokstr + 1)
1885 {
1886 if (itype_end(tokstr+1, IIDENT, 0) >= ptr)
1887 {
1888 char *toksave = tokstr;
1889 char *idstring = dupstrpfx(tokstr+1, eptr-tokstr-1);
1890 redir_var = 1;
1891 zshlex();
1892 if (!hasalias)
1893 hasalias = input_hasalias();
1894
1895 if (IS_REDIROP(tok) && tokfd == -1)
1896 {
1897 *cmplx = c = 1;
1898 nrediradd = par_redir(&r, idstring);
1899 p += nrediradd;
1900 sr += nrediradd;
1901 }
1902 else if (postassigns)
1903 {
1904 /* C.f. normal case below */
1905 postassigns++;
1906 ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_INC, 0));
1907 ecstr(toksave);
1908 ecstr(""); /* TBD can possibly optimise out */
1909 }
1910 else
1911 {
1912 ecstr(toksave);
1913 argc++;
1914 }
1915 }
1916 }
1917 }
1918
1919 if (!redir_var)
1920 {
1921 if (postassigns) {
1922 /*
1923 * We're in the variable part of a typeset,
1924 * but this doesn't have an assignment.
1925 * We'll parse it as if it does, but mark
1926 * it specially with WC_ASSIGN_INC.
1927 */
1928 postassigns++;
1929 ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_INC, 0));
1930 ecstr(tokstr);
1931 ecstr(""); /* TBD can possibly optimise out */
1932 } else {
1933 ecstr(tokstr);
1934 argc++;
1935 }
1936 zshlex();
1937 if (!hasalias)
1938 hasalias = input_hasalias();
1939 }
1940 } else if (IS_REDIROP(tok)) {
1941 *cmplx = c = 1;
1942 nrediradd = par_redir(&r, NULL);
1943 p += nrediradd;
1944 if (ppost)
1945 ppost += nrediradd;
1946 sr += nrediradd;
1947 } else if (tok == ENVSTRING) {
1948 char *ptr, *name, *str;
1949
1950 if (!postassigns++)
1951 ppost = ecadd(0);
1952
1953 name = tokstr;
1954 for (ptr = tokstr; *ptr && *ptr != Inbrack && *ptr != '=' && *ptr != '+';
1955 ptr++);
1956 if (*ptr == Inbrack) skipparens(Inbrack, Outbrack, &ptr);
1957 ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_NEW, 0));
1958
1959 if (*ptr == '=') {
1960 *ptr = '\0';
1961 str = ptr + 1;
1962 } else
1963 equalsplit(tokstr, &str);
1964 ecstr(name);
1965 ecstr(str);
1966 zshlex();
1967 if (!hasalias)
1968 hasalias = input_hasalias();
1969 } else if (tok == ENVARRAY) {
1970 int n, parr;
1971
1972 if (!postassigns++)
1973 ppost = ecadd(0);
1974
1975 parr = ecadd(0);
1976 ecstr(tokstr);
1977 cmdpush(CS_ARRAY);
1978 /*
1979 * Careful here: this must be the typeset case,
1980 * but we need to tell the lexer not to look
1981 * for assignments until we've finished the
1982 * present one.
1983 */
1984 intypeset = 0;
1985 zshlex();
1986 n = par_nl_wordlist();
1987 ecbuf[parr] = WCB_ASSIGN(WC_ASSIGN_ARRAY, WC_ASSIGN_NEW, n);
1988 cmdpop();
1989 intypeset = 1;
1990 if (tok != OUTPAR)
1991 YYERROR(oecused);
1992 zshlex();
1993 } else if (tok == INOUTPAR) {
1994 zlong oldlineno = lineno;
1995 int onp, so, oecssub = ecssub;
1996
1997 /* Error if too many function definitions at once */
1998 if (!isset(MULTIFUNCDEF) && argc > 1)
1999 YYERROR(oecused);
2000 /* Error if preceding assignments */
2001 if (assignments || postassigns)
2002 YYERROR(oecused);
2003 if (hasalias && !isset(ALIASFUNCDEF) && argc &&
2004 hasalias != input_hasalias()) {
2005 zwarn("defining function based on alias `%s'", hasalias);
2006 YYERROR(oecused);
2007 }
2008
2009 *cmplx = c;
2010 lineno = 0;
2011 incmdpos = 1;
2012 cmdpush(CS_FUNCDEF);
2013 zshlex();
2014 while (tok == SEPER)
2015 zshlex();
2016
2017 ecispace(p + 1, 1);
2018 ecbuf[p + 1] = argc;
2019 ecadd(0);
2020 ecadd(0);
2021 ecadd(0);
2022
2023 ecnfunc++;
2024 ecssub = so = ecsoffs;
2025 onp = ecnpats;
2026 ecnpats = 0;
2027
2028 if (tok == INBRACE) {
2029 int c = 0;
2030
2031 zshlex();
2032 par_list(&c);
2033 if (tok != OUTBRACE) {
2034 cmdpop();
2035 lineno += oldlineno;
2036 ecnpats = onp;
2037 ecssub = oecssub;
2038 YYERROR(oecused);
2039 }
2040 if (argc == 0) {
2041 /* Anonymous function, possibly with arguments */
2042 incmdpos = 0;
2043 }
2044 zshlex();
2045 } else {
2046 int ll, sl, c = 0;
2047
2048 ll = ecadd(0);
2049 sl = ecadd(0);
2050 (void)ecadd(WCB_PIPE(WC_PIPE_END, 0));
2051
2052 if (!par_cmd(&c, argc == 0)) {
2053 cmdpop();
2054 YYERROR(oecused);
2055 }
2056 if (argc == 0) {
2057 /*
2058 * Anonymous function, possibly with arguments.
2059 * N.B. for cmplx structures in particular
2060 * ( ... ) we rely on lower level code doing this
2061 * to get the immediately following word (the
2062 * first token after the ")" has already been
2063 * read).
2064 */
2065 incmdpos = 0;
2066 }
2067
2068 set_sublist_code(sl, WC_SUBLIST_END, 0, ecused - 1 - sl, c);
2069 set_list_code(ll, (Z_SYNC | Z_END), c);
2070 }
2071 cmdpop();
2072
2073 ecadd(WCB_END());
2074 ecbuf[p + argc + 2] = so - oecssub;
2075 ecbuf[p + argc + 3] = ecsoffs - so;
2076 ecbuf[p + argc + 4] = ecnpats;
2077
2078 ecnpats = onp;
2079 ecssub = oecssub;
2080 ecnfunc++;
2081
2082 ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p);
2083
2084 if (argc == 0) {
2085 /* Unnamed function */
2086 int parg = ecadd(0);
2087 ecadd(0);
2088 while (tok == STRING || IS_REDIROP(tok)) {
2089 if (tok == STRING)
2090 {
2091 ecstr(tokstr);
2092 argc++;
2093 zshlex();
2094 } else {
2095 *cmplx = c = 1;
2096 nrediradd = par_redir(&r, NULL);
2097 p += nrediradd;
2098 if (ppost)
2099 ppost += nrediradd;
2100 sr += nrediradd;
2101 parg += nrediradd;
2102 }
2103 }
2104 if (argc > 0)
2105 *cmplx = 1;
2106 ecbuf[parg] = ecused - parg; /*?*/
2107 ecbuf[parg+1] = argc;
2108 }
2109 lineno += oldlineno;
2110
2111 isfunc = 1;
2112 isnull = 0;
2113 break;
2114 } else
2115 break;
2116 isnull = 0;
2117 }
2118 if (isnull && !(sr + nr)) {
2119 ecused = p;
2120 return 0;
2121 }
2122 incmdpos = 1;
2123 intypeset = 0;
2124
2125 if (!isfunc) {
2126 if (is_typeset) {
2127 ecbuf[p] = WCB_TYPESET(argc);
2128 if (postassigns)
2129 ecbuf[ppost] = postassigns;
2130 else
2131 ecadd(0);
2132 } else
2133 ecbuf[p] = WCB_SIMPLE(argc);
2134 }
2135
2136 return sr + 1;
2137 }
2138
2139 /*
2140 * redir : ( OUTANG | ... | TRINANG ) STRING
2141 *
2142 * Return number of code words required for redirection
2143 */
2144
2145 static int redirtab[TRINANG - OUTANG + 1] = {
2146 REDIR_WRITE,
2147 REDIR_WRITENOW,
2148 REDIR_APP,
2149 REDIR_APPNOW,
2150 REDIR_READ,
2151 REDIR_READWRITE,
2152 REDIR_HEREDOC,
2153 REDIR_HEREDOCDASH,
2154 REDIR_MERGEIN,
2155 REDIR_MERGEOUT,
2156 REDIR_ERRWRITE,
2157 REDIR_ERRWRITENOW,
2158 REDIR_ERRAPP,
2159 REDIR_ERRAPPNOW,
2160 REDIR_HERESTR,
2161 };
2162
2163 /**/
2164 static int
par_redir(int * rp,char * idstring)2165 par_redir(int *rp, char *idstring)
2166 {
2167 int r = *rp, type, fd1, oldcmdpos, oldnc, ncodes;
2168 char *name;
2169
2170 oldcmdpos = incmdpos;
2171 incmdpos = 0;
2172 oldnc = nocorrect;
2173 if (tok != INANG && tok != INOUTANG)
2174 nocorrect = 1;
2175 type = redirtab[tok - OUTANG];
2176 fd1 = tokfd;
2177 zshlex();
2178 if (tok != STRING && tok != ENVSTRING)
2179 YYERROR(ecused);
2180 incmdpos = oldcmdpos;
2181 nocorrect = oldnc;
2182
2183 /* assign default fd */
2184 if (fd1 == -1)
2185 fd1 = IS_READFD(type) ? 0 : 1;
2186
2187 name = tokstr;
2188
2189 switch (type) {
2190 case REDIR_HEREDOC:
2191 case REDIR_HEREDOCDASH: {
2192 /* <<[-] name */
2193 struct heredocs **hd;
2194 int htype = type;
2195
2196 /*
2197 * Add two here for the string to remember the HERE
2198 * terminator in raw and munged form.
2199 */
2200 if (idstring)
2201 {
2202 type |= REDIR_VARID_MASK;
2203 ncodes = 6;
2204 }
2205 else
2206 ncodes = 5;
2207
2208 /* If we ever to change the number of codes, we have to change
2209 * the definition of WC_REDIR_WORDS. */
2210 ecispace(r, ncodes);
2211 *rp = r + ncodes;
2212 ecbuf[r] = WCB_REDIR(type | REDIR_FROM_HEREDOC_MASK);
2213 ecbuf[r + 1] = fd1;
2214
2215 /*
2216 * r + 2: the HERE string we recover
2217 * r + 3: the HERE document terminator, raw
2218 * r + 4: the HERE document terminator, munged
2219 */
2220 if (idstring)
2221 ecbuf[r + 5] = ecstrcode(idstring);
2222
2223 for (hd = &hdocs; *hd; hd = &(*hd)->next)
2224 ;
2225 *hd = zalloc(sizeof(struct heredocs));
2226 (*hd)->next = NULL;
2227 (*hd)->type = htype;
2228 (*hd)->pc = r;
2229 (*hd)->str = tokstr;
2230
2231 zshlex();
2232 return ncodes;
2233 }
2234 case REDIR_WRITE:
2235 case REDIR_WRITENOW:
2236 if (tokstr[0] == OutangProc && tokstr[1] == Inpar)
2237 /* > >(...) */
2238 type = REDIR_OUTPIPE;
2239 else if (tokstr[0] == Inang && tokstr[1] == Inpar)
2240 YYERROR(ecused);
2241 break;
2242 case REDIR_READ:
2243 if (tokstr[0] == Inang && tokstr[1] == Inpar)
2244 /* < <(...) */
2245 type = REDIR_INPIPE;
2246 else if (tokstr[0] == OutangProc && tokstr[1] == Inpar)
2247 YYERROR(ecused);
2248 break;
2249 case REDIR_READWRITE:
2250 if ((tokstr[0] == Inang || tokstr[0] == OutangProc) &&
2251 tokstr[1] == Inpar)
2252 type = tokstr[0] == Inang ? REDIR_INPIPE : REDIR_OUTPIPE;
2253 break;
2254 }
2255 zshlex();
2256
2257 /* If we ever to change the number of codes, we have to change
2258 * the definition of WC_REDIR_WORDS. */
2259 if (idstring)
2260 {
2261 type |= REDIR_VARID_MASK;
2262 ncodes = 4;
2263 }
2264 else
2265 ncodes = 3;
2266
2267 ecispace(r, ncodes);
2268 *rp = r + ncodes;
2269 ecbuf[r] = WCB_REDIR(type);
2270 ecbuf[r + 1] = fd1;
2271 ecbuf[r + 2] = ecstrcode(name);
2272 if (idstring)
2273 ecbuf[r + 3] = ecstrcode(idstring);
2274
2275 return ncodes;
2276 }
2277
2278 /**/
2279 void
setheredoc(int pc,int type,char * str,char * termstr,char * munged_termstr)2280 setheredoc(int pc, int type, char *str, char *termstr, char *munged_termstr)
2281 {
2282 int varid = WC_REDIR_VARID(ecbuf[pc]) ? REDIR_VARID_MASK : 0;
2283 ecbuf[pc] = WCB_REDIR(type | REDIR_FROM_HEREDOC_MASK | varid);
2284 ecbuf[pc + 2] = ecstrcode(str);
2285 ecbuf[pc + 3] = ecstrcode(termstr);
2286 ecbuf[pc + 4] = ecstrcode(munged_termstr);
2287 }
2288
2289 /*
2290 * wordlist : { STRING }
2291 */
2292
2293 /**/
2294 static int
par_wordlist(void)2295 par_wordlist(void)
2296 {
2297 int num = 0;
2298 while (tok == STRING) {
2299 ecstr(tokstr);
2300 num++;
2301 zshlex();
2302 }
2303 return num;
2304 }
2305
2306 /*
2307 * nl_wordlist : { STRING | SEPER }
2308 */
2309
2310 /**/
2311 static int
par_nl_wordlist(void)2312 par_nl_wordlist(void)
2313 {
2314 int num = 0;
2315
2316 while (tok == STRING || tok == SEPER) {
2317 if (tok != SEPER) {
2318 ecstr(tokstr);
2319 num++;
2320 }
2321 zshlex();
2322 }
2323 return num;
2324 }
2325
2326 /*
2327 * condlex is zshlex for normal parsing, but is altered to allow
2328 * the test builtin to use par_cond.
2329 */
2330
2331 /**/
2332 void (*condlex) _((void)) = zshlex;
2333
2334 /*
2335 * cond : cond_1 { SEPER } [ DBAR { SEPER } cond ]
2336 */
2337
2338 #define COND_SEP() (tok == SEPER && condlex != testlex && *zshlextext != ';')
2339
2340 /**/
2341 static int
par_cond(void)2342 par_cond(void)
2343 {
2344 int p = ecused, r;
2345
2346 r = par_cond_1();
2347 while (COND_SEP())
2348 condlex();
2349 if (tok == DBAR) {
2350 condlex();
2351 while (COND_SEP())
2352 condlex();
2353 ecispace(p, 1);
2354 par_cond();
2355 ecbuf[p] = WCB_COND(COND_OR, ecused - 1 - p);
2356 return 1;
2357 }
2358 return r;
2359 }
2360
2361 /*
2362 * cond_1 : cond_2 { SEPER } [ DAMPER { SEPER } cond_1 ]
2363 */
2364
2365 /**/
2366 static int
par_cond_1(void)2367 par_cond_1(void)
2368 {
2369 int r, p = ecused;
2370
2371 r = par_cond_2();
2372 while (COND_SEP())
2373 condlex();
2374 if (tok == DAMPER) {
2375 condlex();
2376 while (COND_SEP())
2377 condlex();
2378 ecispace(p, 1);
2379 par_cond_1();
2380 ecbuf[p] = WCB_COND(COND_AND, ecused - 1 - p);
2381 return 1;
2382 }
2383 return r;
2384 }
2385
2386 /*
2387 * Return 1 if condition matches. This also works for non-elided options.
2388 *
2389 * input is test string, may begin - or Dash.
2390 * cond is condition following the -.
2391 */
check_cond(const char * input,const char * cond)2392 static int check_cond(const char *input, const char *cond)
2393 {
2394 if (!IS_DASH(input[0]))
2395 return 0;
2396 return !strcmp(input + 1, cond);
2397 }
2398
2399 /*
2400 * cond_2 : BANG cond_2
2401 | INPAR { SEPER } cond_2 { SEPER } OUTPAR
2402 | STRING STRING STRING
2403 | STRING STRING
2404 | STRING ( INANG | OUTANG ) STRING
2405 */
2406
2407 /**/
2408 static int
par_cond_2(void)2409 par_cond_2(void)
2410 {
2411 char *s1, *s2, *s3;
2412 int dble = 0;
2413 int n_testargs = (condlex == testlex) ? arrlen(testargs) + 1 : 0;
2414
2415 if (n_testargs) {
2416 /* See the description of test in POSIX 1003.2 */
2417 if (tok == NULLTOK)
2418 /* no arguments: false */
2419 return par_cond_double(dupstring("-n"), dupstring(""));
2420 if (n_testargs == 1) {
2421 /* one argument: [ foo ] is equivalent to [ -n foo ] */
2422 s1 = tokstr;
2423 condlex();
2424 /* ksh behavior: [ -t ] means [ -t 1 ]; bash disagrees */
2425 if (unset(POSIXBUILTINS) && check_cond(s1, "t"))
2426 return par_cond_double(s1, dupstring("1"));
2427 return par_cond_double(dupstring("-n"), s1);
2428 }
2429 if (n_testargs > 2) {
2430 /* three arguments: if the second argument is a binary operator, *
2431 * perform that binary test on the first and the third argument */
2432 if (!strcmp(*testargs, "=") ||
2433 !strcmp(*testargs, "==") ||
2434 !strcmp(*testargs, "!=") ||
2435 (IS_DASH(**testargs) && get_cond_num(*testargs + 1) >= 0)) {
2436 s1 = tokstr;
2437 condlex();
2438 s2 = tokstr;
2439 condlex();
2440 s3 = tokstr;
2441 condlex();
2442 return par_cond_triple(s1, s2, s3);
2443 }
2444 }
2445 /*
2446 * We fall through here on any non-numeric infix operator
2447 * or any other time there are at least two arguments.
2448 */
2449 } else
2450 while (COND_SEP())
2451 condlex();
2452 if (tok == BANG) {
2453 /*
2454 * In "test" compatibility mode, "! -a ..." and "! -o ..."
2455 * are treated as "[string] [and] ..." and "[string] [or] ...".
2456 */
2457 if (!(n_testargs > 1 && (check_cond(*testargs, "a") ||
2458 check_cond(*testargs, "o"))))
2459 {
2460 condlex();
2461 ecadd(WCB_COND(COND_NOT, 0));
2462 return par_cond_2();
2463 }
2464 }
2465 if (tok == INPAR) {
2466 int r;
2467
2468 condlex();
2469 while (COND_SEP())
2470 condlex();
2471 r = par_cond();
2472 while (COND_SEP())
2473 condlex();
2474 if (tok != OUTPAR)
2475 YYERROR(ecused);
2476 condlex();
2477 return r;
2478 }
2479 s1 = tokstr;
2480 dble = (s1 && IS_DASH(*s1)
2481 && (!n_testargs
2482 || strspn(s1+1, "abcdefghknoprstuvwxzLONGS") == 1)
2483 && !s1[2]);
2484 if (tok != STRING) {
2485 /* Check first argument for [[ STRING ]] re-interpretation */
2486 if (s1 /* tok != DOUTBRACK && tok != DAMPER && tok != DBAR */
2487 && tok != LEXERR && (!dble || n_testargs)) {
2488 do condlex(); while (COND_SEP());
2489 return par_cond_double(dupstring("-n"), s1);
2490 } else
2491 YYERROR(ecused);
2492 }
2493 condlex();
2494 if (n_testargs == 2 && tok != STRING && tokstr && IS_DASH(s1[0])) {
2495 /*
2496 * Something like "test -z" followed by a token.
2497 * We'll turn the token into a string (we've also
2498 * checked it does have a string representation).
2499 */
2500 tok = STRING;
2501 } else
2502 while (COND_SEP())
2503 condlex();
2504 if (tok == INANG || tok == OUTANG) {
2505 enum lextok xtok = tok;
2506 do condlex(); while (COND_SEP());
2507 if (tok != STRING)
2508 YYERROR(ecused);
2509 s3 = tokstr;
2510 do condlex(); while (COND_SEP());
2511 ecadd(WCB_COND((xtok == INANG ? COND_STRLT : COND_STRGTR), 0));
2512 ecstr(s1);
2513 ecstr(s3);
2514 return 1;
2515 }
2516 if (tok != STRING) {
2517 /*
2518 * Check second argument in case semantics e.g. [ = -a = ]
2519 * mean we have to go back and fix up the first one
2520 */
2521 if (tok != LEXERR) {
2522 if (!dble || n_testargs)
2523 return par_cond_double(dupstring("-n"), s1);
2524 else
2525 return par_cond_multi(s1, newlinklist());
2526 } else
2527 YYERROR(ecused);
2528 }
2529 s2 = tokstr;
2530 if (!n_testargs)
2531 dble = (s2 && IS_DASH(*s2) && !s2[2]);
2532 incond++; /* parentheses do globbing */
2533 do condlex(); while (COND_SEP());
2534 incond--; /* parentheses do grouping */
2535 if (tok == STRING && !dble) {
2536 s3 = tokstr;
2537 do condlex(); while (COND_SEP());
2538 if (tok == STRING) {
2539 LinkList l = newlinklist();
2540
2541 addlinknode(l, s2);
2542 addlinknode(l, s3);
2543
2544 while (tok == STRING) {
2545 addlinknode(l, tokstr);
2546 do condlex(); while (COND_SEP());
2547 }
2548 return par_cond_multi(s1, l);
2549 } else
2550 return par_cond_triple(s1, s2, s3);
2551 } else
2552 return par_cond_double(s1, s2);
2553 }
2554
2555 /**/
2556 static int
par_cond_double(char * a,char * b)2557 par_cond_double(char *a, char *b)
2558 {
2559 if (!IS_DASH(a[0]) || !a[1])
2560 COND_ERROR("parse error: condition expected: %s", a);
2561 else if (!a[2] && strspn(a+1, "abcdefgknoprstuvwxzhLONGS") == 1) {
2562 ecadd(WCB_COND(a[1], 0));
2563 ecstr(b);
2564 } else {
2565 ecadd(WCB_COND(COND_MOD, 1));
2566 ecstr(a);
2567 ecstr(b);
2568 }
2569 return 1;
2570 }
2571
2572 /**/
2573 static int
get_cond_num(char * tst)2574 get_cond_num(char *tst)
2575 {
2576 static char *condstrs[] =
2577 {
2578 "nt", "ot", "ef", "eq", "ne", "lt", "gt", "le", "ge", NULL
2579 };
2580 int t0;
2581
2582 for (t0 = 0; condstrs[t0]; t0++)
2583 if (!strcmp(condstrs[t0], tst))
2584 return t0;
2585 return -1;
2586 }
2587
2588 /**/
2589 static int
par_cond_triple(char * a,char * b,char * c)2590 par_cond_triple(char *a, char *b, char *c)
2591 {
2592 int t0;
2593
2594 if ((b[0] == Equals || b[0] == '=') && !b[1]) {
2595 ecadd(WCB_COND(COND_STREQ, 0));
2596 ecstr(a);
2597 ecstr(c);
2598 ecadd(ecnpats++);
2599 } else if ((b[0] == Equals || b[0] == '=') &&
2600 (b[1] == Equals || b[1] == '=') && !b[2]) {
2601 ecadd(WCB_COND(COND_STRDEQ, 0));
2602 ecstr(a);
2603 ecstr(c);
2604 ecadd(ecnpats++);
2605 } else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2]) {
2606 ecadd(WCB_COND(COND_STRNEQ, 0));
2607 ecstr(a);
2608 ecstr(c);
2609 ecadd(ecnpats++);
2610 } else if ((b[0] == Equals || b[0] == '=') &&
2611 (b[1] == '~' || b[1] == Tilde) && !b[2]) {
2612 /* We become an implicit COND_MODI but do not provide the first
2613 * item, it's skipped */
2614 ecadd(WCB_COND(COND_REGEX, 0));
2615 ecstr(a);
2616 ecstr(c);
2617 } else if (IS_DASH(b[0])) {
2618 if ((t0 = get_cond_num(b + 1)) > -1) {
2619 ecadd(WCB_COND(t0 + COND_NT, 0));
2620 ecstr(a);
2621 ecstr(c);
2622 } else {
2623 ecadd(WCB_COND(COND_MODI, 0));
2624 ecstr(b);
2625 ecstr(a);
2626 ecstr(c);
2627 }
2628 } else if (IS_DASH(a[0]) && a[1]) {
2629 ecadd(WCB_COND(COND_MOD, 2));
2630 ecstr(a);
2631 ecstr(b);
2632 ecstr(c);
2633 } else
2634 COND_ERROR("condition expected: %s", b);
2635
2636 return 1;
2637 }
2638
2639 /**/
2640 static int
par_cond_multi(char * a,LinkList l)2641 par_cond_multi(char *a, LinkList l)
2642 {
2643 if (!IS_DASH(a[0]) || !a[1])
2644 COND_ERROR("condition expected: %s", a);
2645 else {
2646 LinkNode n;
2647
2648 ecadd(WCB_COND(COND_MOD, countlinknodes(l)));
2649 ecstr(a);
2650 for (n = firstnode(l); n; incnode(n))
2651 ecstr((char *) getdata(n));
2652 }
2653 return 1;
2654 }
2655
2656 /**/
2657 static void
yyerror(int noerr)2658 yyerror(int noerr)
2659 {
2660 int t0;
2661 char *t;
2662
2663 if ((t = dupstring(zshlextext)))
2664 untokenize(t);
2665
2666 for (t0 = 0; t0 != 20; t0++)
2667 if (!t || !t[t0] || t[t0] == '\n')
2668 break;
2669 if (!(histdone & HISTFLAG_NOEXEC) && !(errflag & ERRFLAG_INT)) {
2670 if (t0 == 20)
2671 zwarn("parse error near `%l...'", t, 20);
2672 else if (t0)
2673 zwarn("parse error near `%l'", t, t0);
2674 else
2675 zwarn("parse error");
2676 }
2677 if (!noerr && noerrs != 2)
2678 errflag |= ERRFLAG_ERROR;
2679 }
2680
2681 /*
2682 * Duplicate a programme list, on the heap if heap is 1, else
2683 * in permanent storage.
2684 *
2685 * Be careful in case p is the Eprog for a function which will
2686 * later be autoloaded. The shf element of the returned Eprog
2687 * must be set appropriately by the caller. (Normally we create
2688 * the Eprog in this case by using mkautofn.)
2689 */
2690
2691 /**/
2692 mod_export Eprog
dupeprog(Eprog p,int heap)2693 dupeprog(Eprog p, int heap)
2694 {
2695 Eprog r;
2696 int i;
2697 Patprog *pp;
2698
2699 if (p == &dummy_eprog)
2700 return p;
2701
2702 r = (heap ? (Eprog) zhalloc(sizeof(*r)) : (Eprog) zalloc(sizeof(*r)));
2703 r->flags = (heap ? EF_HEAP : EF_REAL) | (p->flags & EF_RUN);
2704 r->dump = NULL;
2705 r->len = p->len;
2706 r->npats = p->npats;
2707 /*
2708 * If Eprog is on the heap, reference count is not valid.
2709 * Otherwise, initialise reference count to 1 so that a freeeprog()
2710 * will delete it if it is not in use.
2711 */
2712 r->nref = heap ? -1 : 1;
2713 pp = r->pats = (heap ? (Patprog *) hcalloc(r->len) :
2714 (Patprog *) zshcalloc(r->len));
2715 r->prog = (Wordcode) (r->pats + r->npats);
2716 r->strs = ((char *) r->prog) + (p->strs - ((char *) p->prog));
2717 memcpy(r->prog, p->prog, r->len - (p->npats * sizeof(Patprog)));
2718 r->shf = NULL;
2719
2720 for (i = r->npats; i--; pp++)
2721 *pp = dummy_patprog1;
2722
2723 return r;
2724 }
2725
2726
2727 /*
2728 * Pair of functions to mark an Eprog as in use, and to delete it
2729 * when it is no longer in use, by means of the reference count in
2730 * then nref element.
2731 *
2732 * If nref is negative, the Eprog is on the heap and is never freed.
2733 */
2734
2735 /* Increase the reference count of an Eprog so it won't be deleted. */
2736
2737 /**/
2738 mod_export void
useeprog(Eprog p)2739 useeprog(Eprog p)
2740 {
2741 if (p && p != &dummy_eprog && p->nref >= 0)
2742 p->nref++;
2743 }
2744
2745 /* Free an Eprog if we have finished with it */
2746
2747 /**/
2748 mod_export void
freeeprog(Eprog p)2749 freeeprog(Eprog p)
2750 {
2751 int i;
2752 Patprog *pp;
2753
2754 if (p && p != &dummy_eprog) {
2755 /* paranoia */
2756 DPUTS(p->nref > 0 && (p->flags & EF_HEAP), "Heap EPROG has nref > 0");
2757 DPUTS(p->nref < 0 && !(p->flags & EF_HEAP), "Real EPROG has nref < 0");
2758 DPUTS(p->nref < -1, "Uninitialised EPROG nref");
2759 #ifdef MAX_FUNCTION_DEPTH
2760 DPUTS(zsh_funcnest >=0 && p->nref > zsh_funcnest + 10,
2761 "Overlarge EPROG nref");
2762 #endif
2763 if (p->nref > 0 && !--p->nref) {
2764 for (i = p->npats, pp = p->pats; i--; pp++)
2765 freepatprog(*pp);
2766 if (p->dump) {
2767 decrdumpcount(p->dump);
2768 zfree(p->pats, p->npats * sizeof(Patprog));
2769 } else
2770 zfree(p->pats, p->len);
2771 zfree(p, sizeof(*p));
2772 }
2773 }
2774 }
2775
2776 /**/
2777 char *
ecgetstr(Estate s,int dup,int * tokflag)2778 ecgetstr(Estate s, int dup, int *tokflag)
2779 {
2780 static char buf[4];
2781 wordcode c = *s->pc++;
2782 char *r;
2783
2784 if (c == 6 || c == 7)
2785 r = "";
2786 else if (c & 2) {
2787 buf[0] = (char) ((c >> 3) & 0xff);
2788 buf[1] = (char) ((c >> 11) & 0xff);
2789 buf[2] = (char) ((c >> 19) & 0xff);
2790 buf[3] = '\0';
2791 r = dupstring(buf);
2792 dup = EC_NODUP;
2793 } else {
2794 r = s->strs + (c >> 2);
2795 }
2796 if (tokflag)
2797 *tokflag = (c & 1);
2798
2799 /*** Since function dump files are mapped read-only, avoiding to
2800 * to duplicate strings when they don't contain tokens may fail
2801 * when one of the many utility functions happens to write to
2802 * one of the strings (without really modifying it).
2803 * If that happens to you and you don't feel like debugging it,
2804 * just change the line below to:
2805 *
2806 * return (dup ? dupstring(r) : r);
2807 */
2808
2809 return ((dup == EC_DUP || (dup && (c & 1))) ? dupstring(r) : r);
2810 }
2811
2812 /**/
2813 char *
ecrawstr(Eprog p,Wordcode pc,int * tokflag)2814 ecrawstr(Eprog p, Wordcode pc, int *tokflag)
2815 {
2816 static char buf[4];
2817 wordcode c = *pc;
2818
2819 if (c == 6 || c == 7) {
2820 if (tokflag)
2821 *tokflag = (c & 1);
2822 return "";
2823 } else if (c & 2) {
2824 buf[0] = (char) ((c >> 3) & 0xff);
2825 buf[1] = (char) ((c >> 11) & 0xff);
2826 buf[2] = (char) ((c >> 19) & 0xff);
2827 buf[3] = '\0';
2828 if (tokflag)
2829 *tokflag = (c & 1);
2830 return buf;
2831 } else {
2832 if (tokflag)
2833 *tokflag = (c & 1);
2834 return p->strs + (c >> 2);
2835 }
2836 }
2837
2838 /**/
2839 char **
ecgetarr(Estate s,int num,int dup,int * tokflag)2840 ecgetarr(Estate s, int num, int dup, int *tokflag)
2841 {
2842 char **ret, **rp;
2843 int tf = 0, tmp = 0;
2844
2845 ret = rp = (char **) zhalloc((num + 1) * sizeof(char *));
2846
2847 while (num--) {
2848 *rp++ = ecgetstr(s, dup, &tmp);
2849 tf |= tmp;
2850 }
2851 *rp = NULL;
2852 if (tokflag)
2853 *tokflag = tf;
2854
2855 return ret;
2856 }
2857
2858 /**/
2859 LinkList
ecgetlist(Estate s,int num,int dup,int * tokflag)2860 ecgetlist(Estate s, int num, int dup, int *tokflag)
2861 {
2862 if (num) {
2863 LinkList ret;
2864 int i, tf = 0, tmp = 0;
2865
2866 ret = newsizedlist(num);
2867 for (i = 0; i < num; i++) {
2868 setsizednode(ret, i, ecgetstr(s, dup, &tmp));
2869 tf |= tmp;
2870 }
2871 if (tokflag)
2872 *tokflag = tf;
2873 return ret;
2874 }
2875 if (tokflag)
2876 *tokflag = 0;
2877 return NULL;
2878 }
2879
2880 /**/
2881 LinkList
ecgetredirs(Estate s)2882 ecgetredirs(Estate s)
2883 {
2884 LinkList ret = newlinklist();
2885 wordcode code = *s->pc++;
2886
2887 while (wc_code(code) == WC_REDIR) {
2888 Redir r = (Redir) zhalloc(sizeof(*r));
2889
2890 r->type = WC_REDIR_TYPE(code);
2891 r->fd1 = *s->pc++;
2892 r->name = ecgetstr(s, EC_DUP, NULL);
2893 if (WC_REDIR_FROM_HEREDOC(code)) {
2894 r->flags = REDIRF_FROM_HEREDOC;
2895 r->here_terminator = ecgetstr(s, EC_DUP, NULL);
2896 r->munged_here_terminator = ecgetstr(s, EC_DUP, NULL);
2897 } else {
2898 r->flags = 0;
2899 r->here_terminator = NULL;
2900 r->munged_here_terminator = NULL;
2901 }
2902 if (WC_REDIR_VARID(code))
2903 r->varid = ecgetstr(s, EC_DUP, NULL);
2904 else
2905 r->varid = NULL;
2906
2907 addlinknode(ret, r);
2908
2909 code = *s->pc++;
2910 }
2911 s->pc--;
2912
2913 return ret;
2914 }
2915
2916 /*
2917 * Copy the consecutive set of redirections in the state at s.
2918 * Return NULL if none, else an Eprog consisting only of the
2919 * redirections from permanently allocated memory.
2920 *
2921 * s is left in the state ready for whatever follows the redirections.
2922 */
2923
2924 /**/
2925 Eprog
eccopyredirs(Estate s)2926 eccopyredirs(Estate s)
2927 {
2928 Wordcode pc = s->pc;
2929 wordcode code = *pc;
2930 int ncode, ncodes = 0, r;
2931
2932 if (wc_code(code) != WC_REDIR)
2933 return NULL;
2934
2935 init_parse();
2936
2937 while (wc_code(code) == WC_REDIR) {
2938 #ifdef DEBUG
2939 int type = WC_REDIR_TYPE(code);
2940 #endif
2941
2942 DPUTS(type == REDIR_HEREDOC || type == REDIR_HEREDOCDASH,
2943 "unexpanded here document");
2944
2945 if (WC_REDIR_FROM_HEREDOC(code))
2946 ncode = 5;
2947 else
2948 ncode = 3;
2949 if (WC_REDIR_VARID(code))
2950 ncode++;
2951 pc += ncode;
2952 ncodes += ncode;
2953 code = *pc;
2954 }
2955 r = ecused;
2956 ecispace(r, ncodes);
2957
2958 code = *s->pc;
2959 while (wc_code(code) == WC_REDIR) {
2960 s->pc++;
2961
2962 ecbuf[r++] = code;
2963 /* fd1 */
2964 ecbuf[r++] = *s->pc++;
2965 /* name or HERE string */
2966 /* No DUP needed as we'll copy into Eprog immediately below */
2967 ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
2968 if (WC_REDIR_FROM_HEREDOC(code))
2969 {
2970 /* terminator, raw */
2971 ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
2972 /* terminator, munged */
2973 ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
2974 }
2975 if (WC_REDIR_VARID(code))
2976 ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
2977
2978 code = *s->pc;
2979 }
2980
2981 /* bld_eprog() appends a useful WC_END marker */
2982 return bld_eprog(0);
2983 }
2984
2985 /**/
2986 mod_export struct eprog dummy_eprog;
2987
2988 static wordcode dummy_eprog_code;
2989
2990 /**/
2991 void
init_eprog(void)2992 init_eprog(void)
2993 {
2994 dummy_eprog_code = WCB_END();
2995 dummy_eprog.len = sizeof(wordcode);
2996 dummy_eprog.prog = &dummy_eprog_code;
2997 dummy_eprog.strs = NULL;
2998 }
2999
3000 /* Code for function dump files.
3001 *
3002 * Dump files consist of a header and the function bodies (the wordcode
3003 * plus the string table) and that twice: once for the byte-order of the
3004 * host the file was created on and once for the other byte-order. The
3005 * header describes where the beginning of the `other' version is and it
3006 * is up to the shell reading the file to decide which version it needs.
3007 * This is done by checking if the first word is FD_MAGIC (then the
3008 * shell reading the file has the same byte order as the one that created
3009 * the file) or if it is FD_OMAGIC, then the `other' version has to be
3010 * read.
3011 * The header is the magic number, a word containing the flags (if the
3012 * file should be mapped or read and if this header is the `other' one),
3013 * the version string in a field of 40 characters and the descriptions
3014 * for the functions in the dump file.
3015 *
3016 * NOTES:
3017 * - This layout has to be kept; everything after it may be changed.
3018 * - When incompatible changes are made, the FD_MAGIC and FD_OMAGIC
3019 * numbers have to be changed.
3020 *
3021 * Each description consists of a struct fdhead followed by the name,
3022 * aligned to sizeof(wordcode) (i.e. 4 bytes).
3023 */
3024
3025 #include "version.h"
3026
3027 #define FD_EXT ".zwc"
3028 #define FD_MINMAP 4096
3029
3030 #define FD_PRELEN 12
3031 #define FD_MAGIC 0x04050607
3032 #define FD_OMAGIC 0x07060504
3033
3034 #define FDF_MAP 1
3035 #define FDF_OTHER 2
3036
3037 typedef struct fdhead *FDHead;
3038
3039 struct fdhead {
3040 wordcode start; /* offset to function definition */
3041 wordcode len; /* length of wordcode/strings */
3042 wordcode npats; /* number of patterns needed */
3043 wordcode strs; /* offset to strings */
3044 wordcode hlen; /* header length (incl. name) */
3045 wordcode flags; /* flags and offset to name tail */
3046 };
3047
3048 #define fdheaderlen(f) (((Wordcode) (f))[FD_PRELEN])
3049
3050 #define fdmagic(f) (((Wordcode) (f))[0])
3051 #define fdsetbyte(f,i,v) \
3052 ((((unsigned char *) (((Wordcode) (f)) + 1))[i]) = ((unsigned char) (v)))
3053 #define fdbyte(f,i) ((wordcode) (((unsigned char *) (((Wordcode) (f)) + 1))[i]))
3054 #define fdflags(f) fdbyte(f, 0)
3055 #define fdsetflags(f,v) fdsetbyte(f, 0, v)
3056 #define fdother(f) (fdbyte(f, 1) + (fdbyte(f, 2) << 8) + (fdbyte(f, 3) << 16))
3057 #define fdsetother(f, o) \
3058 do { \
3059 fdsetbyte(f, 1, ((o) & 0xff)); \
3060 fdsetbyte(f, 2, (((o) >> 8) & 0xff)); \
3061 fdsetbyte(f, 3, (((o) >> 16) & 0xff)); \
3062 } while (0)
3063 #define fdversion(f) ((char *) ((f) + 2))
3064
3065 #define firstfdhead(f) ((FDHead) (((Wordcode) (f)) + FD_PRELEN))
3066 #define nextfdhead(f) ((FDHead) (((Wordcode) (f)) + (f)->hlen))
3067
3068 #define fdhflags(f) (((FDHead) (f))->flags)
3069 #define fdhtail(f) (((FDHead) (f))->flags >> 2)
3070 #define fdhbldflags(f,t) ((f) | ((t) << 2))
3071
3072 #define FDHF_KSHLOAD 1
3073 #define FDHF_ZSHLOAD 2
3074
3075 #define fdname(f) ((char *) (((FDHead) (f)) + 1))
3076
3077 /* This is used when building wordcode files. */
3078
3079 typedef struct wcfunc *WCFunc;
3080
3081 struct wcfunc {
3082 char *name;
3083 Eprog prog;
3084 int flags;
3085 };
3086
3087 /* Try to find the description for the given function name. */
3088
3089 static FDHead
dump_find_func(Wordcode h,char * name)3090 dump_find_func(Wordcode h, char *name)
3091 {
3092 FDHead n, e = (FDHead) (h + fdheaderlen(h));
3093
3094 for (n = firstfdhead(h); n < e; n = nextfdhead(n))
3095 if (!strcmp(name, fdname(n) + fdhtail(n)))
3096 return n;
3097
3098 return NULL;
3099 }
3100
3101 /**/
3102 int
bin_zcompile(char * nam,char ** args,Options ops,UNUSED (int func))3103 bin_zcompile(char *nam, char **args, Options ops, UNUSED(int func))
3104 {
3105 int map, flags, ret;
3106 char *dump;
3107
3108 if ((OPT_ISSET(ops,'k') && OPT_ISSET(ops,'z')) ||
3109 (OPT_ISSET(ops,'R') && OPT_ISSET(ops,'M')) ||
3110 (OPT_ISSET(ops,'c') &&
3111 (OPT_ISSET(ops,'U') || OPT_ISSET(ops,'k') || OPT_ISSET(ops,'z'))) ||
3112 (!(OPT_ISSET(ops,'c') || OPT_ISSET(ops,'a')) && OPT_ISSET(ops,'m'))) {
3113 zwarnnam(nam, "illegal combination of options");
3114 return 1;
3115 }
3116 if ((OPT_ISSET(ops,'c') || OPT_ISSET(ops,'a')) && isset(KSHAUTOLOAD))
3117 zwarnnam(nam, "functions will use zsh style autoloading");
3118
3119 flags = (OPT_ISSET(ops,'k') ? FDHF_KSHLOAD :
3120 (OPT_ISSET(ops,'z') ? FDHF_ZSHLOAD : 0));
3121
3122 if (OPT_ISSET(ops,'t')) {
3123 Wordcode f;
3124
3125 if (!*args) {
3126 zwarnnam(nam, "too few arguments");
3127 return 1;
3128 }
3129 if (!(f = load_dump_header(nam, (strsfx(FD_EXT, *args) ? *args :
3130 dyncat(*args, FD_EXT)), 1)))
3131 return 1;
3132
3133 if (args[1]) {
3134 for (args++; *args; args++)
3135 if (!dump_find_func(f, *args))
3136 return 1;
3137 return 0;
3138 } else {
3139 FDHead h, e = (FDHead) (f + fdheaderlen(f));
3140
3141 printf("zwc file (%s) for zsh-%s\n",
3142 ((fdflags(f) & FDF_MAP) ? "mapped" : "read"), fdversion(f));
3143 for (h = firstfdhead(f); h < e; h = nextfdhead(h))
3144 printf("%s\n", fdname(h));
3145 return 0;
3146 }
3147 }
3148 if (!*args) {
3149 zwarnnam(nam, "too few arguments");
3150 return 1;
3151 }
3152 map = (OPT_ISSET(ops,'M') ? 2 : (OPT_ISSET(ops,'R') ? 0 : 1));
3153
3154 if (!args[1] && !(OPT_ISSET(ops,'c') || OPT_ISSET(ops,'a'))) {
3155 queue_signals();
3156 ret = build_dump(nam, dyncat(*args, FD_EXT), args, OPT_ISSET(ops,'U'),
3157 map, flags);
3158 unqueue_signals();
3159 return ret;
3160 }
3161 dump = (strsfx(FD_EXT, *args) ? *args : dyncat(*args, FD_EXT));
3162
3163 queue_signals();
3164 ret = ((OPT_ISSET(ops,'c') || OPT_ISSET(ops,'a')) ?
3165 build_cur_dump(nam, dump, args + 1, OPT_ISSET(ops,'m'), map,
3166 (OPT_ISSET(ops,'c') ? 1 : 0) |
3167 (OPT_ISSET(ops,'a') ? 2 : 0)) :
3168 build_dump(nam, dump, args + 1, OPT_ISSET(ops,'U'), map, flags));
3169 unqueue_signals();
3170
3171 return ret;
3172 }
3173
3174 /* Load the header of a dump file. Returns NULL if the file isn't a
3175 * valid dump file. */
3176
3177 /**/
3178 static Wordcode
load_dump_header(char * nam,char * name,int err)3179 load_dump_header(char *nam, char *name, int err)
3180 {
3181 int fd, v = 1;
3182 wordcode buf[FD_PRELEN + 1];
3183
3184 if ((fd = open(name, O_RDONLY)) < 0) {
3185 if (err)
3186 zwarnnam(nam, "can't open zwc file: %s", name);
3187 return NULL;
3188 }
3189 if (read(fd, buf, (FD_PRELEN + 1) * sizeof(wordcode)) !=
3190 ((FD_PRELEN + 1) * sizeof(wordcode)) ||
3191 (v = (fdmagic(buf) != FD_MAGIC && fdmagic(buf) != FD_OMAGIC)) ||
3192 strcmp(fdversion(buf), ZSH_VERSION)) {
3193 if (err) {
3194 if (!v) {
3195 zwarnnam(nam, "zwc file has wrong version (zsh-%s): %s",
3196 fdversion(buf), name);
3197 } else
3198 zwarnnam(nam, "invalid zwc file: %s" , name);
3199 }
3200 close(fd);
3201 return NULL;
3202 } else {
3203 int len;
3204 Wordcode head;
3205
3206 if (fdmagic(buf) == FD_MAGIC) {
3207 len = fdheaderlen(buf) * sizeof(wordcode);
3208 head = (Wordcode) zhalloc(len);
3209 }
3210 else {
3211 int o = fdother(buf);
3212
3213 if (lseek(fd, o, 0) == -1 ||
3214 read(fd, buf, (FD_PRELEN + 1) * sizeof(wordcode)) !=
3215 ((FD_PRELEN + 1) * sizeof(wordcode))) {
3216 zwarnnam(nam, "invalid zwc file: %s" , name);
3217 close(fd);
3218 return NULL;
3219 }
3220 len = fdheaderlen(buf) * sizeof(wordcode);
3221 head = (Wordcode) zhalloc(len);
3222 }
3223 memcpy(head, buf, (FD_PRELEN + 1) * sizeof(wordcode));
3224
3225 len -= (FD_PRELEN + 1) * sizeof(wordcode);
3226 if (read(fd, head + (FD_PRELEN + 1), len) != len) {
3227 close(fd);
3228 zwarnnam(nam, "invalid zwc file: %s" , name);
3229 return NULL;
3230 }
3231 close(fd);
3232 return head;
3233 }
3234 }
3235
3236 /* Swap the bytes in a wordcode. */
3237
3238 static void
fdswap(Wordcode p,int n)3239 fdswap(Wordcode p, int n)
3240 {
3241 wordcode c;
3242
3243 for (; n--; p++) {
3244 c = *p;
3245 *p = (((c & 0xff) << 24) |
3246 ((c & 0xff00) << 8) |
3247 ((c & 0xff0000) >> 8) |
3248 ((c & 0xff000000) >> 24));
3249 }
3250 }
3251
3252 /* Write a dump file. */
3253
3254 static void
write_dump(int dfd,LinkList progs,int map,int hlen,int tlen)3255 write_dump(int dfd, LinkList progs, int map, int hlen, int tlen)
3256 {
3257 LinkNode node;
3258 WCFunc wcf;
3259 int other = 0, ohlen, tmp;
3260 wordcode pre[FD_PRELEN];
3261 char *tail, *n;
3262 struct fdhead head;
3263 Eprog prog;
3264
3265 if (map == 1)
3266 map = (tlen >= FD_MINMAP);
3267
3268 memset(pre, 0, sizeof(wordcode) * FD_PRELEN);
3269
3270 for (ohlen = hlen; ; hlen = ohlen) {
3271 fdmagic(pre) = (other ? FD_OMAGIC : FD_MAGIC);
3272 fdsetflags(pre, ((map ? FDF_MAP : 0) | other));
3273 fdsetother(pre, tlen);
3274 strcpy(fdversion(pre), ZSH_VERSION);
3275 write_loop(dfd, (char *)pre, FD_PRELEN * sizeof(wordcode));
3276
3277 for (node = firstnode(progs); node; incnode(node)) {
3278 wcf = (WCFunc) getdata(node);
3279 n = wcf->name;
3280 prog = wcf->prog;
3281 head.start = hlen;
3282 hlen += (prog->len - (prog->npats * sizeof(Patprog)) +
3283 sizeof(wordcode) - 1) / sizeof(wordcode);
3284 head.len = prog->len - (prog->npats * sizeof(Patprog));
3285 head.npats = prog->npats;
3286 head.strs = prog->strs - ((char *) prog->prog);
3287 head.hlen = (sizeof(struct fdhead) / sizeof(wordcode)) +
3288 (strlen(n) + sizeof(wordcode)) / sizeof(wordcode);
3289 if ((tail = strrchr(n, '/')))
3290 tail++;
3291 else
3292 tail = n;
3293 head.flags = fdhbldflags(wcf->flags, (tail - n));
3294 if (other)
3295 fdswap((Wordcode) &head, sizeof(head) / sizeof(wordcode));
3296 write_loop(dfd, (char *)&head, sizeof(head));
3297 tmp = strlen(n) + 1;
3298 write_loop(dfd, n, tmp);
3299 if ((tmp &= (sizeof(wordcode) - 1)))
3300 write_loop(dfd, (char *)&head, sizeof(wordcode) - tmp);
3301 }
3302 for (node = firstnode(progs); node; incnode(node)) {
3303 prog = ((WCFunc) getdata(node))->prog;
3304 tmp = (prog->len - (prog->npats * sizeof(Patprog)) +
3305 sizeof(wordcode) - 1) / sizeof(wordcode);
3306 if (other)
3307 fdswap(prog->prog, (((Wordcode) prog->strs) - prog->prog));
3308 write_loop(dfd, (char *)prog->prog, tmp * sizeof(wordcode));
3309 }
3310 if (other)
3311 break;
3312 other = FDF_OTHER;
3313 }
3314 }
3315
3316 /**/
3317 static int
build_dump(char * nam,char * dump,char ** files,int ali,int map,int flags)3318 build_dump(char *nam, char *dump, char **files, int ali, int map, int flags)
3319 {
3320 int dfd, fd, hlen, tlen, flen, ona = noaliases;
3321 LinkList progs;
3322 char *file;
3323 Eprog prog;
3324 WCFunc wcf;
3325
3326 if (!strsfx(FD_EXT, dump))
3327 dump = dyncat(dump, FD_EXT);
3328
3329 unlink(dump);
3330 if ((dfd = open(dump, O_WRONLY|O_CREAT, 0444)) < 0) {
3331 zwarnnam(nam, "can't write zwc file: %s", dump);
3332 return 1;
3333 }
3334 progs = newlinklist();
3335 noaliases = ali;
3336
3337 for (hlen = FD_PRELEN, tlen = 0; *files; files++) {
3338 struct stat st;
3339
3340 if (check_cond(*files, "k")) {
3341 flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_KSHLOAD;
3342 continue;
3343 } else if (check_cond(*files, "z")) {
3344 flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_ZSHLOAD;
3345 continue;
3346 }
3347 if ((fd = open(*files, O_RDONLY)) < 0 ||
3348 fstat(fd, &st) != 0 || !S_ISREG(st.st_mode) ||
3349 (flen = lseek(fd, 0, 2)) == -1) {
3350 if (fd >= 0)
3351 close(fd);
3352 close(dfd);
3353 zwarnnam(nam, "can't open file: %s", *files);
3354 noaliases = ona;
3355 unlink(dump);
3356 return 1;
3357 }
3358 file = (char *) zalloc(flen + 1);
3359 file[flen] = '\0';
3360 lseek(fd, 0, 0);
3361 if (read(fd, file, flen) != flen) {
3362 close(fd);
3363 close(dfd);
3364 zfree(file, flen);
3365 zwarnnam(nam, "can't read file: %s", *files);
3366 noaliases = ona;
3367 unlink(dump);
3368 return 1;
3369 }
3370 close(fd);
3371 file = metafy(file, flen, META_REALLOC);
3372
3373 if (!(prog = parse_string(file, 1)) || errflag) {
3374 errflag &= ~ERRFLAG_ERROR;
3375 close(dfd);
3376 zfree(file, flen);
3377 zwarnnam(nam, "can't read file: %s", *files);
3378 noaliases = ona;
3379 unlink(dump);
3380 return 1;
3381 }
3382 zfree(file, flen);
3383
3384 wcf = (WCFunc) zhalloc(sizeof(*wcf));
3385 wcf->name = *files;
3386 wcf->prog = prog;
3387 wcf->flags = ((prog->flags & EF_RUN) ? FDHF_KSHLOAD : flags);
3388 addlinknode(progs, wcf);
3389
3390 flen = (strlen(*files) + sizeof(wordcode)) / sizeof(wordcode);
3391 hlen += (sizeof(struct fdhead) / sizeof(wordcode)) + flen;
3392
3393 tlen += (prog->len - (prog->npats * sizeof(Patprog)) +
3394 sizeof(wordcode) - 1) / sizeof(wordcode);
3395 }
3396 noaliases = ona;
3397
3398 tlen = (tlen + hlen) * sizeof(wordcode);
3399
3400 write_dump(dfd, progs, map, hlen, tlen);
3401
3402 close(dfd);
3403
3404 return 0;
3405 }
3406
3407 static int
cur_add_func(char * nam,Shfunc shf,LinkList names,LinkList progs,int * hlen,int * tlen,int what)3408 cur_add_func(char *nam, Shfunc shf, LinkList names, LinkList progs,
3409 int *hlen, int *tlen, int what)
3410 {
3411 Eprog prog;
3412 WCFunc wcf;
3413
3414 if (shf->node.flags & PM_UNDEFINED) {
3415 int ona = noaliases;
3416
3417 if (!(what & 2)) {
3418 zwarnnam(nam, "function is not loaded: %s", shf->node.nam);
3419 return 1;
3420 }
3421 noaliases = (shf->node.flags & PM_UNALIASED);
3422 if (!(prog = getfpfunc(shf->node.nam, NULL, NULL, NULL, 0)) ||
3423 prog == &dummy_eprog) {
3424 noaliases = ona;
3425 zwarnnam(nam, "can't load function: %s", shf->node.nam);
3426 return 1;
3427 }
3428 if (prog->dump)
3429 prog = dupeprog(prog, 1);
3430 noaliases = ona;
3431 } else {
3432 if (!(what & 1)) {
3433 zwarnnam(nam, "function is already loaded: %s", shf->node.nam);
3434 return 1;
3435 }
3436 prog = dupeprog(shf->funcdef, 1);
3437 }
3438 wcf = (WCFunc) zhalloc(sizeof(*wcf));
3439 wcf->name = shf->node.nam;
3440 wcf->prog = prog;
3441 wcf->flags = ((prog->flags & EF_RUN) ? FDHF_KSHLOAD : FDHF_ZSHLOAD);
3442 addlinknode(progs, wcf);
3443 addlinknode(names, shf->node.nam);
3444
3445 *hlen += ((sizeof(struct fdhead) / sizeof(wordcode)) +
3446 ((strlen(shf->node.nam) + sizeof(wordcode)) / sizeof(wordcode)));
3447 *tlen += (prog->len - (prog->npats * sizeof(Patprog)) +
3448 sizeof(wordcode) - 1) / sizeof(wordcode);
3449
3450 return 0;
3451 }
3452
3453 /**/
3454 static int
build_cur_dump(char * nam,char * dump,char ** names,int match,int map,int what)3455 build_cur_dump(char *nam, char *dump, char **names, int match, int map,
3456 int what)
3457 {
3458 int dfd, hlen, tlen;
3459 LinkList progs, lnames;
3460 Shfunc shf = NULL;
3461
3462 if (!strsfx(FD_EXT, dump))
3463 dump = dyncat(dump, FD_EXT);
3464
3465 unlink(dump);
3466 if ((dfd = open(dump, O_WRONLY|O_CREAT, 0444)) < 0) {
3467 zwarnnam(nam, "can't write zwc file: %s", dump);
3468 return 1;
3469 }
3470 progs = newlinklist();
3471 lnames = newlinklist();
3472
3473 hlen = FD_PRELEN;
3474 tlen = 0;
3475
3476 if (!*names) {
3477 int i;
3478 HashNode hn;
3479
3480 for (i = 0; i < shfunctab->hsize; i++)
3481 for (hn = shfunctab->nodes[i]; hn; hn = hn->next)
3482 if (cur_add_func(nam, (Shfunc) hn, lnames, progs,
3483 &hlen, &tlen, what)) {
3484 errflag &= ~ERRFLAG_ERROR;
3485 close(dfd);
3486 unlink(dump);
3487 return 1;
3488 }
3489 } else if (match) {
3490 char *pat;
3491 Patprog pprog;
3492 int i;
3493 HashNode hn;
3494
3495 for (; *names; names++) {
3496 tokenize(pat = dupstring(*names));
3497 /* Signal-safe here, caller queues signals */
3498 if (!(pprog = patcompile(pat, PAT_STATIC, NULL))) {
3499 zwarnnam(nam, "bad pattern: %s", *names);
3500 close(dfd);
3501 unlink(dump);
3502 return 1;
3503 }
3504 for (i = 0; i < shfunctab->hsize; i++)
3505 for (hn = shfunctab->nodes[i]; hn; hn = hn->next)
3506 if (!linknodebydatum(lnames, hn->nam) &&
3507 pattry(pprog, hn->nam) &&
3508 cur_add_func(nam, (Shfunc) hn, lnames, progs,
3509 &hlen, &tlen, what)) {
3510 errflag &= ~ERRFLAG_ERROR;
3511 close(dfd);
3512 unlink(dump);
3513 return 1;
3514 }
3515 }
3516 } else {
3517 for (; *names; names++) {
3518 if (errflag ||
3519 !(shf = (Shfunc) shfunctab->getnode(shfunctab, *names))) {
3520 zwarnnam(nam, "unknown function: %s", *names);
3521 errflag &= ~ERRFLAG_ERROR;
3522 close(dfd);
3523 unlink(dump);
3524 return 1;
3525 }
3526 if (cur_add_func(nam, shf, lnames, progs, &hlen, &tlen, what)) {
3527 errflag &= ~ERRFLAG_ERROR;
3528 close(dfd);
3529 unlink(dump);
3530 return 1;
3531 }
3532 }
3533 }
3534 if (empty(progs)) {
3535 zwarnnam(nam, "no functions");
3536 errflag &= ~ERRFLAG_ERROR;
3537 close(dfd);
3538 unlink(dump);
3539 return 1;
3540 }
3541 tlen = (tlen + hlen) * sizeof(wordcode);
3542
3543 write_dump(dfd, progs, map, hlen, tlen);
3544
3545 close(dfd);
3546
3547 return 0;
3548 }
3549
3550 /**/
3551 #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
3552
3553 #include <sys/mman.h>
3554
3555 /**/
3556 #if defined(MAP_SHARED) && defined(PROT_READ)
3557
3558 /**/
3559 #define USE_MMAP 1
3560
3561 /**/
3562 #endif
3563 /**/
3564 #endif
3565
3566 /**/
3567 #ifdef USE_MMAP
3568
3569 /* List of dump files mapped. */
3570
3571 static FuncDump dumps;
3572
3573 /**/
3574 static int
zwcstat(char * filename,struct stat * buf)3575 zwcstat(char *filename, struct stat *buf)
3576 {
3577 if (stat(filename, buf)) {
3578 #ifdef HAVE_FSTAT
3579 FuncDump f;
3580
3581 for (f = dumps; f; f = f->next) {
3582 if (!strncmp(filename, f->filename, strlen(f->filename)) &&
3583 !fstat(f->fd, buf))
3584 return 0;
3585 }
3586 #endif
3587 return 1;
3588 } else return 0;
3589 }
3590
3591 /* Load a dump file (i.e. map it). */
3592
3593 static void
load_dump_file(char * dump,struct stat * sbuf,int other,int len)3594 load_dump_file(char *dump, struct stat *sbuf, int other, int len)
3595 {
3596 FuncDump d;
3597 Wordcode addr;
3598 int fd, off, mlen;
3599
3600 if (other) {
3601 static size_t pgsz = 0;
3602
3603 if (!pgsz) {
3604
3605 #ifdef _SC_PAGESIZE
3606 pgsz = sysconf(_SC_PAGESIZE); /* SVR4 */
3607 #else
3608 # ifdef _SC_PAGE_SIZE
3609 pgsz = sysconf(_SC_PAGE_SIZE); /* HPUX */
3610 # else
3611 pgsz = getpagesize();
3612 # endif
3613 #endif
3614
3615 pgsz--;
3616 }
3617 off = len & ~pgsz;
3618 mlen = len + (len - off);
3619 } else {
3620 off = 0;
3621 mlen = len;
3622 }
3623 if ((fd = open(dump, O_RDONLY)) < 0)
3624 return;
3625
3626 fd = movefd(fd);
3627 if (fd == -1)
3628 return;
3629
3630 if ((addr = (Wordcode) mmap(NULL, mlen, PROT_READ, MAP_SHARED, fd, off)) ==
3631 ((Wordcode) -1)) {
3632 close(fd);
3633 return;
3634 }
3635 d = (FuncDump) zalloc(sizeof(*d));
3636 d->next = dumps;
3637 dumps = d;
3638 d->dev = sbuf->st_dev;
3639 d->ino = sbuf->st_ino;
3640 d->fd = fd;
3641 #ifdef FD_CLOEXEC
3642 fcntl(fd, F_SETFD, FD_CLOEXEC);
3643 #endif
3644 d->map = addr + (other ? (len - off) / sizeof(wordcode) : 0);
3645 d->addr = addr;
3646 d->len = len;
3647 d->count = 0;
3648 d->filename = ztrdup(dump);
3649 }
3650
3651 #else
3652
3653 #define zwcstat(f, b) (!!stat(f, b))
3654
3655 /**/
3656 #endif
3657
3658 /* Try to load a function from one of the possible wordcode files for it.
3659 * The first argument is a element of $fpath, the second one is the name
3660 * of the function searched and the last one is the possible name for the
3661 * uncompiled function file (<path>/<func>). */
3662
3663 /**/
3664 Eprog
try_dump_file(char * path,char * name,char * file,int * ksh,int test_only)3665 try_dump_file(char *path, char *name, char *file, int *ksh, int test_only)
3666 {
3667 Eprog prog;
3668 struct stat std, stc, stn;
3669 int rd, rc, rn;
3670 char *dig, *wc;
3671
3672 if (strsfx(FD_EXT, path)) {
3673 queue_signals();
3674 prog = check_dump_file(path, NULL, name, ksh, test_only);
3675 unqueue_signals();
3676 return prog;
3677 }
3678 dig = dyncat(path, FD_EXT);
3679 wc = dyncat(file, FD_EXT);
3680
3681 rd = zwcstat(dig, &std);
3682 rc = stat(wc, &stc);
3683 rn = stat(file, &stn);
3684
3685 /* See if there is a digest file for the directory, it is younger than
3686 * both the uncompiled function file and its compiled version (or they
3687 * don't exist) and the digest file contains the definition for the
3688 * function. */
3689 queue_signals();
3690 if (!rd &&
3691 (rc || std.st_mtime >= stc.st_mtime) &&
3692 (rn || std.st_mtime >= stn.st_mtime) &&
3693 (prog = check_dump_file(dig, &std, name, ksh, test_only))) {
3694 unqueue_signals();
3695 return prog;
3696 }
3697 /* No digest file. Now look for the per-function compiled file. */
3698 if (!rc &&
3699 (rn || stc.st_mtime >= stn.st_mtime) &&
3700 (prog = check_dump_file(wc, &stc, name, ksh, test_only))) {
3701 unqueue_signals();
3702 return prog;
3703 }
3704 /* No compiled file for the function. The caller (getfpfunc() will
3705 * check if the directory contains the uncompiled file for it. */
3706 unqueue_signals();
3707 return NULL;
3708 }
3709
3710 /* Almost the same, but for sourced files. */
3711
3712 /**/
3713 Eprog
try_source_file(char * file)3714 try_source_file(char *file)
3715 {
3716 Eprog prog;
3717 struct stat stc, stn;
3718 int rc, rn;
3719 char *wc, *tail;
3720
3721 if ((tail = strrchr(file, '/')))
3722 tail++;
3723 else
3724 tail = file;
3725
3726 if (strsfx(FD_EXT, file)) {
3727 queue_signals();
3728 prog = check_dump_file(file, NULL, tail, NULL, 0);
3729 unqueue_signals();
3730 return prog;
3731 }
3732 wc = dyncat(file, FD_EXT);
3733
3734 rc = stat(wc, &stc);
3735 rn = stat(file, &stn);
3736
3737 queue_signals();
3738 if (!rc && (rn || stc.st_mtime >= stn.st_mtime) &&
3739 (prog = check_dump_file(wc, &stc, tail, NULL, 0))) {
3740 unqueue_signals();
3741 return prog;
3742 }
3743 unqueue_signals();
3744 return NULL;
3745 }
3746
3747 /* See if `file' names a wordcode dump file and that contains the
3748 * definition for the function `name'. If so, return an eprog for it. */
3749
3750 /**/
3751 static Eprog
check_dump_file(char * file,struct stat * sbuf,char * name,int * ksh,int test_only)3752 check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh,
3753 int test_only)
3754 {
3755 int isrec = 0;
3756 Wordcode d;
3757 FDHead h;
3758 FuncDump f;
3759 struct stat lsbuf;
3760
3761 if (!sbuf) {
3762 if (zwcstat(file, &lsbuf))
3763 return NULL;
3764 sbuf = &lsbuf;
3765 }
3766
3767 #ifdef USE_MMAP
3768
3769 rec:
3770
3771 #endif
3772
3773 d = NULL;
3774
3775 #ifdef USE_MMAP
3776
3777 for (f = dumps; f; f = f->next)
3778 if (f->dev == sbuf->st_dev && f->ino == sbuf->st_ino) {
3779 d = f->map;
3780 break;
3781 }
3782
3783 #else
3784
3785 f = NULL;
3786
3787 #endif
3788
3789 if (!f && (isrec || !(d = load_dump_header(NULL, file, 0))))
3790 return NULL;
3791
3792 if ((h = dump_find_func(d, name))) {
3793 /* Found the name. If the file is already mapped, return the eprog,
3794 * otherwise map it and just go up. */
3795 if (test_only)
3796 {
3797 /* This is all we need. Just return dummy. */
3798 return &dummy_eprog;
3799 }
3800
3801 #ifdef USE_MMAP
3802
3803 if (f) {
3804 Eprog prog = (Eprog) zalloc(sizeof(*prog));
3805 Patprog *pp;
3806 int np;
3807
3808 prog->flags = EF_MAP;
3809 prog->len = h->len;
3810 prog->npats = np = h->npats;
3811 prog->nref = 1; /* allocated from permanent storage */
3812 prog->pats = pp = (Patprog *) zalloc(np * sizeof(Patprog));
3813 prog->prog = f->map + h->start;
3814 prog->strs = ((char *) prog->prog) + h->strs;
3815 prog->shf = NULL;
3816 prog->dump = f;
3817
3818 incrdumpcount(f);
3819
3820 while (np--)
3821 *pp++ = dummy_patprog1;
3822
3823 if (ksh)
3824 *ksh = ((fdhflags(h) & FDHF_KSHLOAD) ? 2 :
3825 ((fdhflags(h) & FDHF_ZSHLOAD) ? 0 : 1));
3826
3827 return prog;
3828 } else if (fdflags(d) & FDF_MAP) {
3829 load_dump_file(file, sbuf, (fdflags(d) & FDF_OTHER), fdother(d));
3830 isrec = 1;
3831 goto rec;
3832 } else
3833
3834 #endif
3835
3836 {
3837 Eprog prog;
3838 Patprog *pp;
3839 int np, fd, po = h->npats * sizeof(Patprog);
3840
3841 if ((fd = open(file, O_RDONLY)) < 0 ||
3842 lseek(fd, ((h->start * sizeof(wordcode)) +
3843 ((fdflags(d) & FDF_OTHER) ? fdother(d) : 0)), 0) < 0) {
3844 if (fd >= 0)
3845 close(fd);
3846 return NULL;
3847 }
3848 d = (Wordcode) zalloc(h->len + po);
3849
3850 if (read(fd, ((char *) d) + po, h->len) != (int)h->len) {
3851 close(fd);
3852 zfree(d, h->len);
3853
3854 return NULL;
3855 }
3856 close(fd);
3857
3858 prog = (Eprog) zalloc(sizeof(*prog));
3859
3860 prog->flags = EF_REAL;
3861 prog->len = h->len + po;
3862 prog->npats = np = h->npats;
3863 prog->nref = 1; /* allocated from permanent storage */
3864 prog->pats = pp = (Patprog *) d;
3865 prog->prog = (Wordcode) (((char *) d) + po);
3866 prog->strs = ((char *) prog->prog) + h->strs;
3867 prog->shf = NULL;
3868 prog->dump = f;
3869
3870 while (np--)
3871 *pp++ = dummy_patprog1;
3872
3873 if (ksh)
3874 *ksh = ((fdhflags(h) & FDHF_KSHLOAD) ? 2 :
3875 ((fdhflags(h) & FDHF_ZSHLOAD) ? 0 : 1));
3876
3877 return prog;
3878 }
3879 }
3880 return NULL;
3881 }
3882
3883 #ifdef USE_MMAP
3884
3885 /* Increment the reference counter for a dump file. */
3886
3887 /**/
3888 void
incrdumpcount(FuncDump f)3889 incrdumpcount(FuncDump f)
3890 {
3891 f->count++;
3892 }
3893
3894 /**/
3895 static void
freedump(FuncDump f)3896 freedump(FuncDump f)
3897 {
3898 munmap((void *) f->addr, f->len);
3899 zclose(f->fd);
3900 zsfree(f->filename);
3901 zfree(f, sizeof(*f));
3902 }
3903
3904 /* Decrement the reference counter for a dump file. If zero, unmap the file. */
3905
3906 /**/
3907 void
decrdumpcount(FuncDump f)3908 decrdumpcount(FuncDump f)
3909 {
3910 f->count--;
3911 if (!f->count) {
3912 FuncDump p, q;
3913
3914 for (q = NULL, p = dumps; p && p != f; q = p, p = p->next);
3915 if (p) {
3916 if (q)
3917 q->next = p->next;
3918 else
3919 dumps = p->next;
3920 freedump(f);
3921 }
3922 }
3923 }
3924
3925 #ifndef FD_CLOEXEC
3926 /**/
3927 mod_export void
closedumps(void)3928 closedumps(void)
3929 {
3930 while (dumps) {
3931 FuncDump p = dumps->next;
3932 freedump(dumps);
3933 dumps = p;
3934 }
3935 }
3936 #endif
3937
3938 #else
3939
3940 void
incrdumpcount(FuncDump f)3941 incrdumpcount(FuncDump f)
3942 {
3943 }
3944
3945 void
decrdumpcount(FuncDump f)3946 decrdumpcount(FuncDump f)
3947 {
3948 }
3949
3950 #ifndef FD_CLOEXEC
3951 /**/
3952 mod_export void
closedumps(void)3953 closedumps(void)
3954 {
3955 }
3956 #endif
3957
3958 #endif
3959
3960 /**/
3961 int
dump_autoload(char * nam,char * file,int on,Options ops,int func)3962 dump_autoload(char *nam, char *file, int on, Options ops, int func)
3963 {
3964 Wordcode h;
3965 FDHead n, e;
3966 Shfunc shf;
3967 int ret = 0;
3968
3969 if (!strsfx(FD_EXT, file))
3970 file = dyncat(file, FD_EXT);
3971
3972 if (!(h = load_dump_header(nam, file, 1)))
3973 return 1;
3974
3975 for (n = firstfdhead(h), e = (FDHead) (h + fdheaderlen(h)); n < e;
3976 n = nextfdhead(n)) {
3977 shf = (Shfunc) zshcalloc(sizeof *shf);
3978 shf->node.flags = on;
3979 shf->funcdef = mkautofn(shf);
3980 shf->sticky = NULL;
3981 shfunctab->addnode(shfunctab, ztrdup(fdname(n) + fdhtail(n)), shf);
3982 if (OPT_ISSET(ops,'X') && eval_autoload(shf, shf->node.nam, ops, func))
3983 ret = 1;
3984 }
3985 return ret;
3986 }
3987