GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/csh/parse.c Lines: 0 285 0.0 %
Date: 2017-11-07 Branches: 0 241 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: parse.c,v 1.12 2015/12/26 13:48:38 mestre Exp $	*/
2
/*	$NetBSD: parse.c,v 1.6 1995/03/21 09:03:10 cgd Exp $	*/
3
4
/*-
5
 * Copyright (c) 1980, 1991, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/types.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <stdarg.h>
37
38
#include "csh.h"
39
#include "extern.h"
40
41
static void	 asyntax(struct wordent *, struct wordent *);
42
static void	 asyn0(struct wordent *, struct wordent *);
43
static void	 asyn3(struct wordent *, struct wordent *);
44
static struct wordent
45
		*freenod(struct wordent *, struct wordent *);
46
static struct command
47
		*syn0(struct wordent *, struct wordent *, int);
48
static struct command
49
		*syn1(struct wordent *, struct wordent *, int);
50
static struct command
51
		*syn1a(struct wordent *, struct wordent *, int);
52
static struct command
53
		*syn1b(struct wordent *, struct wordent *, int);
54
static struct command
55
		*syn2(struct wordent *, struct wordent *, int);
56
static struct command
57
		*syn3(struct wordent *, struct wordent *, int);
58
59
#define ALEFT	21		/* max of 20 alias expansions	 */
60
#define HLEFT	11		/* max of 10 history expansions	 */
61
/*
62
 * Perform aliasing on the word list lex
63
 * Do a (very rudimentary) parse to separate into commands.
64
 * If word 0 of a command has an alias, do it.
65
 * Repeat a maximum of 20 times.
66
 */
67
static int aleft;
68
extern int hleft;
69
void
70
alias(struct wordent *lex)
71
{
72
    jmp_buf osetexit;
73
74
    aleft = ALEFT;
75
    hleft = HLEFT;
76
    getexit(osetexit);
77
    (void) setexit();
78
    if (haderr) {
79
	resexit(osetexit);
80
	reset();
81
    }
82
    if (--aleft == 0)
83
	stderror(ERR_ALIASLOOP);
84
    asyntax(lex->next, lex);
85
    resexit(osetexit);
86
}
87
88
static void
89
asyntax(struct wordent *p1, struct wordent *p2)
90
{
91
    while (p1 != p2)
92
	if (any(";&\n", p1->word[0]))
93
	    p1 = p1->next;
94
	else {
95
	    asyn0(p1, p2);
96
	    return;
97
	}
98
}
99
100
static void
101
asyn0(struct wordent *p1, struct wordent *p2)
102
{
103
    struct wordent *p;
104
    int l = 0;
105
106
    for (p = p1; p != p2; p = p->next)
107
	switch (p->word[0]) {
108
109
	case '(':
110
	    l++;
111
	    continue;
112
113
	case ')':
114
	    l--;
115
	    if (l < 0)
116
		stderror(ERR_TOOMANYRP);
117
	    continue;
118
119
	case '>':
120
	    if (p->next != p2 && eq(p->next->word, STRand))
121
		p = p->next;
122
	    continue;
123
124
	case '&':
125
	case '|':
126
	case ';':
127
	case '\n':
128
	    if (l != 0)
129
		continue;
130
	    asyn3(p1, p);
131
	    asyntax(p->next, p2);
132
	    return;
133
	}
134
    if (l == 0)
135
	asyn3(p1, p2);
136
}
137
138
static void
139
asyn3(struct wordent *p1, struct wordent *p2)
140
{
141
    struct varent *ap;
142
    struct wordent alout;
143
    bool redid;
144
145
    if (p1 == p2)
146
	return;
147
    if (p1->word[0] == '(') {
148
	for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
149
	    if (p2 == p1)
150
		return;
151
	if (p2 == p1->next)
152
	    return;
153
	asyn0(p1->next, p2);
154
	return;
155
    }
156
    ap = adrof1(p1->word, &aliases);
157
    if (ap == 0)
158
	return;
159
    alhistp = p1->prev;
160
    alhistt = p2;
161
    alvec = ap->vec;
162
    redid = lex(&alout);
163
    alhistp = alhistt = 0;
164
    alvec = 0;
165
    if (seterr) {
166
	freelex(&alout);
167
	stderror(ERR_OLD);
168
    }
169
    if (p1->word[0] && eq(p1->word, alout.next->word)) {
170
	Char   *cp = alout.next->word;
171
172
	alout.next->word = Strspl(STRQNULL, cp);
173
	free(cp);
174
    }
175
    p1 = freenod(p1, redid ? p2 : p1->next);
176
    if (alout.next != &alout) {
177
	p1->next->prev = alout.prev->prev;
178
	alout.prev->prev->next = p1->next;
179
	alout.next->prev = p1;
180
	p1->next = alout.next;
181
	free(alout.prev->word);
182
	free((alout.prev));
183
    }
184
    reset();			/* throw! */
185
}
186
187
static struct wordent *
188
freenod(struct wordent *p1, struct wordent *p2)
189
{
190
    struct wordent *retp = p1->prev;
191
192
    while (p1 != p2) {
193
	free(p1->word);
194
	p1 = p1->next;
195
	free((p1->prev));
196
    }
197
    retp->next = p2;
198
    p2->prev = retp;
199
    return (retp);
200
}
201
202
#define	PHERE	1
203
#define	PIN	2
204
#define	POUT	4
205
#define	PERR	8
206
207
/*
208
 * syntax
209
 *	empty
210
 *	syn0
211
 */
