aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-10-21 12:02:14 -0700
committerNicholas Noll <nbnoll@eml.cc>2021-10-21 12:02:14 -0700
commit79fb5e6be113678d4ef0349d2e584f219e567426 (patch)
tree48aaedc53f40329c1552eb748ad021a76ec3318c
parentfaaf40e55e002212c0c28f7845dfa2322eb7ad05 (diff)
feat(rc): string join operator
-rw-r--r--sys/cmd/rc/code.c4
-rw-r--r--sys/cmd/rc/exec.c41
-rw-r--r--sys/cmd/rc/exec.h1
-rw-r--r--sys/cmd/rc/io.c2
-rw-r--r--sys/cmd/rc/lex.c26
-rw-r--r--sys/cmd/rc/parse.c8
-rw-r--r--sys/cmd/rc/parse.h4
-rw-r--r--sys/cmd/rc/syntax.y4
8 files changed, 66 insertions, 24 deletions
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
@@ -625,6 +625,47 @@ Xconcatenate(void)
}
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)
{
int n;
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: