Deleted Added
sdiff udiff text old ( 83675 ) new ( 90111 )
full compact
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 $";
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));
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;
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 *
158list(nlflag)
159 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 *
229andor() {
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 *
255pipeline() {
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() {
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 *
530simplecmd(rpp, redir)
531 union node **rpp, *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 *
607makename() {
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
618void fixredir(n, text, err)
619 union node *n;
620 const char *text;
621 int err;
622 {
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
642parsefname() {
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
683parseheredoc() {
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() {
707 int t;
708
709 t = readtoken();
710 tokpushback++;
711 return (t);
712}
713
714STATIC int
715readtoken() {
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
794xxreadtoken() {
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
884readtoken1(firstc, syntax, eofmark, striptabs)
885 int firstc;
886 char const *syntax;
887 char *eofmark;
888 int striptabs;
889 {
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
1487noexpand(text)
1488 char *text;
1489 {
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
1512goodname(name)
1513 char *name;
1514 {
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
1535synexpect(token)
1536 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
1551synerror(msg)
1552 char *msg;
1553 {
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
1561setprompt(which)
1562 int which;
1563 {
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 *
1577getprompt(unused)
1578 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}