aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-11-16 12:08:59 -0800
committerNicholas Noll <nbnoll@eml.cc>2021-11-16 12:08:59 -0800
commit29138fff8643194ec49cb79304d2a878d46c378b (patch)
tree04f46762380d84994ec821cec13f1ff8288d46fc
parente4f9b993e97b6e6e790810b6d261dc5bf61b0513 (diff)
Feat: added heredocs
Heredocs are simply strings written to tmp files. There was minimal bug testing here. Also, various bug fixes are included
-rw-r--r--src/cmd/rc/code.c38
-rw-r--r--src/cmd/rc/exec.c133
-rw-r--r--src/cmd/rc/exec.h8
-rw-r--r--src/cmd/rc/io.c22
-rw-r--r--src/cmd/rc/lex.c207
-rw-r--r--src/cmd/rc/main.c1
-rw-r--r--src/cmd/rc/parse.c203
-rw-r--r--src/cmd/rc/parse.h4
-rw-r--r--src/cmd/rc/rc.h16
-rw-r--r--src/cmd/rc/syntax.y4
-rw-r--r--src/cmd/rc/sys.c32
-rw-r--r--src/cmd/rc/tree.c8
-rw-r--r--src/cmd/rc/var.c18
13 files changed, 510 insertions, 184 deletions
diff --git a/src/cmd/rc/code.c b/src/cmd/rc/code.c
index 201ecc2..dd0e99c 100644
--- a/src/cmd/rc/code.c
+++ b/src/cmd/rc/code.c
@@ -51,8 +51,6 @@ funcstr(Tree *node)
return v;
}
-void yyerror(const char *msg);
-
static void
walk(Tree *node)
{
@@ -250,6 +248,7 @@ walk(Tree *node)
goto emitcase;
donecase:
storepc(addr3);
+ emitf(Xunmark);
break;
case Ttwiddle:
@@ -265,6 +264,7 @@ walk(Tree *node)
walk(node->child[0]);
if(addr1 == interpreter.i) // empty condition => while(true)
emitf(Xsettrue);
+ emitf(Xnewpgid);
emitf(Xtrue);
addr2 = emiti(0); // goto end of loop
@@ -278,7 +278,7 @@ walk(Tree *node)
emitf(Xmark);
if(node->child[1]){ // for( x in X )
walk(node->child[1]);
- // emitf(Xglob)
+ emitf(Xglob);
}else{ // for(X)
emitf(Xmark);
emitf(Xword);
@@ -336,6 +336,30 @@ walk(Tree *node)
emitf(Xpipewait);
break;
+
+#if 0
+ case Tpipefd:
+#endif
+
+ case Tredir:
+ emitf(Xmark);
+ walk(node->child[0]);
+ emitf(Xglob);
+ switch(node->redir.type){
+ case Rappend: emitf(Xappend); break;
+ case Rwrite: emitf(Xwrite); break;
+ case Rread: /* fallthrough */
+ case Rhere: emitf(Xread); break;
+ case Rrdwr: emitf(Xrdwr); break;
+ default:
+ print(shell.err, "bad redir type %d in interpreter walk\n", node->redir.type);
+ fatal("crashing\n");
+ break;
+ }
+ emiti(node->redir.fd[0]);
+ walk(node->child[1]);
+ emitf(Xpopredir);
+ break;
}
}
@@ -357,6 +381,13 @@ copycode(Code *c)
return c;
}
+void
+emitdelhere(char *name)
+{
+ emitf(Xdelhere);
+ emits(strdup(name));
+}
+
int
compile(Tree *node)
{
@@ -368,6 +399,7 @@ compile(Tree *node)
walk(node);
+ readhere();
emitf(Xreturn);
emitf(nil);
diff --git a/src/cmd/rc/exec.c b/src/cmd/rc/exec.c
index 71f5359..28b6135 100644
--- a/src/cmd/rc/exec.c
+++ b/src/cmd/rc/exec.c
@@ -685,12 +685,129 @@ Xmark(void)
}
void
+Xunmark(void)
+{
+ poplist();
+}
+
+void
Xword(void)
{
pushword(runner->code.exe[runner->code.i++].s);
}
void
+Xwrite(void)
+{
+ int fd;
+ char *path;
+
+ switch(count(runner->args->word)){
+ default:
+ Xerror("> requires singleton\n");
+ return;
+ case 0:
+ Xerror("> requires path\n");
+ return;
+ case 1:
+ ;
+ }
+ path = runner->args->word->str;
+ if((fd=open(path,O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR))<0){
+ print(shell.err, "%s: ", path);
+ Xerror("can't open");
+ return;
+ }
+ pushredir(Ropen, fd, runner->code.exe[runner->code.i++].i);
+ poplist();
+}
+
+void
+Xappend(void)
+{
+ int fd;
+ char *path;
+
+ switch(count(runner->args->word)){
+ default:
+ Xerror(">> requires singleton\n");
+ return;
+ case 0:
+ Xerror(">> requires path\n");
+ return;
+ case 1:
+ ;
+ }
+ path = runner->args->word->str;
+ if(((fd=open(path,O_APPEND|O_WRONLY))<0)
+ && ((fd=open(path,O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR))<0)){
+ print(shell.err, "%s: ", path);
+ Xerror("can't open");
+ return;
+ }
+ pushredir(Ropen, fd, runner->code.exe[runner->code.i++].i);
+ poplist();
+}
+
+void
+Xread(void)
+{
+ int fd;
+ char *path;
+
+ switch(count(runner->args->word)){
+ default:
+ Xerror("< requires singleton\n");
+ return;
+ case 0:
+ Xerror("< requires path\n");
+ return;
+ case 1:
+ ;
+ }
+ path = runner->args->word->str;
+ if((fd=open(path,O_RDONLY))<0){
+ print(shell.err, "%s: ", path);
+ Xerror("can't open");
+ return;
+ }
+ pushredir(Ropen, fd, runner->code.exe[runner->code.i++].i);
+ poplist();
+}
+
+void
+Xrdwr(void)
+{
+ int fd;
+ char *path;
+
+ switch(count(runner->args->word)){
+ default:
+ Xerror("<> requires singleton\n");
+ return;
+ case 0:
+ Xerror("<> requires path\n");
+ return;
+ case 1:
+ ;
+ }
+ path = runner->args->word->str;
+ if((fd=open(path,O_RDWR))<0){
+ print(shell.err, "%s: ", path);
+ Xerror("can't open");
+ return;
+ }
+ pushredir(Ropen, fd, runner->code.exe[runner->code.i++].i);
+ poplist();
+}
+
+void
+Xnewpgid(void)
+{
+ runner->pgid = -1;
+}
+
+void
Xsettrue(void)
{
setstatus(nil);
@@ -774,12 +891,15 @@ clean:
void
Xfor(void)
{
- if(!runner->args->word){
+ if(!runner->args->word){ /* terminate loop */
poplist();
runner->code.i = runner->code.exe[runner->code.i].i;
- }else{
+ }else{ /* continue loop */
freelist(runner->local->val);
+ /* reset process group */
+ runner->pgid = -1;
+ /* reset local variables */
runner->local->val = runner->args->word;
runner->local->new = 1;
runner->args->word = runner->args->word->link;
@@ -789,8 +909,7 @@ Xfor(void)
}
}
-static
-Word*
+static Word*
catlist(Word *l, Word *r, Word *tail)
{
Word *w;
@@ -1344,6 +1463,12 @@ Xpopredir(void)
}
void
+Xdelhere(void)
+{
+ remove(runner->code.exe[runner->code.i++].s);
+}
+
+void
Xreturn(void)
{
Thread *curr = runner;
diff --git a/src/cmd/rc/exec.h b/src/cmd/rc/exec.h
index 1a81644..9db7e60 100644
--- a/src/cmd/rc/exec.h
+++ b/src/cmd/rc/exec.h
@@ -7,6 +7,13 @@
* code in line with jump around {...}
*/
+void Xnewpgid(void);
+void Xunmark(void);
+void Xwrite(void);
+void Xread(void);
+void Xrdwr(void);
+void Xappend(void);
+void Xdelhere(void);
void Xcase(void);
void Xfunc(void);
void Xmatch(void);
@@ -34,6 +41,7 @@ void Xflat(void);
void Xpipe(void);
void Xpipewait(void);
void Xpopredir(void);
+void Xglob(void);
void Xreturn(void);
void Xexit(void);
diff --git a/src/cmd/rc/io.c b/src/cmd/rc/io.c
index 5152627..3e47036 100644
--- a/src/cmd/rc/io.c
+++ b/src/cmd/rc/io.c
@@ -88,7 +88,6 @@ refill(Io *io)
return *io->b++&0xff;
}
-
void
flush(Io *io)
{
@@ -106,14 +105,13 @@ flush(Io *io)
}else{
n = io->b-io->buf;
if(n && write(io->fd, io->buf, n) < 0)
- write(3, "write error\n", 12);
+ write(mapfd(3), "write error\n", 12);
io->b = io->buf;
io->e = io->buf + io->cap;
}
}
-static
void
printchar(Io *io, int c)
{
@@ -123,7 +121,7 @@ printchar(Io *io, int c)
*io->b++=c;
}
-void
+static void
printquote(Io *io, char *s)
{
printchar(io, '\'');
@@ -142,7 +140,7 @@ printstr(Io *io, char *s)
while(*s) printchar(io, *s++);
}
-void
+static void
printword(Io *io, char *s)
{
char *t;
@@ -157,7 +155,7 @@ printword(Io *io, char *s)
printstr(io, s);
}
-void
+static void
printptr(Io *io, void *v)
{
int n;
@@ -170,8 +168,7 @@ printptr(Io *io, void *v)
for(n = 28;n>=0;n-=4) printchar(io, "0123456789ABCDEF"[(p>>n)&0xF]);
}
-static
-void
+static void
printint(Io *io, int n)
{
if(n<0){
@@ -192,8 +189,7 @@ printint(Io *io, int n)
printchar(io, n%10+'0');
}
-static
-void
+static void
printoct(Io *io, unsigned n)
{
if(n>7)
@@ -201,8 +197,7 @@ printoct(Io *io, unsigned n)
printchar(io, (n&7)+'0');
}
-static
-void
+static void
printval(Io *io, Word *a)
{
if(a){
@@ -219,8 +214,7 @@ printval(Io *io, Word *a)
#define C1 t->child[1]
#define C2 t->child[2]
-static
-void
+static void
printtree(Io *io, Tree *t)
{
Tree *c, *nc;
diff --git a/src/cmd/rc/lex.c b/src/cmd/rc/lex.c
index 3722606..0eb023c 100644
--- a/src/cmd/rc/lex.c
+++ b/src/cmd/rc/lex.c
@@ -16,12 +16,29 @@ struct Lexer
char buf[BUFSIZ];
};
-static struct Lexer lexer = { .c={0, EOF}, .doprompt=1 };
+struct Here
+{
+ Tree *tag;
+ char *name;
+ struct Here *link;
+};
+// -----------------------------------------------------------------------
+// globals
+
+static struct Lexer lexer = { .c={0, EOF}, .doprompt=1 };
#define put1(b) lexer.buf[0] = (b), lexer.buf[1] = 0;
#define put2(b0,b1) lexer.buf[0] = (b0), lexer.buf[1] = (b1), lexer.buf[2] = 0;
#define put3(b0,b1,b2) lexer.buf[0] = (b0), lexer.buf[1] = (b1), lexer.buf[2] = b2, lexer.buf[3] = 0;
+static struct Here *heres, **endhere;
+static char hex[]="0123456789abcdef";
+static char tmp[]="/tmp/here0000.0000";
+static int numhere;
+
+// -----------------------------------------------------------------------
+// internal functions
+
void
yyerror(const char *msg)
{
@@ -41,6 +58,80 @@ yyerror(const char *msg)
advance();
}
+static void
+hexnum(char *p, int n)
+{
+ *p++=hex[(n>>12)&0xF];
+ *p++=hex[(n>>8)&0xF];
+ *p++=hex[(n>>4)&0xF];
+ *p = hex[n&0xF];
+}
+
+static void
+pword(Io *io, Word *arg)
+{
+ if(arg){
+ while(arg->link && arg->link->str){
+ printstr(io, arg->str);
+ printchar(io, ' ');
+ arg = arg->link;
+ }
+ printstr(io, arg->str);
+ }
+}
+
+static void
+psubst(Io *io, char *s)
+{
+ char *t, *u;
+ int savec, n;
+ Word *star;
+
+ while(*s){
+ if(*s!='$'){
+ if(0xa0<=(*s&0xff) && (*s&0xff)<=0xf5){
+ printchar(io, *s++);
+ if(*s=='\0')
+ break;
+ }else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){
+ printchar(io, *s++);
+ if(*s=='\0')
+ break;
+ printchar(io, *s++);
+ if(*s=='\0')
+ break;
+ }
+ printchar(io, *s++);
+ }else{
+ t=++s;
+ if(*t=='$')
+ printchar(io, *t++);
+ else{
+ while(*t && isidentchar(*t))
+ t++;
+ savec=*t;
+ *t='\0';
+ n = 0;
+ for(u = s;*u && '0'<=*u && *u<='9';u++) n = n*10+*u-'0';
+ if(n && *u=='\0'){
+ star = var("*")->val;
+ if(star && 1<=n && n<=count(star)){
+ while(--n)
+ star = star->link;
+ printstr(io, star->str);
+ }
+ }
+ else
+ pword(io, var(s)->val);
+ *t = savec;
+ if(savec=='^')
+ t++;
+ }
+ s = t;
+ }
+ }
+}
+
int
readc(void)
{
@@ -68,8 +159,7 @@ readc(void)
return c;
}
-static
-int
+static int
peekc(void)
{
if(lexer.c[1] == EOF)
@@ -78,8 +168,7 @@ peekc(void)
return lexer.c[1];
}
-static
-int
+static int
advance(void)
{
int c = peekc();
@@ -88,8 +177,7 @@ advance(void)
return c;
}
-static
-void
+static void
skipws(void)
{
int c;
@@ -102,8 +190,7 @@ skipws(void)
}
}
-static
-void
+static void
skipnl(void)
{
int c;
@@ -116,8 +203,7 @@ skipnl(void)
}
}
-static
-int
+static int
nextis(int c)
{
if(peekc()==c){
@@ -127,8 +213,7 @@ nextis(int c)
return 0;
}
-static
-char *
+static char *
putbyte(char *buf, int c)
{
if(!buf)
@@ -165,7 +250,93 @@ putrune(char *buf, int c)
}
// -----------------------------------------------------------------------
-// exported functions
+// here doc exports
+
+Tree *
+heredoc(Tree *tag)
+{
+ struct Here *h;
+ if(tag->type != Tword)
+ yyerror("bad here tag");
+
+ h = emalloc(sizeof(*h));
+ h->link = nil;
+ if(heres)
+ *endhere = h;
+ else
+ heres = h;
+
+ h->tag = tag;
+ hexnum(&tmp[9], getpid());
+ hexnum(&tmp[14], numhere++);
+ h->name = strdup(tmp);
+ return token(Tword, tmp);
+}
+
+void
+readhere(void)
+{
+ Io *io;
+ int c, sub;
+ long len;
+ struct Here *h, *nh;
+ char *s, *beg, *end, *tag, line[PAGESIZE+1];
+
+ for(h=heres; h; h = nh){
+ sub = !h->tag->quoted;
+ tag = h->tag->str;
+
+ if((c=open(h->name,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))<0)
+ yyerror("failed to make heredoc");
+ io = openfd(c);
+
+ prompt(&lexer.doprompt);
+
+ beg=line, s=line, end=arrend(line)-1, len=PAGESIZE;
+ while((c=get(runner->cmd.io))!=EOF){
+ /* out of space: get bigger buffer */
+ if(s == end){
+ s = beg;
+ beg = (beg == line) ? emalloc(2*len+1) : erealloc(beg, 2*len+1);
+ memcpy(beg, s, len);
+ s = beg + len;
+ len *= 2;
+ end = beg + len;
+ }
+
+ if(c!='\n'){
+ *s++ = c;
+ continue;
+ }
+ /* c == '\n' */
+ *s = 0;
+ if(tag && strcmp(beg, tag) == 0)
+ break;
+ if(sub)
+ psubst(io, beg);
+ else
+ printstr(io, beg);
+ /* reset */
+ s = beg;
+ prompt(&lexer.doprompt);
+ printchar(io, c);
+ }
+
+ flush(io);
+ terminate(io);
+ emitdelhere(h->name);
+ nh = h->link;
+ if(beg != line)
+ efree(beg);
+ efree(h);
+ }
+ heres = nil;
+ lexer.doprompt = 1;
+}
+
+
+// -----------------------------------------------------------------------
+// lexer exported functions
// TODO: turn into static tables
int
@@ -183,8 +354,8 @@ isidentchar(int c)
int
yylex(void)
{
- int c, d = peekc();
Tree *node;
+ int c, d = peekc();
char *w = lexer.buf;
yylval.tree = nil;
@@ -194,7 +365,7 @@ yylex(void)
lexer.hadword = 0;
if(d=='('){
advance();
- strcpy(lexer.buf, "( [Tindex]");
+ strcpy(lexer.buf, "(Tindex)");
return Tindex;
}
if(iswordchar(d) || d=='\'' || d=='`' || d=='$' || d=='"'){
@@ -225,6 +396,7 @@ yylex(void)
put1('$');
return '$';
+#if 0
case '@':
lexer.haddollar = 0;
put1('@');
@@ -234,6 +406,7 @@ yylex(void)
lexer.haddollar = 0;
put1('!');
return Tbang;
+#endif
case '&':
lexer.haddollar = 0;
@@ -294,7 +467,7 @@ yylex(void)
*w++='[';
c = advance();
*w++ = c;
- if(c < '0' || '9' < c){
+ if(c<'0' || '9'<c){
badredir:
*w = 0;
yyerror(node->type == Tpipe ? "pipe syntax" : "redirection syntax");
diff --git a/src/cmd/rc/main.c b/src/cmd/rc/main.c
index eb83c90..0897352 100644
--- a/src/cmd/rc/main.c
+++ b/src/cmd/rc/main.c
@@ -55,6 +55,7 @@ main(int argc, char *argv[])
shell.err = openfd(2);
/* yydebug=1; */
+
initenv();
initpath();
initkeywords();
diff --git a/src/cmd/rc/parse.c b/src/cmd/rc/parse.c
index e57bf2e..7ff860e 100644
--- a/src/cmd/rc/parse.c
+++ b/src/cmd/rc/parse.c
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.7.6. */
+/* A Bison parser, made by GNU Bison 3.8.2. */
/* Bison implementation for Yacc-like parsers in C
@@ -46,10 +46,10 @@
USER NAME SPACE" below. */
/* Identify Bison output, and Bison version. */
-#define YYBISON 30706
+#define YYBISON 30802
/* Bison version string. */
-#define YYBISON_VERSION "3.7.6"
+#define YYBISON_VERSION "3.8.2"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -323,12 +323,18 @@ typedef int yy_state_fast_t;
# define YY_USE(E) /* empty */
#endif
-#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
+# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
+# else
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# endif
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
@@ -545,7 +551,7 @@ static const yytype_int8 yytranslate[] =
};
#if YYDEBUG
- /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
0, 38, 38, 39, 42, 43, 46, 47, 50, 53,
@@ -589,18 +595,6 @@ yysymbol_name (yysymbol_kind_t yysymbol)
}
#endif
-#ifdef YYPRINT
-/* YYTOKNUM[NUM] -- (External) token number corresponding to the
- (internal) symbol number NUM (which must be that of a token). */
-static const yytype_int16 yytoknum[] =
-{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
- 275, 276, 277, 278, 279, 41, 280, 281, 10, 94,
- 36, 282, 283, 40, 123, 125, 59, 38, 61, 96
-};
-#endif
-
#define YYPACT_NINF (-44)
#define yypact_value_is_default(Yyn) \
@@ -611,8 +605,8 @@ static const yytype_int16 yytoknum[] =
#define yytable_value_is_error(Yyn) \
0
- /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
static const yytype_int16 yypact[] =
{
124, -18, -16, -16, 19, 415, 447, 447, -44, 415,
@@ -631,9 +625,9 @@ static const yytype_int16 yypact[] =
-44, -44, -44, 267, -44, -8
};
- /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE does not specify something else to do. Zero
- means the default is an error. */
+/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
static const yytype_int8 yydefact[] =
{
24, 0, 0, 0, 0, 0, 24, 24, 68, 0,
@@ -652,7 +646,7 @@ static const yytype_int8 yydefact[] =
18, 39, 73, 24, 16, 0
};
- /* YYPGOTO[NTERM-NUM]. */
+/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
-44, -44, 77, -26, 98, 13, 26, -28, -44, -44,
@@ -660,7 +654,7 @@ static const yytype_int8 yypgoto[] =
-44, -43, -44, -30
};
- /* YYDEFGOTO[NTERM-NUM]. */
+/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_uint8 yydefgoto[] =
{
0, 18, 19, 56, 30, 20, 57, 58, 105, 127,
@@ -668,9 +662,9 @@ static const yytype_uint8 yydefgoto[] =
47, 50, 55, 79
};
- /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule whose
- number is the opposite. If YYTABLE_NINF, syntax error. */
+/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_int16 yytable[] =
{
24, 80, 83, 78, 46, 63, 48, 49, 46, 68,
@@ -777,8 +771,8 @@ static const yytype_int16 yycheck[] =
33, 34, -1, -1, -1, -1, 39
};
- /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
+/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
+ state STATE-NUM. */
static const yytype_int8 yystos[] =
{
0, 3, 5, 6, 8, 11, 12, 13, 14, 15,
@@ -797,7 +791,7 @@ static const yytype_int8 yystos[] =
50, 35, 36, 63, 47, 54
};
- /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
static const yytype_int8 yyr1[] =
{
0, 40, 41, 41, 42, 42, 43, 43, 44, 45,
@@ -810,7 +804,7 @@ static const yytype_int8 yyr1[] =
62, 62, 62, 63, 63
};
- /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
static const yytype_int8 yyr2[] =
{
0, 2, 0, 2, 1, 2, 1, 2, 3, 3,
@@ -832,6 +826,7 @@ enum { YYENOMEM = -2 };
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
#define YYERROR goto yyerrorlab
+#define YYNOMEM goto yyexhaustedlab
#define YYRECOVERING() (!!yyerrstatus)
@@ -872,10 +867,7 @@ do { \
YYFPRINTF Args; \
} while (0)
-/* This macro is provided for backward compatibility. */
-# ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
+
# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
@@ -902,10 +894,6 @@ yy_symbol_value_print (FILE *yyo,
YY_USE (yyoutput);
if (!yyvaluep)
return;
-# ifdef YYPRINT
- if (yykind < YYNTOKENS)
- YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
-# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
@@ -1360,6 +1348,7 @@ yyparse (void)
YYDPRINTF ((stderr, "Starting parse\n"));
yychar = YYEMPTY; /* Cause a token to be read. */
+
goto yysetstate;
@@ -1385,7 +1374,7 @@ yysetstate:
if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
- goto yyexhaustedlab;
+ YYNOMEM;
#else
{
/* Get the current used size of the three stacks, in elements. */
@@ -1413,7 +1402,7 @@ yysetstate:
# else /* defined YYSTACK_RELOCATE */
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
+ YYNOMEM;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
yystacksize = YYMAXDEPTH;
@@ -1424,7 +1413,7 @@ yysetstate:
YY_CAST (union yyalloc *,
YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
if (! yyptr)
- goto yyexhaustedlab;
+ YYNOMEM;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
# undef YYSTACK_RELOCATE
@@ -1446,6 +1435,7 @@ yysetstate:
}
#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
+
if (yystate == YYFINAL)
YYACCEPT;
@@ -1560,293 +1550,293 @@ yyreduce:
case 2: /* rc: %empty */
#line 38 "src/cmd/rc/syntax.y"
{ return 0; }
-#line 1564 "src/cmd/rc/parse.c"
+#line 1554 "src/cmd/rc/parse.c"
break;
case 3: /* rc: line '\n' */
#line 39 "src/cmd/rc/syntax.y"
{ return compile((yyvsp[-1].tree)); }
-#line 1570 "src/cmd/rc/parse.c"
+#line 1560 "src/cmd/rc/parse.c"
break;
case 5: /* line: cmds line */
#line 43 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1576 "src/cmd/rc/parse.c"
+#line 1566 "src/cmd/rc/parse.c"
break;
case 7: /* body: cmdsln body */
#line 47 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1582 "src/cmd/rc/parse.c"
+#line 1572 "src/cmd/rc/parse.c"
break;
case 8: /* paren: '(' body ')' */
#line 50 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tparen, (yyvsp[-1].tree)); }
-#line 1588 "src/cmd/rc/parse.c"
+#line 1578 "src/cmd/rc/parse.c"
break;
case 9: /* block: '{' body '}' */
#line 53 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tblock, (yyvsp[-1].tree)); }
-#line 1594 "src/cmd/rc/parse.c"
+#line 1584 "src/cmd/rc/parse.c"
break;
case 11: /* cmds: cmd '&' */
#line 57 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1('&', (yyvsp[-1].tree)); }
-#line 1600 "src/cmd/rc/parse.c"
+#line 1590 "src/cmd/rc/parse.c"
break;
case 14: /* ifbody: cmd */
#line 64 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(Tif, nil, (yyvsp[0].tree)); }
-#line 1606 "src/cmd/rc/parse.c"
+#line 1596 "src/cmd/rc/parse.c"
break;
case 15: /* ifbody: block Telse nl cmd */
#line 65 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree3(Tif, nil, (yyvsp[-3].tree), (yyvsp[-2].tree)); }
-#line 1612 "src/cmd/rc/parse.c"
+#line 1602 "src/cmd/rc/parse.c"
break;
case 16: /* case: Tcase words ';' nl cmdsln */
#line 68 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild2((yyvsp[-4].tree), (yyvsp[-3].tree), 0, (yyvsp[0].tree), 1);}
-#line 1618 "src/cmd/rc/parse.c"
+#line 1608 "src/cmd/rc/parse.c"
break;
case 17: /* casebody: %empty */
#line 71 "src/cmd/rc/syntax.y"
{ (yyval.tree) = nil; }
-#line 1624 "src/cmd/rc/parse.c"
+#line 1614 "src/cmd/rc/parse.c"
break;
case 18: /* casebody: case casebody */
#line 72 "src/cmd/rc/syntax.y"
{ (yyval.tree) = (!(yyvsp[0].tree)) ? (yyvsp[-1].tree) : maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1630 "src/cmd/rc/parse.c"
+#line 1620 "src/cmd/rc/parse.c"
break;
case 19: /* assign: executable '=' word */
#line 75 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2('=', (yyvsp[-2].tree), (yyvsp[0].tree)); }
-#line 1636 "src/cmd/rc/parse.c"
+#line 1626 "src/cmd/rc/parse.c"
break;
case 21: /* redir: Tredir word */
#line 79 "src/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 0); }
-#line 1642 "src/cmd/rc/parse.c"
+ { (yyval.tree) = hangchild1((yyvsp[-1].tree), ((yyvsp[-1].tree)->redir.type == Rhere)?heredoc((yyvsp[0].tree)):(yyvsp[0].tree), 0); }
+#line 1632 "src/cmd/rc/parse.c"
break;
case 22: /* epilog: %empty */
#line 82 "src/cmd/rc/syntax.y"
{ (yyval.tree) = nil; }
-#line 1648 "src/cmd/rc/parse.c"
+#line 1638 "src/cmd/rc/parse.c"
break;
case 23: /* epilog: redir epilog */
#line 83 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 1); }
-#line 1654 "src/cmd/rc/parse.c"
+#line 1644 "src/cmd/rc/parse.c"
break;
case 24: /* cmd: %empty */
#line 86 "src/cmd/rc/syntax.y"
{ (yyval.tree) = nil; }
-#line 1660 "src/cmd/rc/parse.c"
+#line 1650 "src/cmd/rc/parse.c"
break;
case 25: /* cmd: basic */
#line 87 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tbasic, (yyvsp[0].tree)); }
-#line 1666 "src/cmd/rc/parse.c"
+#line 1656 "src/cmd/rc/parse.c"
break;
case 26: /* cmd: block epilog */
#line 88 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangepilog((yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1672 "src/cmd/rc/parse.c"
+#line 1662 "src/cmd/rc/parse.c"
break;
case 27: /* cmd: cmd Tpipe nl cmd */
#line 89 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild2((yyvsp[-2].tree), (yyvsp[-3].tree), 0, (yyvsp[0].tree), 1); }
-#line 1678 "src/cmd/rc/parse.c"
+#line 1668 "src/cmd/rc/parse.c"
break;
case 28: /* cmd: cmd Tandand nl cmd */
#line 90 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(Tandand, (yyvsp[-3].tree), (yyvsp[0].tree)); }
-#line 1684 "src/cmd/rc/parse.c"
+#line 1674 "src/cmd/rc/parse.c"
break;
case 29: /* cmd: cmd Toror nl cmd */
#line 91 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(Toror, (yyvsp[-3].tree), (yyvsp[0].tree)); }
-#line 1690 "src/cmd/rc/parse.c"
+#line 1680 "src/cmd/rc/parse.c"
break;
case 30: /* cmd: redir cmd */
#line 92 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 1); }
-#line 1696 "src/cmd/rc/parse.c"
+#line 1686 "src/cmd/rc/parse.c"
break;
case 31: /* cmd: assign cmd */
#line 93 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 2); }
-#line 1702 "src/cmd/rc/parse.c"
+#line 1692 "src/cmd/rc/parse.c"
break;
case 32: /* cmd: Tbang cmd */
#line 94 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tbang, (yyvsp[0].tree)); }
-#line 1708 "src/cmd/rc/parse.c"
+#line 1698 "src/cmd/rc/parse.c"
break;
case 33: /* cmd: Tsubshell cmd */
#line 95 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tsubshell, (yyvsp[0].tree)); }
-#line 1714 "src/cmd/rc/parse.c"
+#line 1704 "src/cmd/rc/parse.c"
break;
case 34: /* cmd: Ttwiddle word words */
#line 96 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild2((yyvsp[-2].tree), (yyvsp[-1].tree), 0, (yyvsp[0].tree), 1); }
-#line 1720 "src/cmd/rc/parse.c"
+#line 1710 "src/cmd/rc/parse.c"
break;
case 35: /* cmd: Tfor '(' word ')' nl cmd */
#line 97 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild3((yyvsp[-5].tree), (yyvsp[-3].tree), nil, (yyvsp[0].tree)); }
-#line 1726 "src/cmd/rc/parse.c"
+#line 1716 "src/cmd/rc/parse.c"
break;
case 36: /* cmd: Tfor '(' word Tin words ')' nl cmd */
#line 98 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild3((yyvsp[-7].tree), (yyvsp[-5].tree), (yyvsp[-3].tree), (yyvsp[0].tree)); }
-#line 1732 "src/cmd/rc/parse.c"
+#line 1722 "src/cmd/rc/parse.c"
break;
case 37: /* cmd: Twhile paren nl cmd */
#line 99 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild2((yyvsp[-3].tree), (yyvsp[-2].tree), 0, (yyvsp[0].tree), 1); }
-#line 1738 "src/cmd/rc/parse.c"
+#line 1728 "src/cmd/rc/parse.c"
break;
case 38: /* cmd: Tif paren nl ifbody */
#line 100 "src/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild1((yyvsp[-2].tree), (yyvsp[-2].tree), 0); }
-#line 1744 "src/cmd/rc/parse.c"
+ { (yyval.tree) = hangchild1((yyvsp[0].tree), (yyvsp[-2].tree), 0); }
+#line 1734 "src/cmd/rc/parse.c"
break;
case 39: /* cmd: Tswitch '(' word ')' nl '{' nl casebody '}' */
#line 101 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild2((yyvsp[-8].tree), (yyvsp[-6].tree), 0, (yyvsp[-1].tree), 1); }
-#line 1750 "src/cmd/rc/parse.c"
+#line 1740 "src/cmd/rc/parse.c"
break;
case 40: /* cmd: Tfunc words block */
#line 102 "src/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild2((yyvsp[-2].tree), (yyvsp[-1].tree), 0, (yyvsp[0].tree), 1); }
-#line 1756 "src/cmd/rc/parse.c"
+#line 1746 "src/cmd/rc/parse.c"
break;
case 42: /* basic: basic word */
#line 106 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(Targs, (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1762 "src/cmd/rc/parse.c"
+#line 1752 "src/cmd/rc/parse.c"
break;
case 43: /* basic: basic redir */
#line 107 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(Targs, (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1768 "src/cmd/rc/parse.c"
+#line 1758 "src/cmd/rc/parse.c"
break;
case 45: /* atom: keyword */
#line 111 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tword, (yyvsp[0].tree)); }
-#line 1774 "src/cmd/rc/parse.c"
+#line 1764 "src/cmd/rc/parse.c"
break;
case 47: /* word: word '^' atom */
#line 115 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); }
-#line 1780 "src/cmd/rc/parse.c"
+#line 1770 "src/cmd/rc/parse.c"
break;
case 49: /* executable: executable '^' atom */
#line 119 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); }
-#line 1786 "src/cmd/rc/parse.c"
+#line 1776 "src/cmd/rc/parse.c"
break;
case 51: /* nonkeyword: '$' atom */
#line 123 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1('$', (yyvsp[0].tree)); }
-#line 1792 "src/cmd/rc/parse.c"
+#line 1782 "src/cmd/rc/parse.c"
break;
case 52: /* nonkeyword: '$' atom Tindex words ')' */
#line 124 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(Tindex, (yyvsp[-3].tree), (yyvsp[-1].tree)); }
-#line 1798 "src/cmd/rc/parse.c"
+#line 1788 "src/cmd/rc/parse.c"
break;
case 53: /* nonkeyword: '(' wordsnl ')' */
#line 125 "src/cmd/rc/syntax.y"
{ (yyval.tree) = (yyvsp[-1].tree); }
-#line 1804 "src/cmd/rc/parse.c"
+#line 1794 "src/cmd/rc/parse.c"
break;
case 54: /* nonkeyword: Tcount atom */
#line 126 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tcount, (yyvsp[0].tree)); }
-#line 1810 "src/cmd/rc/parse.c"
+#line 1800 "src/cmd/rc/parse.c"
break;
case 55: /* nonkeyword: Tjoin atom */
#line 127 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tjoin, (yyvsp[0].tree)); }
-#line 1816 "src/cmd/rc/parse.c"
+#line 1806 "src/cmd/rc/parse.c"
break;
case 56: /* nonkeyword: '`' block */
#line 128 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1('`', (yyvsp[0].tree)); }
-#line 1822 "src/cmd/rc/parse.c"
+#line 1812 "src/cmd/rc/parse.c"
break;
case 68: /* words: %empty */
#line 135 "src/cmd/rc/syntax.y"
{ (yyval.tree) = nil; }
-#line 1828 "src/cmd/rc/parse.c"
+#line 1818 "src/cmd/rc/parse.c"
break;
case 69: /* words: words word */
#line 136 "src/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(Twords, (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1834 "src/cmd/rc/parse.c"
+#line 1824 "src/cmd/rc/parse.c"
break;
case 70: /* wordsnl: %empty */
#line 139 "src/cmd/rc/syntax.y"
{ (yyval.tree) = nil; }
-#line 1840 "src/cmd/rc/parse.c"
+#line 1830 "src/cmd/rc/parse.c"
break;
case 72: /* wordsnl: wordsnl word */
#line 141 "src/cmd/rc/syntax.y"
{(yyval.tree) = (!(yyvsp[-1].tree)) ? ((!(yyvsp[0].tree)) ? nil : (yyvsp[0].tree)) : ((!(yyvsp[0].tree)) ? (yyvsp[-1].tree) : maketree2(Twords, (yyvsp[-1].tree), (yyvsp[0].tree))); }
-#line 1846 "src/cmd/rc/parse.c"
+#line 1836 "src/cmd/rc/parse.c"
break;
-#line 1850 "src/cmd/rc/parse.c"
+#line 1840 "src/cmd/rc/parse.c"
default: break;
}
@@ -1922,7 +1912,7 @@ yyerrlab:
}
yyerror (yymsgp);
if (yysyntax_error_status == YYENOMEM)
- goto yyexhaustedlab;
+ YYNOMEM;
}
}
@@ -1958,6 +1948,7 @@ yyerrorlab:
label yyerrorlab therefore never appears in user code. */
if (0)
YYERROR;
+ ++yynerrs;
/* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
@@ -2018,7 +2009,7 @@ yyerrlab1:
`-------------------------------------*/
yyacceptlab:
yyresult = 0;
- goto yyreturn;
+ goto yyreturnlab;
/*-----------------------------------.
@@ -2026,24 +2017,22 @@ yyacceptlab:
`-----------------------------------*/
yyabortlab:
yyresult = 1;
- goto yyreturn;
+ goto yyreturnlab;
-#if 1
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
+/*-----------------------------------------------------------.
+| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
+`-----------------------------------------------------------*/
yyexhaustedlab:
yyerror (YY_("memory exhausted"));
yyresult = 2;
- goto yyreturn;
-#endif
+ goto yyreturnlab;
-/*-------------------------------------------------------.
-| yyreturn -- parsing is finished, clean up and return. |
-`-------------------------------------------------------*/
-yyreturn:
+/*----------------------------------------------------------.
+| yyreturnlab -- parsing is finished, clean up and return. |
+`----------------------------------------------------------*/
+yyreturnlab:
if (yychar != YYEMPTY)
{
/* Make sure we have latest lookahead translation. See comments at
diff --git a/src/cmd/rc/parse.h b/src/cmd/rc/parse.h
index a99e118..88859ea 100644
--- a/src/cmd/rc/parse.h
+++ b/src/cmd/rc/parse.h
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.7.6. */
+/* A Bison parser, made by GNU Bison 3.8.2. */
/* Bison interface for Yacc-like parsers in C
@@ -103,6 +103,8 @@ typedef union YYSTYPE YYSTYPE;
extern YYSTYPE yylval;
+
int yyparse (void);
+
#endif /* !YY_YY_SRC_CMD_RC_PARSE_H_INCLUDED */
diff --git a/src/cmd/rc/rc.h b/src/cmd/rc/rc.h
index 0c006e3..720c6f2 100644
--- a/src/cmd/rc/rc.h
+++ b/src/cmd/rc/rc.h
@@ -32,6 +32,7 @@ enum
Rhere,
Rdupfd,
Ropen,
+ Rdup,
Rclose,
Rrdwr
};
@@ -45,7 +46,7 @@ struct Tree
char *str; // Tword
};
struct {
- ushort type; // Tpipe, Tredir, Tdup
+ ushort type; // Tpipe, Tredir, Tdup, There
int fd[2];
} redir;
};
@@ -198,10 +199,18 @@ int put(Io **, char);
void flush(Io *io);
void print(Io *, char *, ...);
+void printstr(Io *, char *);
+void printchar(Io *, int);
/* lex.c */
-int iswordchar(int c);
-int yylex(void);
+int yylex(void);
+void yyerror(const char *msg);
+
+void readhere(void);
+Tree *heredoc(Tree *);
+
+int iswordchar(int c);
+int isidentchar(int c);
/* tree.c */
Tree *maketree(void);
@@ -266,6 +275,7 @@ char **mkenv(void);
int compile(Tree *);
Code *copycode(Code *c);
void freecode(Code *c);
+void emitdelhere(char *);
/* glob.c */
#define GLOB ((char)(0x01))
diff --git a/src/cmd/rc/syntax.y b/src/cmd/rc/syntax.y
index 64ebb41..4acd92f 100644
--- a/src/cmd/rc/syntax.y
+++ b/src/cmd/rc/syntax.y
@@ -76,7 +76,7 @@ assign:
redir:
Tdup
-| Tredir word { $$ = hangchild1($1, $2, 0); }
+| Tredir word { $$ = hangchild1($1, ($1->redir.type == Rhere)?heredoc($2):$2, 0); }
epilog:
/* empty */ { $$ = nil; }
@@ -97,7 +97,7 @@ cmd:
| Tfor '(' word ')' nl cmd { $$ = hangchild3($1, $3, nil, $6); }
| Tfor '(' word Tin words ')' nl cmd { $$ = hangchild3($1, $3, $5, $8); }
| Twhile paren nl cmd { $$ = hangchild2($1, $2, 0, $4, 1); }
-| Tif paren nl ifbody { $$ = hangchild1($2, $2, 0); }
+| Tif paren nl ifbody { $$ = hangchild1($4, $2, 0); }
| Tswitch '(' word ')' nl '{' nl casebody '}' { $$ = hangchild2($1, $3, 0, $8, 1); }
| Tfunc words block { $$ = hangchild2($1, $2, 0, $3, 1); }
diff --git a/src/cmd/rc/sys.c b/src/cmd/rc/sys.c
index 807359d..a845122 100644
--- a/src/cmd/rc/sys.c
+++ b/src/cmd/rc/sys.c
@@ -94,24 +94,24 @@ execute(Word *cmd, Word *path)
void
redirect(Redir *r)
{
- if(r){
- redirect(r->link);
- switch(r->type){
- case Ropen:
- if(r->from != r->to){
- dup2(r->from, r->to);
- close(r->from);
- }
- break;
- case Rdupfd:
- dup2(r->from, r->to); // TODO: error checking
- break;
- case Rclose:
+ if(!r) return;
+ redirect(r->link);
+
+ switch(r->type){
+ case Ropen:
+ if(r->from != r->to){
+ dup2(r->from, r->to);
close(r->from);
- break;
- default:
- fatal("unrecognized redirection type %d\n", r->type);
}
+ break;
+ case Rdup:
+ dup2(r->from, r->to); // TODO: error checking
+ break;
+ case Rclose:
+ close(r->from);
+ break;
+ default:
+ fatal("unrecognized redirection type %d\n", r->type);
}
}
diff --git a/src/cmd/rc/tree.c b/src/cmd/rc/tree.c
index 2c65041..3703a25 100644
--- a/src/cmd/rc/tree.c
+++ b/src/cmd/rc/tree.c
@@ -101,11 +101,3 @@ token(int type, char *s)
return node;
}
-
-/*
-Tree*
-basic(Tree *node)
-{
- return maketree1(Tbasic, node);
-}
-*/
diff --git a/src/cmd/rc/var.c b/src/cmd/rc/var.c
index 73532f3..6004bb9 100644
--- a/src/cmd/rc/var.c
+++ b/src/cmd/rc/var.c
@@ -282,15 +282,15 @@ initpath(void)
}
#define KEYWORDS \
- KEYWORD("for", Tfor) \
- KEYWORD("in", Tin) \
- KEYWORD("while", Twhile) \
- KEYWORD("if", Tif) \
- KEYWORD("else", Telse) \
- KEYWORD("switch", Tswitch) \
- KEYWORD("case", Tcase) \
- KEYWORD("!", Tbang) \
- KEYWORD("@", Tsubshell) \
+ KEYWORD("for", Tfor) \
+ KEYWORD("in", Tin) \
+ KEYWORD("while", Twhile) \
+ KEYWORD("if", Tif) \
+ KEYWORD("else", Telse) \
+ KEYWORD("switch", Tswitch) \
+ KEYWORD("case", Tcase) \
+ KEYWORD("!", Tbang) \
+ KEYWORD("@", Tsubshell) \
KEYWORD("func", Tfunc)
void