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} |