diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-05-06 13:53:33 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-05-06 13:53:33 +0300 |
commit | 338c8ebdfc70c653a674df628cf9c876b5c54267 (patch) | |
tree | daba1bc56d64e8a919c30b51d09719991fa3b705 | |
parent | 90d064900d35975950587882a00cfe92b26d94bd (diff) | |
download | rush-338c8ebdfc70c653a674df628cf9c876b5c54267.tar.gz rush-338c8ebdfc70c653a674df628cf9c876b5c54267.tar.bz2 |
Improve parser. Add more tests.
* src/cf.c: New global option "expand-undefined".
(global_attrib_set): Handle the 'b' data type marker.
* src/cf.h (expand_undefined): New extern.
* src/cfgram.y: Provide textual descriptions for named tokens.
Require '=' or '=~' between identifier and value in SET and SETENV
rules. Allow for values in UNSETENV list.
* src/cflex.l: Accept slashes in unquoted strings.
Gracefully handle undefined escape sequences in strings.
* src/map.c (expand_undefined): New global.
(rush_expand_string): Expand undefined variables to empty strings
if expand_undefined is set.
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Add new tests.
* tests/backref.at: New file.
* tests/clrenv.at: New file.
* tests/keepenv.at: New file.
* tests/regexp.at: New file.
* tests/setenv.at: New file.
* tests/setvar.at: New file.
* tests/undef.at: New file.
-rw-r--r-- | src/cf.c | 17 | ||||
-rw-r--r-- | src/cf.h | 1 | ||||
-rw-r--r-- | src/cfgram.y | 124 | ||||
-rw-r--r-- | src/cflex.l | 32 | ||||
-rw-r--r-- | src/map.c | 5 | ||||
-rw-r--r-- | tests/Makefile.am | 9 | ||||
-rw-r--r-- | tests/backref.at | 43 | ||||
-rw-r--r-- | tests/clrenv.at | 34 | ||||
-rw-r--r-- | tests/fallthrough.at | 6 | ||||
-rw-r--r-- | tests/keepenv.at | 40 | ||||
-rw-r--r-- | tests/regexp.at | 88 | ||||
-rw-r--r-- | tests/set.at | 10 | ||||
-rw-r--r-- | tests/setenv.at | 130 | ||||
-rw-r--r-- | tests/setvar.at | 43 | ||||
-rw-r--r-- | tests/testsuite.at | 17 | ||||
-rw-r--r-- | tests/transform.at | 8 | ||||
-rw-r--r-- | tests/undef.at | 65 | ||||
-rw-r--r-- | tests/unsetenv.at | 76 | ||||
-rw-r--r-- | tests/unsetvar.at | 46 |
19 files changed, 723 insertions, 71 deletions
@@ -862,6 +862,13 @@ glattrib_acct_umask(int argc, struct argval *arg) return parse_file_mode(arg->strval, &rushdb_umask, &arg->loc); } +static int +glattrib_expand_undef(int argc, struct argval *arg) +{ + expand_undefined = arg->intval; + return 0; +} + static struct global_attrib global_attrib[] = { { "debug", "n", glattrib_debug }, { "sleep-time", "n", glattrib_sleep_time }, @@ -871,6 +878,7 @@ static struct global_attrib global_attrib[] = { { "acct-file-mode", "s", glattrib_acct_file_mode }, { "acct-dir-mode", "s", glattrib_acct_dir_mode }, { "acct-umask", "s", glattrib_acct_umask }, + { "expand-undefined", "b", glattrib_expand_undef }, { NULL } }; @@ -906,6 +914,15 @@ global_attrib_set(struct global_attrib *glatt, case 's': i++; break; + case 'b': + if (get_bool(arg->strval, &arg->intval)) { + cferror(loc, + _("expected boolean value, but found `%s'"), + arg->strval); + return 1; + } + i++; + break; case '.': break; case 0: @@ -152,6 +152,7 @@ void global_attrib_set(struct global_attrib *glatt, extern int re_flags; +extern int expand_undefined; extern struct cfloc curloc; void trimws(char *s); diff --git a/src/cfgram.y b/src/cfgram.y index 052dae6..386608f 100644 --- a/src/cfgram.y +++ b/src/cfgram.y @@ -1,4 +1,4 @@ -/* This file is part of GNU Rush. +/* This file is part of GNU Rush. Copyright (C) 2008-2019 Sergey Poznyakoff GNU Rush is free software; you can redistribute it and/or modify @@ -20,11 +20,12 @@ static int errors; int re_flags = REG_EXTENDED; static struct rush_rule *current_rule; -struct name_entry { - struct name_entry *next; +struct asgn { + struct asgn *next; char *name; + char *value; }; -static void add_name_list(struct name_entry *head, enum envar_type type); +static void add_asgn_list(struct asgn *head, enum envar_type type); %} %error-verbose @@ -45,10 +46,11 @@ static void add_name_list(struct name_entry *head, enum envar_type type); int start; int end; } range; + struct asgn *asgn; struct { - struct name_entry *head; - struct name_entry *tail; - } name_list; + struct asgn *head; + struct asgn *tail; + } asgn_list; struct limits_rec *lrec; rule_attrib_setter_t attrib; struct global_attrib *global_attrib; @@ -85,10 +87,23 @@ static void add_name_list(struct name_entry *head, enum envar_type type); %token <global_attrib> GLATTRIB "global attribute" %token BOGUS "erroneous token" +%token OR "||" +%token AND "&&" +%token NOT "!" +%token EQ "==" +%token NE "!=" +%token LT "<" +%token LE "<=" +%token GT ">" +%token GE ">=" +%token XF "=~" +%token IN "in" +%token MEMBER "member" + %left OR %left AND %left NOT -%nonassoc EQ NE LT LE GT GE '~' IN MEMBER +%nonassoc EQ NE LT LE GT GE XF '~' IN MEMBER %type <intval> fdescr index %type <str> literal string value defval ruleid @@ -96,18 +111,19 @@ static void add_name_list(struct name_entry *head, enum envar_type type); %type <node> expr compound_cond simple_cond %type <range> range %type <lrec> resource_limits -%type <name_list> name_list +%type <asgn> asgn +%type <asgn_list> asgn_list %type <strlist> strlist %type <arg> arg %type <arglist> arglist %% rcfile : PREFACE EOL content - { + { if (errors) YYERROR; } - | BOGUS + | BOGUS { if (parse_old_rc()) YYERROR; @@ -115,11 +131,11 @@ rcfile : PREFACE EOL content ; content : /* empty */ - | rulelist - ; + | rulelist + ; rulelist : rule - | rulelist rule + | rulelist rule ; rule : rulehdr rulebody @@ -183,10 +199,10 @@ rulehdr : RULE ruleid EOL ; ruleid : /* empty */ - { + { $$ = NULL; } - | string + | string ; rulebody : stmt @@ -202,8 +218,8 @@ stmt : match_stmt EOL | include_stmt EOL | flowctl_stmt EOL | attrib_stmt EOL - | error { skiptoeol(); } EOL - { + | error { skiptoeol(); } EOL + { restorenormal(); yyerrok; yyclearin; @@ -356,17 +372,17 @@ regex : string /* ****************** Set statement ****************** */ -set_stmt : SET index value +set_stmt : SET index '=' value { struct transform_node *node; node = new_transform_node(current_rule, transform_set); node->target.type = target_arg; node->target.v.arg = $2; - node->v.xf.pattern = $3; + node->v.xf.pattern = $4; node->v.xf.trans = NULL; } - | SET index '~' value + | SET index XF value { struct transform_node *node; @@ -376,17 +392,17 @@ set_stmt : SET index value node->v.xf.pattern = NULL; node->v.xf.trans = compile_transform_expr($4, re_flags); } - | SET index string '~' value + | SET index '=' string '~' value { struct transform_node *node; node = new_transform_node(current_rule, transform_set); node->target.type = target_arg; node->target.v.arg = $2; - node->v.xf.pattern = $3; - node->v.xf.trans = compile_transform_expr($5, re_flags); + node->v.xf.pattern = $4; + node->v.xf.trans = compile_transform_expr($6, re_flags); } - | SET IDENT value + | SET IDENT '=' value { struct transform_node *node; @@ -401,10 +417,10 @@ set_stmt : SET index value node->target.type = target_var; node->target.v.name = $2; } - node->v.xf.pattern = $3; + node->v.xf.pattern = $4; node->v.xf.trans = NULL; } - | SET IDENT '~' value + | SET IDENT XF value { struct transform_node *node; @@ -422,7 +438,7 @@ set_stmt : SET index value node->v.xf.pattern = NULL; node->v.xf.trans = compile_transform_expr($4, re_flags); } - | SET IDENT string '~' value + | SET IDENT '=' string '~' value { struct transform_node *node; @@ -437,8 +453,8 @@ set_stmt : SET index value node->target.type = target_var; node->target.v.name = $2; } - node->v.xf.pattern = $3; - node->v.xf.trans = compile_transform_expr($5, re_flags); + node->v.xf.pattern = $4; + node->v.xf.trans = compile_transform_expr($6, re_flags); } | UNSET IDENT { @@ -626,37 +642,47 @@ environ_stmt: CLRENV { current_rule->clrenv = 1; } - | SETENV IDENT string + | SETENV IDENT '=' string { new_envar(current_rule, $2, strlen($2), - $3, strlen($3), + $4, strlen($4), envar_set); } - | UNSETENV name_list + | UNSETENV asgn_list { - add_name_list($2.head, envar_unset); + add_asgn_list($2.head, envar_unset); } - | KEEPENV name_list + | KEEPENV asgn_list { - add_name_list($2.head, envar_keep); + add_asgn_list($2.head, envar_keep); } ; -name_list : IDENT +asgn_list : asgn { - struct name_entry *np = xmalloc(sizeof(*np)); - np->next = NULL; - np->name = $1; - $$.head = $$.tail = np; + $$.head = $$.tail = $1; } - | name_list IDENT + | asgn_list asgn { - struct name_entry *np = xmalloc(sizeof(*np)); - np->next = NULL; - np->name = $2; - LIST_APPEND(np, $1.head, $1.tail); - $$ = $1; + LIST_APPEND($2, $1.head, $1.tail); + $$ = $1; + } + ; + +asgn : IDENT + { + $$ = xmalloc(sizeof(*$$)); + $$->next = NULL; + $$->name = $1; + $$->value = NULL; + } + | IDENT '=' value + { + $$ = xmalloc(sizeof(*$$)); + $$->next = NULL; + $$->name = $1; + $$->value = $3; } ; @@ -759,12 +785,12 @@ new_envar(struct rush_rule *rule, } static void -add_name_list(struct name_entry *head, enum envar_type type) +add_asgn_list(struct asgn *head, enum envar_type type) { for (; head; head = head->next) { new_envar(current_rule, head->name, strlen(head->name), - NULL, 0, + head->value, head->value ? strlen(head->value) : 0, type); free(head->name); } diff --git a/src/cflex.l b/src/cflex.l index a6f03c2..8d57f5b 100644 --- a/src/cflex.l +++ b/src/cflex.l @@ -171,7 +171,7 @@ rush[ \t]+2\.0[ \t]*$ { return tok(IDENT); } } -. { straychar(yytext[0]); skiptoeol(); } +. return yytext[0]; } <ARGS,INMATCH>{ @@ -180,7 +180,7 @@ rush[ \t]+2\.0[ \t]*$ { return tok(NUMBER); } [A-Za-z_][A-Za-z0-9_-]* { yylval.str = xstrdup(yytext); return tok(IDENT); } -[A-Za-z_+-][A-Za-z0-9_-]* { yylval.str = xstrdup(yytext); +[A-Za-z_/+-][A-Za-z0-9_/+-]* { yylval.str = xstrdup(yytext); return tok(STRING); } \$[A-Za-z_][A-Za-z_0-9-]* { yylval.str = xstrdup(yytext); return tok(STRING); } @@ -233,7 +233,17 @@ rush[ \t]+2\.0[ \t]*$ { strtoul(yytext + yyleng - 2, NULL, 16)); pushstart(QSTR); } -"~"|"("|")"|"["|"]" return tok(yytext[0]); +\"[^\\\"\n]*\\. { struct cfloc loc; + loc.beg = loc.end = curloc.end; + loc.beg.column -= 2; + cferror(&loc, + _("unrecognized escape \\%c"), + yytext[yyleng - 1]); + stringbuf_init(&sb); + stringbuf_add_array(&sb, yytext + 1, yyleng - 1); + pushstart(QSTR); } +"=~" return tok(XF); +. return yytext[0]; } <QSTR>{ @@ -261,8 +271,17 @@ rush[ \t]+2\.0[ \t]*$ { stringbuf_add_char(&sb, strtoul(yytext + yyleng - 2, NULL, 16)); } +[^\\\"\n]*\\. { struct cfloc loc; + loc.beg = loc.end = curloc.end; + loc.beg.column -= 2; + cferror(&loc, + _("unrecognized escape \\%c"), + yytext + yyleng - 1); + stringbuf_init(&sb); + stringbuf_add_array(&sb, yytext, yyleng); } \n { advance_line(1); yyerror("unescaped newline in quoted string"); } +. { straychar(yytext[0]); } } <VAR>{ @@ -302,11 +321,10 @@ rush[ \t]+2\.0[ \t]*$ { strtoul(yytext + yyleng - 2, NULL, 16)); pushstart(QSTR); } -[^}\"\$%]+ { stringbuf_add_array(&sb, yytext, yyleng); } +[^}\"\$%]+ { stringbuf_add_array(&sb, yytext, yyleng); } +. { straychar(yytext[0]); + stringbuf_add_char(&sb, yytext[0]); } } - -<INMATCH,ARGS,VAR,QSTR>. { straychar(yytext[0]); - return tok(BOGUS); } %% void straychar(int c) @@ -16,6 +16,9 @@ #include <rush.h> +/* Set to 1 if expansion of undefined variables is allowed */ +int expand_undefined; + static inline int d2n(int d) { @@ -252,7 +255,7 @@ rush_expand_string(const char *string, struct rush_request *req) struct wordsplit ws; int wsflags = WRDSF_NOSPLIT | WRDSF_NOCMD - | WRDSF_UNDEF + | (expand_undefined ? 0: WRDSF_UNDEF) | WRDSF_GETVAR | WRDSF_CLOSURE; char *result; diff --git a/tests/Makefile.am b/tests/Makefile.am index c0877e8..c61ddd9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -63,6 +63,15 @@ TESTSUITE_AT = \ interactive.at\ fallthrough.at\ error.at\ + clrenv.at\ + unsetenv.at\ + keepenv.at\ + setenv.at\ + backref.at\ + setvar.at\ + unsetvar.at\ + undef.at\ + regexp.at\ legacy/argc.at\ legacy/backref.at\ legacy/chdir.at\ diff --git a/tests/backref.at b/tests/backref.at new file mode 100644 index 0000000..a707d5d --- /dev/null +++ b/tests/backref.at @@ -0,0 +1,43 @@ +# This file is part of GNU Rush. +# Copyright (C) 2019 Sergey Poznyakoff +# +# GNU Rush is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Rush is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Rush. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([Back-reference expansion]) +AT_KEYWORDS([backref]) + +AT_RUSH_TEST([ +rush 2.0 +rule chdir + match \$command ~ "^cd \"(.+)\" && (runcom .*)$" + chdir %1 + set command = %2 + fall-through + +rule runcom + match \$0 == runcom + set [0] = "./bin/runcom" +], +[cmdline,home_dir], +[cd "$PWD" && runcom test], +[0], +[{ + "cmdline":"./bin/runcom test", + "home_dir":"$TESTDIR" +} +], +[]) + +AT_CLEANUP + diff --git a/tests/clrenv.at b/tests/clrenv.at new file mode 100644 index 0000000..80c8acc --- /dev/null +++ b/tests/clrenv.at @@ -0,0 +1,34 @@ +# This file is part of GNU Rush. +# Copyright (C) 2016-2019 Sergey Poznyakoff +# +# GNU Rush is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Rush is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Rush. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([clrenv]) +AT_KEYWORDS([clrenv]) + +AT_RUSH_TEST([ +rush 2.0 +rule + clrenv +], +[environ], +[command], +[0], +[{ + "environ":[[]] +} +], +[]) + +AT_CLEANUP diff --git a/tests/fallthrough.at b/tests/fallthrough.at index 787bcc1..e7f1aab 100644 --- a/tests/fallthrough.at +++ b/tests/fallthrough.at @@ -20,11 +20,11 @@ AT_KEYWORDS([fallthrough fall-through]) AT_RUSH_TEST([ rush 2.0 rule - set [0] newcommand + set [0] = newcommand fall-through rule - set [1] list + set [1] = list ], [cmdline,argv], [command], @@ -46,7 +46,7 @@ rule fall-through rule - set [0] newcommand + set [0] = newcommand interactive true ], [cmdline,interactive,home_dir], diff --git a/tests/keepenv.at b/tests/keepenv.at new file mode 100644 index 0000000..a3e1c4a --- /dev/null +++ b/tests/keepenv.at @@ -0,0 +1,40 @@ +# This file is part of GNU Rush. +# Copyright (C) 2016-2019 Sergey Poznyakoff +# +# GNU Rush is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Rush is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Rush. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([keepenv]) +AT_KEYWORDS([keepenv]) + +m4_pushdef([RUSH_ENVIRON],[-i HOME=$PWD USER=$MY_USER LOGIN=NO_$MY_USER PATH=$PATH]) +AT_RUSH_TEST([ +rush 2.0 +rule + clrenv + keepenv HOME USER +], +[environ], +[command], +[0], +[{ + "environ":[[ + "HOME=$TESTDIR", + "USER=$MY_USER" + ]] +} +], +[]) +m4_popdef([RUSH_ENVIRON]) + +AT_CLEANUP diff --git a/tests/regexp.at b/tests/regexp.at new file mode 100644 index 0000000..1708471 --- /dev/null +++ b/tests/regexp.at @@ -0,0 +1,88 @@ +# This file is part of GNU Rush. +# Copyright (C) 2019 Sergey Poznyakoff +# +# GNU Rush is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Rush is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Rush. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([regexp options]) +AT_KEYWORDS([match regexp]) + +AT_RUSH_TEST([ +rush 2.0 +rule + match \$command ~ "fo+\$" +], +[cmdline,argv], +[ls foo], +[0], +[{ + "cmdline":"ls foo", + "argv":[[ + "ls", + "foo" + ]] +} +], +[]) + +AT_RUSH_TEST([ +rush 2.0 +global + regexp basic +rule + match \$command ~ "fo+\$" +], +[cmdline,argv], + +[ls foo], +[1], +[], +[rush: Error: no matching rule for "ls foo", user $MY_USER +], + +[ls fo+], +[0], +[{ + "cmdline":"ls fo+", + "argv":[[ + "ls", + "fo+" + ]] +} +], +[]) + +AT_RUSH_TEST([ +rush 2.0 +global + regexp basic ignore-case +rule + match \$command ~ "fo+\$" +], +[cmdline,argv], + +[ls Fo+], +[0], +[{ + "cmdline":"ls Fo+", + "argv":[[ + "ls", + "Fo+" + ]] +} +], +[]) + + +AT_CLEANUP + diff --git a/tests/set.at b/tests/set.at index 668945d..599f73d 100644 --- a/tests/set.at +++ b/tests/set.at @@ -20,7 +20,7 @@ AT_KEYWORDS([set]) AT_RUSH_TEST([ rush 2.0 rule - set command "ls /" + set command = "ls /" ], [cmdline,argv,prog], [echo], @@ -39,7 +39,7 @@ rule AT_RUSH_TEST([ rush 2.0 rule - set [0] "/usr/bin/\$0" + set [0] = "/usr/bin/\$0" ], [cmdline,argv,prog], [ls /], @@ -58,7 +58,7 @@ rule AT_RUSH_TEST([ rush 2.0 rule - set [1] "/chroot\${1}" + set [1] = "/chroot\${1}" ], [cmdline,argv,prog], [ls /], @@ -77,7 +77,7 @@ rule AT_RUSH_TEST([ rush 2.0 rule - set program "/usr/bin/ls" + set program = "/usr/bin/ls" ], [cmdline,argv,prog], [ls /], @@ -96,7 +96,7 @@ rule AT_RUSH_TEST([ rush 2.0 rule - set [-1] "/tmp" + set [-1] = "/tmp" ], [cmdline,argv,prog], [ls /], diff --git a/tests/setenv.at b/tests/setenv.at new file mode 100644 index 0000000..66ad12b --- /dev/null +++ b/tests/setenv.at @@ -0,0 +1,130 @@ +# This file is part of GNU Rush. +# Copyright (C) 2016-2019 Sergey Poznyakoff +# +# GNU Rush is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Rush is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Rush. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([setenv]) +AT_KEYWORDS([setenv]) + +m4_pushdef([RUSH_ENVIRON],[-i HOME=$PWD USER=$MY_USER]) +AT_RUSH_TEST([ +rush 2.0 +rule + setenv NEWVAR=foo +], +[environ], +[command], +[0], +[{ + "environ":[[ + "HOME=$TESTDIR", + "NEWVAR=foo", + "USER=$MY_USER" + ]] +} +], +[]) +m4_popdef([RUSH_ENVIRON]) + +m4_pushdef([RUSH_ENVIRON],[-i]) +AT_RUSH_TEST([ +rush 2.0 +rule + setenv MYPATH="\${MYPATH:-}\${MYPATH+:}/usr/local/bin" +], +[environ], +[command], +[0], +[{ + "environ":[[ + "MYPATH=/usr/local/bin" + ]] +} +], +[]) +m4_popdef([RUSH_ENVIRON]) + +m4_pushdef([RUSH_ENVIRON],[-i MYPATH=/bin:/usr/bin]) +AT_RUSH_TEST([ +rush 2.0 +rule + setenv MYPATH="\${MYPATH:-}\${MYPATH+:}/usr/local/bin" +], +[environ], +[command], +[0], +[{ + "environ":[[ + "MYPATH=/bin:/usr/bin:/usr/local/bin" + ]] +} +], +[]) +m4_popdef([RUSH_ENVIRON]) + +m4_pushdef([RUSH_ENVIRON],[-i]) +AT_RUSH_TEST([ +rush 2.0 +rule + setenv MYPATH="/usr/local/bin\${MYPATH+:}\${MYPATH:-}" +], +[environ], +[command], +[0], +[{ + "environ":[[ + "MYPATH=/usr/local/bin" + ]] +} +], +[]) +m4_popdef([RUSH_ENVIRON]) + +m4_pushdef([RUSH_ENVIRON],[-i MYPATH=/bin:/usr/bin]) +AT_RUSH_TEST([ +rush 2.0 +rule + setenv MYPATH="/usr/local/bin\${MYPATH+:}\$MYPATH" +], +[environ], +[command], +[0], +[{ + "environ":[[ + "MYPATH=/usr/local/bin:/bin:/usr/bin" + ]] +} +], +[]) +m4_popdef([RUSH_ENVIRON]) + +m4_pushdef([RUSH_ENVIRON],[-i MYPATH=/bin:/usr/bin]) +AT_RUSH_TEST([ +rush 2.0 +rule + setenv MYPATH="/usr/local/bin:\$MYPATH" +], +[environ], +[command], +[0], +[{ + "environ":[[ + "MYPATH=/usr/local/bin:/bin:/usr/bin" + ]] +} +], +[]) +m4_popdef([RUSH_ENVIRON]) + +AT_CLEANUP diff --git a/tests/setvar.at b/tests/setvar.at new file mode 100644 index 0000000..3017f63 --- /dev/null +++ b/tests/setvar.at @@ -0,0 +1,43 @@ +# This file is part of GNU Rush. +# Copyright (C) 2019 Sergey Poznyakoff +# +# GNU Rush is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Rush is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Rush. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([setvar]) +AT_KEYWORDS([setvar]) +AT_RUSH_TEST([ +rush 2.0 +rule first + set home = "$PWD" + set count = 1 + set FOO = bar + fall-through + +rule last + set command = "\$FOO \$count" +], +[cmdline,vars], +[ls], +[0], +[{ + "cmdline":"bar 1", + "vars":{ + "FOO":"bar", + "count":"1", + "home":"$TESTDIR" + } +} +], +[]) +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 61b348c..e10d4b8 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -56,12 +56,16 @@ AT_INIT AT_TESTED([rush]) m4_include([null.at]) +m4_include([setvar.at]) +m4_include([unsetvar.at]) +m4_include([undef.at]) AT_BANNER([Simple Conditions]) m4_include([argc.at]) m4_include([command.at]) m4_include([matcharg.at]) m4_include([matchprog.at]) +m4_include([regexp.at]) m4_include([uid.at]) m4_include([user.at]) m4_include([in.at]) @@ -85,12 +89,21 @@ m4_include([newgrp.at]) m4_include([chdir.at]) m4_include([interactive.at]) -AT_BANNER([Flow control]) +AT_BANNER([Environment]) +m4_include([clrenv.at]) +m4_include([unsetenv.at]) +m4_include([keepenv.at]) +m4_include([setenv.at]) -AT_BANNER([Legacy configuration]) +AT_BANNER([Features]) +m4_include([backref.at]) + +AT_BANNER([Flow control]) m4_include([fallthrough.at]) m4_include([error.at]) +AT_BANNER([Legacy configuration]) + dnl AT_BANNER([Conditionals]) m4_include([legacy/argc.at]) m4_include([legacy/command.at]) diff --git a/tests/transform.at b/tests/transform.at index bbd0fb1..ee56448 100644 --- a/tests/transform.at +++ b/tests/transform.at @@ -20,7 +20,7 @@ AT_KEYWORDS([transform]) AT_RUSH_TEST([ rush 2.0 rule - set command ~ "s/^[^[:space:]]+/& -t/" + set command =~ "s/^[^[:space:]]+/& -t/" ], [cmdline,argv,prog], [svnserve], @@ -39,7 +39,7 @@ rule AT_RUSH_TEST([ rush 2.0 rule - set command "\${command} end" ~ "s/[[:space:]]+-[^[:space:]]+//g" + set command = "\${command} end" ~ "s/[[:space:]]+-[^[:space:]]+//g" ], [cmdline,argv,prog], [echo -c -t foo -n bar], @@ -60,7 +60,7 @@ rule AT_RUSH_TEST([ rush 2.0 rule - set [0] ~ "s|^[^/]|/usr/bin/&|" + set [0] =~ "s|^[^/]|/usr/bin/&|" ], [cmdline,argv,prog], [echo foo], @@ -92,7 +92,7 @@ rule AT_RUSH_TEST([ rush 2.0 rule - set [0] \$program ~ "s,.*/,-," + set [0] = \$program ~ "s,.*/,-," ], [cmdline,argv,prog], [/bin/sh], diff --git a/tests/undef.at b/tests/undef.at new file mode 100644 index 0000000..015dd52 --- /dev/null +++ b/tests/undef.at @@ -0,0 +1,65 @@ +# This file is part of GNU Rush. +# Copyright (C) 2019 Sergey Poznyakoff +# +# GNU Rush is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Rush is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Rush. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([expanding undefined variables]) +AT_KEYWORDS([undef]) + +m4_pushdef([RUSH_ENVIRON],[-i]) +AT_RUSH_TEST([ +rush 2.0 +rule first + set command = \$COMMAND +], +[cmdline], +[ls], +[1], +[], +[rush: Error: undefined variable +]) + +AT_RUSH_TEST([ +rush 2.0 +rule first + set command = \${COMMAND:-\$command} +], +[cmdline], +[ls], +[0], +[{ + "cmdline":"ls" +} +], +[]) + +AT_RUSH_TEST([ +rush 2.0 +global + expand-undefined true + +rule first + set command = \$COMMAND +], +[cmdline], +[ls], +[0], +[{ + "cmdline":"" +} +], +[]) +m4_popdef([RUSH_ENVIRON]) + +AT_CLEANUP < |