From 29138fff8643194ec49cb79304d2a878d46c378b Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 16 Nov 2021 12:08:59 -0800 Subject: Feat: added heredocs Heredocs are simply strings written to tmp files. There was minimal bug testing here. Also, various bug fixes are included --- src/cmd/rc/code.c | 38 +++++++++- src/cmd/rc/exec.c | 133 ++++++++++++++++++++++++++++++++- src/cmd/rc/exec.h | 8 ++ src/cmd/rc/io.c | 22 ++---- src/cmd/rc/lex.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++----- src/cmd/rc/main.c | 1 + src/cmd/rc/parse.c | 203 ++++++++++++++++++++++++--------------------------- src/cmd/rc/parse.h | 4 +- src/cmd/rc/rc.h | 16 +++- src/cmd/rc/syntax.y | 4 +- src/cmd/rc/sys.c | 32 ++++---- src/cmd/rc/tree.c | 8 -- src/cmd/rc/var.c | 18 ++--- 13 files changed, 510 insertions(+), 184 deletions(-) (limited to 'src/cmd') 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 @@ -684,12 +684,129 @@ Xmark(void) pushlist(); } +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) { @@ -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; @@ -1343,6 +1462,12 @@ Xpopredir(void) efree(r); } +void +Xdelhere(void) +{ + remove(runner->code.exe[runner->code.i++].s); +} + void Xreturn(void) { 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'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 -- cgit v1.2.1