212
struct command *
213
syntax(struct wordent *p1, struct wordent *p2, int flags)
214
{
215
216
    while (p1 != p2)
217
	if (any(";&\n", p1->word[0]))
218
	    p1 = p1->next;
219
	else
220
	    return (syn0(p1, p2, flags));
221
    return (0);
222
}
223
224
/*
225
 * syn0
226
 *	syn1
227
 *	syn1 & syntax
228
 */
229
static struct command *
230
syn0(struct wordent *p1, struct wordent *p2, int flags)
231
{
232
    struct wordent *p;
233
    struct command *t, *t1;
234
    int     l;
235
236
    l = 0;
237
    for (p = p1; p != p2; p = p->next)
238
	switch (p->word[0]) {
239
240
	case '(':
241
	    l++;
242
	    continue;
243
244
	case ')':
245
	    l--;
246
	    if (l < 0)
247
		seterror(ERR_TOOMANYRP);
248
	    continue;
249
250
	case '|':
251
	    if (p->word[1] == '|')
252
		continue;
253
	    /* fall into ... */
254
255
	case '>':
256
	    if (p->next != p2 && eq(p->next->word, STRand))
257
		p = p->next;
258
	    continue;
259
260
	case '&':
261
	    if (l != 0)
262
		break;
263
	    if (p->word[1] == '&')
264
		continue;
265
	    t1 = syn1(p1, p, flags);
266
	    if (t1->t_dtyp == NODE_LIST ||
267
		t1->t_dtyp == NODE_AND ||
268
		t1->t_dtyp == NODE_OR) {
269
		t = xcalloc(1, sizeof(*t));
270
		t->t_dtyp = NODE_PAREN;
271
		t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
272
		t->t_dspr = t1;
273
		t1 = t;
274
	    }
275
	    else
276
		t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
277
	    t = xcalloc(1, sizeof(*t));
278
	    t->t_dtyp = NODE_LIST;
279
	    t->t_dflg = 0;
280
	    t->t_dcar = t1;
281
	    t->t_dcdr = syntax(p, p2, flags);
282
	    return (t);
283
	}
284
    if (l == 0)
285
	return (syn1(p1, p2, flags));
286
    seterror(ERR_TOOMANYLP);
287
    return (0);
288
}
289
290
/*
291
 * syn1
292
 *	syn1a
293
 *	syn1a ; syntax
294
 */
295
static struct command *
296
syn1(struct wordent *p1, struct wordent *p2, int flags)
297
{
298
    struct wordent *p;
299
    struct command *t;
300
    int     l;
301
302
    l = 0;
303
    for (p = p1; p != p2; p = p->next)
304
	switch (p->word[0]) {
305
306
	case '(':
307
	    l++;
308
	    continue;
309
310
	case ')':
311
	    l--;
312
	    continue;
313
314
	case ';':
315
	case '\n':
316
	    if (l != 0)
317
		break;
318
	    t = xcalloc(1, sizeof(*t));
319
	    t->t_dtyp = NODE_LIST;
320
	    t->t_dcar = syn1a(p1, p, flags);
321
	    t->t_dcdr = syntax(p->next, p2, flags);
322
	    if (t->t_dcdr == 0)
323
		t->t_dcdr = t->t_dcar, t->t_dcar = 0;
324
	    return (t);
325
	}
326
    return (syn1a(p1, p2, flags));
327
}
328
329
/*
330
 * syn1a
331
 *	syn1b
332
 *	syn1b || syn1a
333
 */
