Deleted Added
full compact
parser.c (83675) parser.c (90111)
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 25 unchanged lines hidden (view full) ---

34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38#if 0
39static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
40#endif
41static const char rcsid[] =
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 25 unchanged lines hidden (view full) ---

34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38#if 0
39static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
40#endif
41static const char rcsid[] =
42 "$FreeBSD: head/bin/sh/parser.c 83675 2001-09-19 20:07:47Z tegge $";
42 "$FreeBSD: head/bin/sh/parser.c 90111 2002-02-02 06:50:57Z imp $";
43#endif /* not lint */
44
45#include <stdlib.h>
46
47#include "shell.h"
48#include "parser.h"
49#include "nodes.h"
50#include "expand.h" /* defines rmescapes() */

--- 52 unchanged lines hidden (view full) ---

103
104#define GDB_HACK 1 /* avoid local declarations which gdb can't handle */
105#ifdef GDB_HACK
106static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'};
107static const char types[] = "}-+?=";
108#endif
109
110
43#endif /* not lint */
44
45#include <stdlib.h>
46
47#include "shell.h"
48#include "parser.h"
49#include "nodes.h"
50#include "expand.h" /* defines rmescapes() */

--- 52 unchanged lines hidden (view full) ---

103
104#define GDB_HACK 1 /* avoid local declarations which gdb can't handle */
105#ifdef GDB_HACK
106static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'};
107static const char types[] = "}-+?=";
108#endif
109
110
111STATIC union node *list __P((int));
112STATIC union node *andor __P((void));
113STATIC union node *pipeline __P((void));
114STATIC union node *command __P((void));
115STATIC union node *simplecmd __P((union node **, union node *));
116STATIC union node *makename __P((void));
117STATIC void parsefname __P((void));
118STATIC void parseheredoc __P((void));
119STATIC int peektoken __P((void));
120STATIC int readtoken __P((void));
121STATIC int xxreadtoken __P((void));
122STATIC int readtoken1 __P((int, char const *, char *, int));
123STATIC int noexpand __P((char *));
124STATIC void synexpect __P((int));
125STATIC void synerror __P((char *));
126STATIC void setprompt __P((int));
111STATIC union node *list(int);
112STATIC union node *andor(void);
113STATIC union node *pipeline(void);
114STATIC union node *command(void);
115STATIC union node *simplecmd(union node **, union node *);
116STATIC union node *makename(void);
117STATIC void parsefname(void);
118STATIC void parseheredoc(void);
119STATIC int peektoken(void);
120STATIC int readtoken(void);
121STATIC int xxreadtoken(void);
122STATIC int readtoken1(int, char const *, char *, int);
123STATIC int noexpand(char *);
124STATIC void synexpect(int);
125STATIC void synerror(char *);
126STATIC void setprompt(int);
127
128
129/*
130 * Read and parse a command. Returns NEOF on end of file. (NULL is a
131 * valid parse tree indicating a blank line.)
132 */
133
134union node *
127
128
129/*
130 * Read and parse a command. Returns NEOF on end of file. (NULL is a
131 * valid parse tree indicating a blank line.)
132 */
133
134union node *
135parsecmd(interact)
136 int interact;
135parsecmd(int interact)
137{
138 int t;
139
140 tokpushback = 0;
141 doprompt = interact;
142 if (doprompt)
143 setprompt(1);
144 else

--- 5 unchanged lines hidden (view full) ---

150 if (t == TNL)
151 return NULL;
152 tokpushback++;
153 return list(1);
154}
155
156
157STATIC union node *
136{
137 int t;
138
139 tokpushback = 0;
140 doprompt = interact;
141 if (doprompt)
142 setprompt(1);
143 else

--- 5 unchanged lines hidden (view full) ---

149 if (t == TNL)
150 return NULL;
151 tokpushback++;
152 return list(1);
153}
154
155
156STATIC union node *
158list(nlflag)
159 int nlflag;
157list(int nlflag)
160{
161 union node *n1, *n2, *n3;
162 int tok;
163
164 checkkwd = 2;
165 if (nlflag == 0 && tokendlist[peektoken()])
166 return NULL;
167 n1 = NULL;

--- 53 unchanged lines hidden (view full) ---

221 return n1;
222 }
223 }
224}
225
226
227
228STATIC union node *
158{
159 union node *n1, *n2, *n3;
160 int tok;
161
162 checkkwd = 2;
163 if (nlflag == 0 && tokendlist[peektoken()])
164 return NULL;
165 n1 = NULL;

--- 53 unchanged lines hidden (view full) ---

219 return n1;
220 }
221 }
222}
223
224
225
226STATIC union node *
229andor() {
227andor(void)
228{
230 union node *n1, *n2, *n3;
231 int t;
232
233 n1 = pipeline();
234 for (;;) {
235 if ((t = readtoken()) == TAND) {
236 t = NAND;
237 } else if (t == TOR) {

--- 9 unchanged lines hidden (view full) ---

247 n3->nbinary.ch2 = n2;
248 n1 = n3;
249 }
250}
251
252
253
254STATIC union node *
229 union node *n1, *n2, *n3;
230 int t;
231
232 n1 = pipeline();
233 for (;;) {
234 if ((t = readtoken()) == TAND) {
235 t = NAND;
236 } else if (t == TOR) {

--- 9 unchanged lines hidden (view full) ---

246 n3->nbinary.ch2 = n2;
247 n1 = n3;
248 }
249}
250
251
252
253STATIC union node *
255pipeline() {
254pipeline(void)
255{
256 union node *n1, *n2, *pipenode;
257 struct nodelist *lp, *prev;
258 int negate;
259
260 negate = 0;
261 TRACE(("pipeline: entered\n"));
262 while (readtoken() == TNOT)
263 negate = !negate;

--- 23 unchanged lines hidden (view full) ---

287 return n2;
288 } else
289 return n1;
290}
291
292
293
294STATIC union node *
256 union node *n1, *n2, *pipenode;
257 struct nodelist *lp, *prev;
258 int negate;
259
260 negate = 0;
261 TRACE(("pipeline: entered\n"));
262 while (readtoken() == TNOT)
263 negate = !negate;

--- 23 unchanged lines hidden (view full) ---

287 return n2;
288 } else
289 return n1;
290}
291
292
293
294STATIC union node *
295command() {
295command(void)
296{
296 union node *n1, *n2;
297 union node *ap, **app;
298 union node *cp, **cpp;
299 union node *redir, **rpp;
300 int t, negate = 0;
301
302 checkkwd = 2;
303 redir = NULL;

--- 218 unchanged lines hidden (view full) ---

522 return n2;
523 }
524 else
525 return n1;
526}
527
528
529STATIC union node *
297 union node *n1, *n2;
298 union node *ap, **app;
299 union node *cp, **cpp;
300 union node *redir, **rpp;
301 int t, negate = 0;
302
303 checkkwd = 2;
304 redir = NULL;

