From 79fb5e6be113678d4ef0349d2e584f219e567426 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Thu, 21 Oct 2021 12:02:14 -0700 Subject: feat(rc): string join operator --- sys/cmd/rc/code.c | 4 ++-- sys/cmd/rc/exec.c | 41 +++++++++++++++++++++++++++++++++++++++++ sys/cmd/rc/exec.h | 1 + sys/cmd/rc/io.c | 2 +- sys/cmd/rc/lex.c | 26 +++++++++++++------------- sys/cmd/rc/parse.c | 8 ++++---- sys/cmd/rc/parse.h | 4 ++-- sys/cmd/rc/syntax.y | 4 ++-- 8 files changed, 66 insertions(+), 24 deletions(-) (limited to 'sys') diff --git a/sys/cmd/rc/code.c b/sys/cmd/rc/code.c index 70fe818..46873ef 100644 --- a/sys/cmd/rc/code.c +++ b/sys/cmd/rc/code.c @@ -66,10 +66,10 @@ walk(Tree *node) emitf(Xcount); break; - case Tflat: + case Tjoin: emitf(Xmark); walk(node->child[0]); - emitf(Xflat); + emitf(Xjoin); break; case ';': diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c index ac0dc08..425d00f 100644 --- a/sys/cmd/rc/exec.c +++ b/sys/cmd/rc/exec.c @@ -624,6 +624,47 @@ Xconcatenate(void) runner->args->word = w; } +void +Xjoin(void) +{ + int n; + char *s; + Word *arg, *elt; + + if(count(runner->args->word) != 1){ + Xerror("variable name is not singleton\n"); + return; + } + + s = runner->args->word->str; + // deglob(s) + + arg = var(s)->val; + poplist(); + + n = count(arg); + if(n==0){ + pushword(""); + return; + } + + for(elt = arg; elt; elt=elt->link) + n += strlen(elt->str); + + s = emalloc(n); + if(arg){ + strcpy(s, arg->str); + for(elt = arg->link; elt; elt = elt->link){ + strcat(s, " "); + strcat(s, elt->str); + } + }else + s[0] = 0; + + pushword(s); + efree(s); +} + void Xdollar(void) { diff --git a/sys/cmd/rc/exec.h b/sys/cmd/rc/exec.h index d018fed..4bf2a4b 100644 --- a/sys/cmd/rc/exec.h +++ b/sys/cmd/rc/exec.h @@ -20,6 +20,7 @@ void Xasync(void); void Xbasic(void); // Xbasic(args) run command and wait for result void Xsubshell(void); void Xword(void); +void Xjoin(void); void Xconcatenate(void); void Xcount(void); void Xflat(void); diff --git a/sys/cmd/rc/io.c b/sys/cmd/rc/io.c index f033031..dc81c2e 100644 --- a/sys/cmd/rc/io.c +++ b/sys/cmd/rc/io.c @@ -230,7 +230,6 @@ printtree(Io *io, Tree *t) switch(t->type){ default: print(io, "bad(%d)[%p %p %p]", t->type, C0, C1, C2); break; case '$': print(io,"$%t",C0); break; - case '"': print(io,"\"%t",C0); break; case '&': print(io,"%t&",C0); break; case '^': print(io,"%t^%t",C0,C1); break; case '`': print(io,"`%t",C0); break; @@ -240,6 +239,7 @@ printtree(Io *io, Tree *t) case Tblock: print(io, "{%t}", C0); break; case Tcount: print(io, "$#%t", C0); break; case Tparen: print(io, "(%t)", C0); break; + case Tjoin: print(io,"$\"%t",C0); break; case Tindex: print(io, "%t(%t)",C0); break; case Tsubshell: print(io, "@ %t",C0); break; //case Ttwiddle: print(io, "~ %t %t", C0, C1); break; diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c index 8ddf270..5de238e 100644 --- a/sys/cmd/rc/lex.c +++ b/sys/cmd/rc/lex.c @@ -217,6 +217,19 @@ yylex(void) put3('E','O','F'); return EOF; + case '$': + lexer.haddollar = 1; + if(nextis('#')){ + put2('$','#'); + return Tcount; + } + if(nextis('^')){ + put2('$','^'); + return Tjoin; + } + put1('$'); + return '$'; + case '@': lexer.haddollar = 0; put1('@'); @@ -324,19 +337,6 @@ yylex(void) return node->type; - case '$': - lexer.haddollar = 1; - if(nextis('#')){ - put2('$','#'); - return Tcount; - } - if(nextis('^')){ - put2('$','^'); - return Tflat; - } - put1('$'); - return '$'; - case '\'': lexer.hadword = 1; lexer.inquote = 1; diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c index 731c244..d1909a5 100644 --- a/sys/cmd/rc/parse.c +++ b/sys/cmd/rc/parse.c @@ -127,7 +127,7 @@ enum yysymbol_kind_t YYSYMBOL_22_ = 22, /* '^' */ YYSYMBOL_23_ = 23, /* '$' */ YYSYMBOL_Tcount = 24, /* Tcount */ - YYSYMBOL_Tflat = 25, /* Tflat */ + YYSYMBOL_Tjoin = 25, /* Tjoin */ YYSYMBOL_26_ = 26, /* '(' */ YYSYMBOL_27_ = 27, /* ')' */ YYSYMBOL_28_ = 28, /* '{' */ @@ -567,7 +567,7 @@ static const char *const yytname[] = "\"end of file\"", "error", "\"invalid token\"", "Tword", "Twords", "Tif", "Telse", "Tbang", "Tsubshell", "Toror", "Tandand", "There", "Tredir", "Tpipe", "Tdup", "Tbasic", "Tparen", "Tblock", "Targs", - "Tindex", "Twhile", "'\\n'", "'^'", "'$'", "Tcount", "Tflat", "'('", + "Tindex", "Twhile", "'\\n'", "'^'", "'$'", "Tcount", "Tjoin", "'('", "')'", "'{'", "'}'", "';'", "'&'", "'='", "$accept", "rc", "line", "body", "paren", "block", "cmds", "cmdsln", "ifbody", "assign", "redir", "epilog", "cmd", "basic", "atom", "word", "executable", "nonkeyword", @@ -1625,9 +1625,9 @@ yyreduce: #line 1626 "sys/cmd/rc/parse.c" break; - case 43: /* nonkeyword: Tflat atom */ + case 43: /* nonkeyword: Tjoin atom */ #line 111 "sys/cmd/rc/syntax.y" - { (yyval.tree) = maketree1(Tflat, (yyvsp[0].tree)); } + { (yyval.tree) = maketree1(Tjoin, (yyvsp[0].tree)); } #line 1632 "sys/cmd/rc/parse.c" break; diff --git a/sys/cmd/rc/parse.h b/sys/cmd/rc/parse.h index ef389bc..64d567a 100644 --- a/sys/cmd/rc/parse.h +++ b/sys/cmd/rc/parse.h @@ -73,7 +73,7 @@ extern int yydebug; Tindex = 274, /* Tindex */ Twhile = 275, /* Twhile */ Tcount = 276, /* Tcount */ - Tflat = 277 /* Tflat */ + Tjoin = 277 /* Tjoin */ }; typedef enum yytokentype yytoken_kind_t; #endif @@ -101,7 +101,7 @@ extern int yydebug; #define Tindex 274 #define Twhile 275 #define Tcount 276 -#define Tflat 277 +#define Tjoin 277 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED diff --git a/sys/cmd/rc/syntax.y b/sys/cmd/rc/syntax.y index 76bcd88..b486484 100644 --- a/sys/cmd/rc/syntax.y +++ b/sys/cmd/rc/syntax.y @@ -17,7 +17,7 @@ %left Tbang Tsubshell %left Tpipe; %left '^'; -%right '$' Tcount Tflat +%right '$' Tcount Tjoin %left Tindex /* semantic types */ @@ -108,7 +108,7 @@ nonkeyword: | '$' atom { $$ = maketree1('$', $2); } | '(' wordsnl ')' { $$ = $2; } | Tcount atom { $$ = maketree1(Tcount, $2); } -| Tflat atom { $$ = maketree1(Tflat, $2); } +| Tjoin atom { $$ = maketree1(Tjoin, $2); } //| '`' block { $$ = maketree1('`', $2); } keyword: -- cgit v1.2.1