334
static struct command *
335
syn1a(struct wordent *p1, struct wordent *p2, int flags)
336
{
337
    struct wordent *p;
338
    struct command *t;
339
    int l = 0;
340
341
    for (p = p1; p != p2; p = p->next)
342
	switch (p->word[0]) {
343
344
	case '(':
345
	    l++;
346
	    continue;
347
348
	case ')':
349
	    l--;
350
	    continue;
351
352
	case '|':
353
	    if (p->word[1] != '|')
354
		continue;
355
	    if (l == 0) {
356
		t = xcalloc(1, sizeof(*t));
357
		t->t_dtyp = NODE_OR;
358
		t->t_dcar = syn1b(p1, p, flags);
359
		t->t_dcdr = syn1a(p->next, p2, flags);
360
		t->t_dflg = 0;
361
		return (t);
362
	    }
363
	    continue;
364
	}
365
    return (syn1b(p1, p2, flags));
366
}
367
368
/*
369
 * syn1b
370
 *	syn2
371
 *	syn2 && syn1b
372
 */
373
static struct command *
374
syn1b(struct wordent *p1, struct wordent *p2, int flags)
375
{
376
    struct wordent *p;
377
    struct command *t;
378
    int l = 0;
379
380
    for (p = p1; p != p2; p = p->next)
381
	switch (p->word[0]) {
382
383
	case '(':
384
	    l++;
385
	    continue;
386
387
	case ')':
388
	    l--;
389
	    continue;
390
391
	case '&':
392
	    if (p->word[1] == '&' && l == 0) {
393
		t = xcalloc(1, sizeof(*t));
394
		t->t_dtyp = NODE_AND;
395
		t->t_dcar = syn2(p1, p, flags);
396
		t->t_dcdr = syn1b(p->next, p2, flags);
397
		t->t_dflg = 0;
398
		return (t);
399
	    }
400
	    continue;
401
	}
402
    return (syn2(p1, p2, flags));
403
}
404
405
/*
406
 * syn2
407
 *	syn3
408
 *	syn3 | syn2
409
 *	syn3 |& syn2
410
 */
411
static struct command *
412
syn2(struct wordent *p1, struct wordent *p2, int flags)
413
{
414
    struct wordent *p, *pn;
415
    struct command *t;
416
    int l = 0;
417
    int     f;
418
419
    for (p = p1; p != p2; p = p->next)
420
	switch (p->word[0]) {
421
422
	case '(':
423
	    l++;
424
	    continue;
425
426
	case ')':
427
	    l--;
428
	    continue;
429
430
	case '|':
431
	    if (l != 0)
432
		continue;
433
	    t = xcalloc(1, sizeof(*t));
434
	    f = flags | POUT;
435
	    pn = p->next;
436
	    if (pn != p2 && pn->word[0] == '&') {
437
		f |= PERR;
438
		t->t_dflg |= F_STDERR;
439
	    }
440
	    t->t_dtyp = NODE_PIPE;
441
	    t->t_dcar = syn3(p1, p, f);
442
	    if (pn != p2 && pn->word[0] == '&')
443
		p = pn;
444
	    t->t_dcdr = syn2(p->next, p2, flags | PIN);
445
	    return (t);
446
	}
447
    return (syn3(p1, p2, flags));
448
}
449
450
static char RELPAR[] = {'<', '>', '(', ')', '\0'};
451
452
/*
453
 * syn3
454
 *	( syn0 ) [ < in  ] [ > out ]
455
 *	word word* [ < in ] [ > out ]
456
 *	KEYWORD ( word* ) word* [ < in ] [ > out ]
457
 *
458
 *	KEYWORD = (@ exit foreach if set switch test while)
459
 */