--- 218 unchanged lines hidden (view full) ---

523 return n2;
524 }
525 else
526 return n1;
527}
528
529
530STATIC union node *
530simplecmd(rpp, redir)
531 union node **rpp, *redir;
532 {
531simplecmd(union node **rpp, union node *redir)
532{
533 union node *args, **app;
534 union node **orig_rpp = rpp;
535 union node *n = NULL, *n2;
536 int negate = 0;
537
538 /* If we don't have any redirections already, then we must reset */
539 /* rpp to be the address of the local redir variable. */
540 if (redir == 0)

--- 58 unchanged lines hidden (view full) ---

599 n2->nnot.com = n;
600 return n2;
601 }
602 else
603 return n;
604}
605
606STATIC union node *
533 union node *args, **app;
534 union node **orig_rpp = rpp;
535 union node *n = NULL, *n2;
536 int negate = 0;
537
538 /* If we don't have any redirections already, then we must reset */
539 /* rpp to be the address of the local redir variable. */
540 if (redir == 0)

--- 58 unchanged lines hidden (view full) ---

599 n2->nnot.com = n;
600 return n2;
601 }
602 else
603 return n;
604}
605
606STATIC union node *
607makename() {
607makename(void)
608{
608 union node *n;
609
610 n = (union node *)stalloc(sizeof (struct narg));
611 n->type = NARG;
612 n->narg.next = NULL;
613 n->narg.text = wordtext;
614 n->narg.backquote = backquotelist;
615 return n;
616}
617
609 union node *n;
610
611 n = (union node *)stalloc(sizeof (struct narg));
612 n->type = NARG;
613 n->narg.next = NULL;
614 n->narg.text = wordtext;
615 n->narg.backquote = backquotelist;
616 return n;
617}
618
618void fixredir(n, text, err)
619 union node *n;
620 const char *text;
621 int err;
622 {
619void fixredir(union node *n, const char *text, int err)
620{
623 TRACE(("Fix redir %s %d\n", text, err));
624 if (!err)
625 n->ndup.vname = NULL;
626
627 if (is_digit(text[0]) && text[1] == '\0')
628 n->ndup.dupfd = digit_val(text[0]);
629 else if (text[0] == '-' && text[1] == '\0')
630 n->ndup.dupfd = -1;
631 else {
632
633 if (err)
634 synerror("Bad fd number");
635 else
636 n->ndup.vname = makename();
637 }
638}
639
640
641STATIC void
621 TRACE(("Fix redir %s %d\n", text, err));
622 if (!err)
623 n->ndup.vname = NULL;
624
625 if (is_digit(text[0]) && text[1] == '\0')
626 n->ndup.dupfd = digit_val(text[0]);
627 else if (text[0] == '-' && text[1] == '\0')
628 n->ndup.dupfd = -1;
629 else {
630
631 if (err)
632 synerror("Bad fd number");
633 else
634 n->ndup.vname = makename();
635 }
636}
637
638
639STATIC void
642parsefname() {
640parsefname(void)
641{
643 union node *n = redirnode;
644
645 if (readtoken() != TWORD)
646 synexpect(-1);
647 if (n->type == NHERE) {
648 struct heredoc *here = heredoc;
649 struct heredoc *p;
650 int i;

--- 24 unchanged lines hidden (view full) ---

675}
676
677
678/*
679 * Input any here documents.
680 */
681
682STATIC void
642 union node *n = redirnode;
643
644 if (readtoken() != TWORD)
645 synexpect(-1);
646 if (n->type == NHERE) {
647 struct heredoc *here = heredoc;
648 struct heredoc *p;
649 int i;

--- 24 unchanged lines hidden (view full) ---

674}
675
676
677/*
678 * Input any here documents.
679 */
680
681STATIC void
683parseheredoc() {
682parseheredoc(void)
683{
684 struct heredoc *here;
685 union node *n;
686
687 while (heredoclist) {
688 here = heredoclist;
689 heredoclist = here->next;
690 if (needprompt) {
691 setprompt(2);

--- 6 unchanged lines hidden (view full) ---

698 n->narg.next = NULL;
699 n->narg.text = wordtext;
700 n->narg.backquote = backquotelist;
701 here->here->nhere.doc = n;
702 }
703}
704
705STATIC int
684 struct heredoc *here;
685 union node *n;
686
687 while (heredoclist) {
688 here = heredoclist;
689 heredoclist = here->next;
690 if (needprompt) {
691 setprompt(2);

--- 6 unchanged lines hidden (view full) ---

698 n->narg.next = NULL;
699 n->narg.text = wordtext;
700 n->narg.backquote = backquotelist;
701 here->here->nhere.doc = n;
702 }
703}
704
705STATIC int
706peektoken() {
706peektoken(void)
707{
707 int t;
708
709 t = readtoken();
710 tokpushback++;
711 return (t);
712}
713
714STATIC int
708 int t;
709
710 t = readtoken();
711 tokpushback++;
712 return (t);
713}
714
715STATIC int
715readtoken() {
716readtoken(void)
717{
716 int t;
717 int savecheckkwd = checkkwd;
718 struct alias *ap;
719#ifdef DEBUG
720 int alreadyseen = tokpushback;
721#endif
722
723 top:

--- 62 unchanged lines hidden (view full) ---

786 * doesn't need to have any internal procedures, but parseword does.
787 * We could also make parseoperator in essence the main routine, and
788 * have parseword (readtoken1?) handle both words and redirection.]
789 */
790
791#define RETURN(token) return lasttoken = token
792
793STATIC int
718 int t;
719 int savecheckkwd = checkkwd;
720 struct alias *ap;
721#ifdef DEBUG
722 int alreadyseen = tokpushback;
723#endif
724
725 top:

--- 62 unchanged lines hidden (view full) ---

788 * doesn't need to have any internal procedures, but parseword does.
789 * We could also make parseoperator in essence the main routine, and
790 * have parseword (readtoken1?) handle both words and redirection.]
791 */
792
793#define RETURN(token) return lasttoken = token
794
795STATIC int
794xxreadtoken() {
796xxreadtoken(void)
797{
795 int c;
796
797 if (tokpushback) {
798 tokpushback = 0;
799 return lasttoken;
800 }
801 if (needprompt) {
802 setprompt(2);

--- 73 unchanged lines hidden (view full) ---

876#define CHECKEND() {goto checkend; checkend_return:;}
877#define PARSEREDIR() {goto parseredir; parseredir_return:;}
878#define PARSESUB() {goto parsesub; parsesub_return:;}
879#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
880#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
881#define PARSEARITH() {goto parsearith; parsearith_return:;}
882
883STATIC int
798 int c;
799
800 if (tokpushback) {
801 tokpushback = 0;
802 return lasttoken;
803 }
804 if (needprompt) {
805 setprompt(2);

--- 73 unchanged lines hidden (view full) ---

879#define CHECKEND() {goto checkend; checkend_return:;}
880#define PARSEREDIR() {goto parseredir; parseredir_return:;}
881#define PARSESUB() {goto parsesub; parsesub_return:;}
882#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
883#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
884#define PARSEARITH() {goto parsearith; parsearith_return:;}
885
886STATIC int
884readtoken1(firstc, syntax, eofmark, striptabs)
885 int firstc;
886 char const *syntax;
887 char *eofmark;
888 int striptabs;
889 {
887readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
888{
890 int c = firstc;
891 char *out;
892 int len;
893 char line[EOFMARKLEN + 1];
894 struct nodelist *bqlist;
895 int quotef;
896 int dblquote;
897 int varnest; /* levels of variables expansion */

--- 581 unchanged lines hidden (view full) ---

1479#endif
1480
1481/*
1482 * Returns true if the text contains nothing to expand (no dollar signs
1483 * or backquotes).
1484 */
1485
1486STATIC int
889 int c = firstc;
890 char *out;
891 int len;
892 char line[EOFMARKLEN + 1];
893 struct nodelist *bqlist;
894 int quotef;
895 int dblquote;
896 int varnest; /* levels of variables expansion */

--- 581 unchanged lines hidden (view full) ---

1478#endif
1479
1480/*
1481 * Returns true if the text contains nothing to expand (no dollar signs
1482 * or backquotes).
1483 */
1484
1485STATIC int
1487noexpand(text)
1488 char *text;
1489 {
1486noexpand(char *text)
1487{
1490 char *p;
1491 char c;
1492
1493 p = text;
1494 while ((c = *p++) != '\0') {
1495 if ( c == CTLQUOTEMARK)
1496 continue;
1497 if (c == CTLESC)

--- 6 unchanged lines hidden (view full) ---

1504
1505
1506/*
1507 * Return true if the argument is a legal variable name (a letter or
1508 * underscore followed by zero or more letters, underscores, and digits).
1509 */
1510
1511int
1488 char *p;
1489 char c;
1490
1491 p = text;
1492 while ((c = *p++) != '\0') {
1493 if ( c == CTLQUOTEMARK)
1494 continue;
1495 if (c == CTLESC)

--- 6 unchanged lines hidden (view full) ---

1502
1503
1504/*
1505 * Return true if the argument is a legal variable name (a letter or
1506 * underscore followed by zero or more letters, underscores, and digits).
1507 */
1508
1509int
1512goodname(name)
1513 char *name;
1514 {
1510goodname(char *name)
1511{
1515 char *p;
1516
1517 p = name;
1518 if (! is_name(*p))
1519 return 0;
1520 while (*++p) {
1521 if (! is_in_name(*p))
1522 return 0;

--- 4 unchanged lines hidden (view full) ---

1527
1528/*
1529 * Called when an unexpected token is read during the parse. The argument
1530 * is the token that is expected, or -1 if more than one type of token can
1531 * occur at this point.
1532 */
1533
1534STATIC void
1512 char *p;
1513
1514 p = name;
1515 if (! is_name(*p))
1516 return 0;
1517 while (*++p) {
1518 if (! is_in_name(*p))
1519 return 0;

--- 4 unchanged lines hidden (view full) ---

1524
1525/*
1526 * Called when an unexpected token is read during the parse. The argument
1527 * is the token that is expected, or -1 if more than one type of token can
1528 * occur at this point.
1529 */
1530
1531STATIC void
1535synexpect(token)
1536 int token;
1532synexpect(int token)
1537{
1538 char msg[64];
1539
1540 if (token >= 0) {
1541 fmtstr(msg, 64, "%s unexpected (expecting %s)",
1542 tokname[lasttoken], tokname[token]);
1543 } else {
1544 fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
1545 }
1546 synerror(msg);
1547}
1548
1549
1550STATIC void
1533{
1534 char msg[64];
1535
1536 if (token >= 0) {
1537 fmtstr(msg, 64, "%s unexpected (expecting %s)",
1538 tokname[lasttoken], tokname[token]);
1539 } else {
1540 fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
1541 }
1542 synerror(msg);
1543}
1544
1545
1546STATIC void
1551synerror(msg)
1552 char *msg;
1553 {
1547synerror(char *msg)
1548{
1554 if (commandname)
1555 outfmt(&errout, "%s: %d: ", commandname, startlinno);
1556 outfmt(&errout, "Syntax error: %s\n", msg);
1557 error((char *)NULL);
1558}
1559
1560STATIC void
1549 if (commandname)
1550 outfmt(&errout, "%s: %d: ", commandname, startlinno);
1551 outfmt(&errout, "Syntax error: %s\n", msg);
1552 error((char *)NULL);
1553}
1554
1555STATIC void
1561setprompt(which)
1562 int which;
1563 {
1556setprompt(int which)
1557{
1564 whichprompt = which;
1565
1566#ifndef NO_HISTORY
1567 if (!el)
1568#endif
1569 out2str(getprompt(NULL));
1570}
1571
1572/*
1573 * called by editline -- any expansions to the prompt
1574 * should be added here.
1575 */
1576char *
1558 whichprompt = which;
1559
1560#ifndef NO_HISTORY
1561 if (!el)
1562#endif
1563 out2str(getprompt(NULL));
1564}
1565
1566/*
1567 * called by editline -- any expansions to the prompt
1568 * should be added here.
1569 */
1570char *
1577getprompt(unused)
1578 void *unused __unused;
1571getprompt(void *unused __unused)
1579{
1580 switch (whichprompt) {
1581 case 0:
1582 return "";
1583 case 1:
1584 return ps1val();
1585 case 2:
1586 return ps2val();
1587 default:
1588 return "<internal prompt error>";
1589 }
1590}
1572{
1573 switch (whichprompt) {
1574 case 0:
1575 return "";
1576 case 1:
1577 return ps1val();
1578 case 2:
1579 return ps2val();
1580 default:
1581 return "<internal prompt error>";
1582 }
1583}