Sun Mar 27 14:40:20 2016 UTC ()
Move the parseredir internal subroutine out of readtoken1() into being
a real function of its own (also inspired by FreeBSD - though for
this one other sh differences require slightly different code.) (from kre@)


(christos)
diff -r1.111 -r1.112 src/bin/sh/parser.c

cvs diff -r1.111 -r1.112 src/bin/sh/parser.c (expand / switch to unified diff)

--- src/bin/sh/parser.c 2016/03/27 14:39:33 1.111
+++ src/bin/sh/parser.c 2016/03/27 14:40:20 1.112
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: parser.c,v 1.111 2016/03/27 14:39:33 christos Exp $ */ 1/* $NetBSD: parser.c,v 1.112 2016/03/27 14:40:20 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37#if 0 37#if 0
38static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; 38static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
39#else 39#else
40__RCSID("$NetBSD: parser.c,v 1.111 2016/03/27 14:39:33 christos Exp $"); 40__RCSID("$NetBSD: parser.c,v 1.112 2016/03/27 14:40:20 christos Exp $");
41#endif 41#endif
42#endif /* not lint */ 42#endif /* not lint */
43 43
44#include <stdio.h> 44#include <stdio.h>
45#include <stdlib.h> 45#include <stdlib.h>
46#include <limits.h> 46#include <limits.h>
47 47
48#include "shell.h" 48#include "shell.h"
49#include "parser.h" 49#include "parser.h"
50#include "nodes.h" 50#include "nodes.h"
51#include "expand.h" /* defines rmescapes() */ 51#include "expand.h" /* defines rmescapes() */
52#include "eval.h" /* defines commandname */ 52#include "eval.h" /* defines commandname */
53#include "redir.h" /* defines copyfd() */ 53#include "redir.h" /* defines copyfd() */
@@ -1169,27 +1169,26 @@ drop_state_level(VSS *stack) @@ -1169,27 +1169,26 @@ drop_state_level(VSS *stack)
1169 --stack->cur; 1169 --stack->cur;
1170 return stack; 1170 return stack;
1171} 1171}
1172 1172
1173static inline void 1173static inline void
1174cleanup_state_stack(VSS *stack) 1174cleanup_state_stack(VSS *stack)
1175{ 1175{
1176 while (stack->prev != NULL) { 1176 while (stack->prev != NULL) {
1177 stack->cur = 0; 1177 stack->cur = 0;
1178 stack = drop_state_level(stack); 1178 stack = drop_state_level(stack);
1179 } 1179 }
1180} 1180}
1181 1181
1182#define PARSEREDIR() {goto parseredir; parseredir_return:;} 
1183#define PARSESUB() {goto parsesub; parsesub_return:;} 1182#define PARSESUB() {goto parsesub; parsesub_return:;}
1184#define PARSEARITH() {goto parsearith; parsearith_return:;} 1183#define PARSEARITH() {goto parsearith; parsearith_return:;}
1185 1184
1186/* 1185/*
1187 * The following macros all assume the existance of a local var "stack" 1186 * The following macros all assume the existance of a local var "stack"
1188 * which contains a pointer to the current struct stackstate 1187 * which contains a pointer to the current struct stackstate
1189 */ 1188 */
1190 1189
1191/* 1190/*
1192 * These are macros rather than inline funcs to avoid code churn as much 1191 * These are macros rather than inline funcs to avoid code churn as much
1193 * as possible - they replace macros of the same name used previously. 1192 * as possible - they replace macros of the same name used previously.
1194 */ 1193 */
1195#define ISDBLQUOTE() (currentstate(stack)->ts_quoted & QS) 1194#define ISDBLQUOTE() (currentstate(stack)->ts_quoted & QS)
@@ -1360,26 +1359,114 @@ done: @@ -1360,26 +1359,114 @@ done:
1360 sstr = str = NULL; 1359 sstr = str = NULL;
1361 INTON; 1360 INTON;
1362 } 1361 }
1363 parsebackquote = savepbq; 1362 parsebackquote = savepbq;
1364 handler = savehandler; 1363 handler = savehandler;
1365 if (arinest || ISDBLQUOTE()) 1364 if (arinest || ISDBLQUOTE())
1366 USTPUTC(CTLBACKQ | CTLQUOTE, out); 1365 USTPUTC(CTLBACKQ | CTLQUOTE, out);
1367 else 1366 else
1368 USTPUTC(CTLBACKQ, out); 1367 USTPUTC(CTLBACKQ, out);
1369 1368
1370 return out; 1369 return out;
1371} 1370}
1372 1371
 1372/*
 1373 * Parse a redirection operator. The parameter "out" points to a string
 1374 * specifying the fd to be redirected. It is guaranteed to be either ""
 1375 * or a numeric string (for now anyway). The parameter "c" contains the
 1376 * first character of the redirection operator.
 1377 *
 1378 * Note the string "out" is on the stack, which we are about to clobber,
 1379 * so process it first...
 1380 */
 1381
 1382static void
 1383parseredir(const char *out, int c)
 1384{
 1385 union node *np;
 1386 int fd;
 1387
 1388 fd = (*out == '\0') ? -1 : atoi(out);
 1389
 1390 np = stalloc(sizeof(struct nfile));
 1391 if (c == '>') {
 1392 if (fd < 0)
 1393 fd = 1;
 1394 c = pgetc();
 1395 if (c == '>')
 1396 np->type = NAPPEND;
 1397 else if (c == '|')
 1398 np->type = NCLOBBER;
 1399 else if (c == '&')
 1400 np->type = NTOFD;
 1401 else {
 1402 np->type = NTO;
 1403 pungetc();
 1404 }
 1405 } else { /* c == '<' */
 1406 if (fd < 0)
 1407 fd = 0;
 1408 switch (c = pgetc()) {
 1409 case '<':
 1410 if (sizeof (struct nfile) != sizeof (struct nhere)) {
 1411 np = stalloc(sizeof(struct nhere));
 1412 np->nfile.fd = 0;
 1413 }
 1414 np->type = NHERE;
 1415 heredoc = stalloc(sizeof(struct heredoc));
 1416 heredoc->here = np;
 1417 if ((c = pgetc()) == '-') {
 1418 heredoc->striptabs = 1;
 1419 } else {
 1420 heredoc->striptabs = 0;
 1421 pungetc();
 1422 }
 1423 break;
 1424
 1425 case '&':
 1426 np->type = NFROMFD;
 1427 break;
 1428
 1429 case '>':
 1430 np->type = NFROMTO;
 1431 break;
 1432
 1433 default:
 1434 np->type = NFROM;
 1435 pungetc();
 1436 break;
 1437 }
 1438 }
 1439 np->nfile.fd = fd;
 1440
 1441 redirnode = np; /* this is the "value" of TRENODE */
 1442}
 1443
 1444
 1445/*
 1446 * The lowest level basic tokenizer.
 1447 *
 1448 * The next input byte (character) is in firstc, syn says which
 1449 * syntax tables we are to use (basic, single or double quoted, or arith)
 1450 * and magicq (used with sqsyntax and dqsyntax only) indicates that the
 1451 * quote character itself is not special (used parsing here docs and similar)
 1452 *
 1453 * The result is the type of the next token (its value, when there is one,
 1454 * is saved in the relevant global var - must fix that someday!) which is
 1455 * also saved for re-reading ("lasttoken").
 1456 *
 1457 * Overall, this routine does far more parsing than it is supposed to.
 1458 * That will also need fixing, someday...
 1459 */