460
static struct command *
461
syn3(struct wordent *p1, struct wordent *p2, int flags)
462
{
463
    struct wordent *p;
464
    struct wordent *lp, *rp;
465
    struct command *t;
466
    int l;
467
    Char  **av;
468
    int     n, c;
469
    bool    specp = 0;
470
471
    if (p1 != p2) {
472
	p = p1;
473
again:
474
	switch (srchx(p->word)) {
475
476
	case T_ELSE:
477
	    p = p->next;
478
	    if (p != p2)
479
		goto again;
480
	    break;
481
482
	case T_EXIT:
483
	case T_FOREACH:
484
	case T_IF:
485
	case T_LET:
486
	case T_SET:
487
	case T_SWITCH:
488
	case T_WHILE:
489
	    specp = 1;
490
	    break;
491
	}
492
    }
493
    n = 0;
494
    l = 0;
495
    for (p = p1; p != p2; p = p->next)
496
	switch (p->word[0]) {
497
498
	case '(':
499
	    if (specp)
500
		n++;
501
	    l++;
502
	    continue;
503
504
	case ')':
505
	    if (specp)
506
		n++;
507
	    l--;
508
	    continue;
509
510
	case '>':
511
	case '<':
512
	    if (l != 0) {
513
		if (specp)
514
		    n++;
515
		continue;
516
	    }
517
	    if (p->next == p2)
518
		continue;
519
	    if (any(RELPAR, p->next->word[0]))
520
		continue;
521
	    n--;
522
	    continue;
523
524
	default:
525
	    if (!specp && l != 0)
526
		continue;
527
	    n++;
528
	    continue;
529
	}
530
    if (n < 0)
531
	n = 0;
532
    t = xcalloc(1, sizeof(*t));
533
    av = xcalloc((size_t) (n + 1), sizeof(Char **));
534
    t->t_dcom = av;
535
    n = 0;
536
    if (p2->word[0] == ')')
537
	t->t_dflg = F_NOFORK;
538
    lp = 0;
539
    rp = 0;
540
    l = 0;
541
    for (p = p1; p != p2; p = p->next) {
542
	c = p->word[0];
543
	switch (c) {
544
545
	case '(':
546
	    if (l == 0) {
547
		if (lp != 0 && !specp)
548
		    seterror(ERR_BADPLP);
549
		lp = p->next;
550
	    }
551
	    l++;
552
	    goto savep;
553
554
	case ')':
555
	    l--;
556
	    if (l == 0)
557
		rp = p;
558
	    goto savep;
559
560
	case '>':
561
	    if (l != 0)
562
		goto savep;
563
	    if (p->word[1] == '>')
564
		t->t_dflg |= F_APPEND;
565
	    if (p->next != p2 && eq(p->next->word, STRand)) {
566
		t->t_dflg |= F_STDERR, p = p->next;
567
		if (flags & (POUT | PERR)) {
568
		    seterror(ERR_OUTRED);
569
		    continue;
570
		}
571
	    }
572
	    if (p->next != p2 && eq(p->next->word, STRbang))
573
		t->t_dflg |= F_OVERWRITE, p = p->next;
574
	    if (p->next == p2) {
575
		seterror(ERR_MISRED);
576
		continue;
577
	    }
578
	    p = p->next;
579
	    if (any(RELPAR, p->word[0])) {
580
		seterror(ERR_MISRED);
581
		continue;
582
	    }
583
	    if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
584
		seterror(ERR_OUTRED);
585
	    else
586
		t->t_drit = Strsave(p->word);
587
	    continue;
588
589
	case '<':
590
	    if (l != 0)
591
		goto savep;
592
	    if (p->word[1] == '<')
593
		t->t_dflg |= F_READ;
594
	    if (p->next == p2) {
595
		seterror(ERR_MISRED);
596
		continue;
597
	    }
598
	    p = p->next;
599
	    if (any(RELPAR, p->word[0])) {
600
		seterror(ERR_MISRED);
601
		continue;
602
	    }
603
	    if ((flags & PHERE) && (t->t_dflg & F_READ))
604
		seterror(ERR_REDPAR);
605
	    else if ((flags & PIN) || t->t_dlef)
606
		seterror(ERR_INRED);
607
	    else
608
		t->t_dlef = Strsave(p->word);
609
	    continue;
610
611
    savep:
612
	    if (!specp)
613
		continue;
614
	default:
615
	    if (l != 0 && !specp)
616
		continue;
617
	    if (seterr == 0)
618
		av[n] = Strsave(p->word);
619
	    n++;
620
	    continue;
621
	}
622
    }
623
    if (lp != 0 && !specp) {
624
	if (n != 0)
625
	    seterror(ERR_BADPLPS);
626
	t->t_dtyp = NODE_PAREN;
627
	t->t_dspr = syn0(lp, rp, PHERE);
628
    }
629
    else {
630
	if (n == 0)
631
	    seterror(ERR_NULLCOM);
632
	t->t_dtyp = NODE_COMMAND;
633
    }
634
    return (t);
635
}
636
637
void
638
freesyn(struct command *t)
639
{
640
    Char **v;
641
642
    if (t == 0)
643
	return;
644
    switch (t->t_dtyp) {
645
646
    case NODE_COMMAND:
647
	for (v = t->t_dcom; *v; v++)
648
	    free(* v);
649
	free((t->t_dcom));
650
	free(t->t_dlef);
651
	free(t->t_drit);
652
	break;
653
    case NODE_PAREN:
654
	freesyn(t->t_dspr);
655
	free(t->t_dlef);
656
	free(t->t_drit);
657
	break;
658
659
    case NODE_AND:
660
    case NODE_OR:
661
    case NODE_PIPE:
662
    case NODE_LIST:
663
	freesyn(t->t_dcar), freesyn(t->t_dcdr);
664
	break;
665
    }
666
    free(t);
667
}