1373STATIC int 1460STATIC int
1374readtoken1(int firstc, char const *syn, int magicq) 1461readtoken1(int firstc, char const *syn, int magicq)
1375{ 1462{
1376 int c = firstc; 1463 int c = firstc;
1377 char * out; 1464 char * out;
1378 int len; 1465 int len;
1379 struct nodelist *bqlist; 1466 struct nodelist *bqlist;
1380 int quotef; 1467 int quotef;
1381 VSS static_stack; 1468 VSS static_stack;
1382 VSS *stack = &static_stack; 1469 VSS *stack = &static_stack;
1383 1470
1384 stack->prev = NULL; 1471 stack->prev = NULL;
1385 stack->cur = 0; 1472 stack->cur = 0;
@@ -1563,108 +1650,43 @@ endword: @@ -1563,108 +1650,43 @@ endword:
1563 if (varnest != 0) { 1650 if (varnest != 0) {
1564 cleanup_state_stack(stack); 1651 cleanup_state_stack(stack);
1565 startlinno = plinno; 1652 startlinno = plinno;
1566 /* { */ 1653 /* { */
1567 synerror("Missing '}'"); 1654 synerror("Missing '}'");
1568 } 1655 }
1569 USTPUTC('\0', out); 1656 USTPUTC('\0', out);
1570 len = out - stackblock(); 1657 len = out - stackblock();
1571 out = stackblock(); 1658 out = stackblock();
1572 if (!magicq) { 1659 if (!magicq) {
1573 if ((c == '<' || c == '>') 1660 if ((c == '<' || c == '>')
1574 && quotef == 0 1661 && quotef == 0
1575 && (*out == '\0' || is_number(out))) { 1662 && (*out == '\0' || is_number(out))) {
1576 PARSEREDIR(); 1663 parseredir(out, c);
1577 cleanup_state_stack(stack); 1664 cleanup_state_stack(stack);
1578 return lasttoken = TREDIR; 1665 return lasttoken = TREDIR;
1579 } else { 1666 } else {
1580 pungetc(); 1667 pungetc();
1581 } 1668 }
1582 } 1669 }
1583 quoteflag = quotef; 1670 quoteflag = quotef;
1584 backquotelist = bqlist; 1671 backquotelist = bqlist;
1585 grabstackblock(len); 1672 grabstackblock(len);
1586 wordtext = out; 1673 wordtext = out;
1587 cleanup_state_stack(stack); 1674 cleanup_state_stack(stack);
1588 return lasttoken = TWORD; 1675 return lasttoken = TWORD;
1589/* end of readtoken routine */ 1676/* end of readtoken routine */
1590 1677
1591 1678
1592/* 1679/*
1593 * Parse a redirection operator. The variable "out" points to a string 
1594 * specifying the fd to be redirected. The variable "c" contains the 
1595 * first character of the redirection operator. 
1596 */ 
1597 
1598parseredir: { 
1599 char fd[64]; 
1600 union node *np; 
1601 strlcpy(fd, out, sizeof(fd)); 
1602 
1603 np = stalloc(sizeof(struct nfile)); 
1604 if (c == '>') { 
1605 np->nfile.fd = 1; 
1606 c = pgetc(); 
1607 if (c == '>') 
1608 np->type = NAPPEND; 
1609 else if (c == '|') 
1610 np->type = NCLOBBER; 
1611 else if (c == '&') 
1612 np->type = NTOFD; 
1613 else { 
1614 np->type = NTO; 
1615 pungetc(); 
1616 } 
1617 } else { /* c == '<' */ 
1618 np->nfile.fd = 0; 
1619 switch (c = pgetc()) { 
1620 case '<': 
1621 if (sizeof (struct nfile) != sizeof (struct nhere)) { 
1622 np = stalloc(sizeof(struct nhere)); 
1623 np->nfile.fd = 0; 
1624 } 
1625 np->type = NHERE; 
1626 heredoc = stalloc(sizeof(struct heredoc)); 
1627 heredoc->here = np; 
1628 if ((c = pgetc()) == '-') { 
1629 heredoc->striptabs = 1; 
1630 } else { 
1631 heredoc->striptabs = 0; 
1632 pungetc(); 
1633 } 
1634 break; 
1635 
1636 case '&': 
1637 np->type = NFROMFD; 
1638 break; 
1639 
1640 case '>': 
1641 np->type = NFROMTO; 
1642 break; 
1643 
1644 default: 
1645 np->type = NFROM; 
1646 pungetc(); 
1647 break; 
1648 } 
1649 } 
1650 if (*fd != '\0') 
1651 np->nfile.fd = number(fd); 
1652 redirnode = np; 
1653 goto parseredir_return; 
1654} 
1655 
1656 
1657/* 
1658 * Parse a substitution. At this point, we have read the dollar sign 1680 * Parse a substitution. At this point, we have read the dollar sign
1659 * and nothing else. 1681 * and nothing else.
1660 */ 1682 */
1661 1683
1662parsesub: { 1684parsesub: {
1663 char buf[10]; 1685 char buf[10];
1664 int subtype; 1686 int subtype;
1665 int typeloc; 1687 int typeloc;
1666 int flags; 1688 int flags;
1667 char *p; 1689 char *p;
1668 static const char types[] = "}-+?="; 1690 static const char types[] = "}-+?=";
1669 int i; 1691 int i;
1670 int linno; 1692 int linno;