aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-10-19 14:16:54 -0700
committerNicholas Noll <nbnoll@eml.cc>2021-10-19 14:16:54 -0700
commit6d50d5b97d49a74a8faf587ec2bbf234626adf0c (patch)
treeff09e03ad96fc873b10027120f38a2ae382ae916
parent2b53bca326decd50012883f0cff3b5316a3e100d (diff)
Feat(rc): added subshell commands and cd builtin
Slowly chipping away at a decent feature list. Subshell commands are executed by @{ ... }.
-rw-r--r--sys/cmd/rc/code.c12
-rw-r--r--sys/cmd/rc/exec.c86
-rw-r--r--sys/cmd/rc/exec.h5
-rw-r--r--sys/cmd/rc/lex.c8
-rw-r--r--sys/cmd/rc/parse.c334
-rw-r--r--sys/cmd/rc/parse.h36
-rw-r--r--sys/cmd/rc/rc.h3
-rw-r--r--sys/cmd/rc/syntax.y10
-rw-r--r--sys/cmd/rc/wait.c107
9 files changed, 366 insertions, 235 deletions
diff --git a/sys/cmd/rc/code.c b/sys/cmd/rc/code.c
index 719e63b..38cc06a 100644
--- a/sys/cmd/rc/code.c
+++ b/sys/cmd/rc/code.c
@@ -110,6 +110,18 @@ walk(Tree *node)
storepc(addr);
break;
+ case Tsubshell:
+ emitf(Xsubshell);
+ addr = emiti(0);
+ walk(node->child[0]);
+ emitf(Xexit);
+ storepc(addr);
+ break;
+
+ case Tbang:
+ walk(node->child[0]);
+ emitf(Xbang);
+
case Tword:
emitf(Xword);
emits(strdup(node->str));
diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c
index 37c289b..217f7ee 100644
--- a/sys/cmd/rc/exec.c
+++ b/sys/cmd/rc/exec.c
@@ -17,6 +17,7 @@ static Word nullpath = { .str="", .link=nil };
struct Builtin builtin[]={
{".", xdot},
+ {"cd", xcd},
{"fg", xfg},
{"jobs", xjob},
0,
@@ -326,7 +327,7 @@ xdot(void)
Thread *old;
char file[512];
- popword();
+ popword(); // "."
#if 0
if(proc->args->word && strcmp(proc->args->word->str, "-i")==0){
iflag = 1;
@@ -383,6 +384,49 @@ xdot(void)
}
void
+xcd(void)
+{
+ Word *arg;
+ Word *cdpath;
+ char dir[512];
+
+ popword(); // cd
+
+ arg = runner->args->word;
+ switch(count(arg)){
+ default:
+ print(shell.err, "usage: cd [directory]\n");
+ break;
+ case 0:
+ arg = var("home")->val;
+ if(count(arg) >= 1){
+ if(chdir(arg->str) < 0)
+ print(shell.err, "failed cd: %s\n", strerror(errno));
+ }else{
+ print(shell.err, "ambiguous cd: $home empty\n");
+ }
+ break;
+
+ case 1:
+ // TODO: add cdpath
+ cdpath = &nullpath;
+ for(; cdpath; cdpath = cdpath->link){
+ strcpy(dir, cdpath->str);
+ if(dir[0])
+ strcat(dir,"/");
+ strcat(dir, arg->str);
+ if(chdir(dir) < 0){
+ print(shell.err, "failed cd %s: %s\n", dir, strerror(errno));
+ }
+ break;
+ }
+ break;
+ }
+
+ poplist();
+}
+
+void
xjob(void)
{
int i;
@@ -681,6 +725,37 @@ Xasync(void)
}
void
+Xsubshell(void)
+{
+ int pid;
+
+ switch(pid=fork()){
+ case -1:
+ Xerror("fork failed: try again");
+ break;
+
+ case 0: // child
+ clearwait(runner);
+ if(shell.interactive){ // NOTE: this needs to read off its caller's interactivity
+ setpid(getpid());
+ tcsetpgrp(0, runner->pgid);
+ defaultsignal();
+ }
+ run(runner->code.exe, runner->code.i+1, runner->local, 1);
+ runner->link = nil;
+ break;
+
+ default: // parent
+ setpid(pid);
+ addwait(runner, pid);
+ waitfor(runner, pid); // wait until child finishes
+ runner->code.i = runner->code.exe[runner->code.i].i; // jump to end of subshell command and continue execution
+ }
+}
+
+
+
+void
Xbasic(void)
{
Var *v;
@@ -781,6 +856,15 @@ Xflat(void)
}
void
+Xbang(void)
+{
+ if(runner->status)
+ runner->status = 0;
+ else
+ runner->status = 1;
+}
+
+void
Xexit(void)
{
exit(runner->status);
diff --git a/sys/cmd/rc/exec.h b/sys/cmd/rc/exec.h
index 0df01d0..9ad0f3d 100644
--- a/sys/cmd/rc/exec.h
+++ b/sys/cmd/rc/exec.h
@@ -15,8 +15,10 @@ void Xlocal(void);
void Xreadcmd(void);
void Xunlocal(void);
void Xassign(void);
+void Xbang(void);
void Xasync(void);
-void Xbasic(void); // Xbasic(args) run command and wait for result
+void Xbasic(void); // Xbasic(args) run command and wait for result
+void Xsubshell(void);
void Xword(void);
void Xcount(void);
void Xflat(void);
@@ -24,6 +26,7 @@ void Xflat(void);
void Xerror(char*);
/* builtin commands */
+void xcd(void);
void xfg(void);
void xdot(void);
void xjob(void);
diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c
index 06737ba..4325882 100644
--- a/sys/cmd/rc/lex.c
+++ b/sys/cmd/rc/lex.c
@@ -191,6 +191,14 @@ yylex(void)
put1('&');
return '&';
+ case '@':
+ put1('@');
+ return Tsubshell;
+
+ case '!':
+ put1('!');
+ return Tbang;
+
case '$':
if(nextis('#')){
put2('$','#');
diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c
index b88e8ab..c53f514 100644
--- a/sys/cmd/rc/parse.c
+++ b/sys/cmd/rc/parse.c
@@ -110,43 +110,44 @@ enum yysymbol_kind_t
YYSYMBOL_Tif = 5, /* Tif */
YYSYMBOL_Telse = 6, /* Telse */
YYSYMBOL_Tbang = 7, /* Tbang */
- YYSYMBOL_Targs = 8, /* Targs */
- YYSYMBOL_Tindex = 9, /* Tindex */
- YYSYMBOL_Tbasic = 10, /* Tbasic */
- YYSYMBOL_Tparen = 11, /* Tparen */
- YYSYMBOL_Tblock = 12, /* Tblock */
- YYSYMBOL_Twhile = 13, /* Twhile */
- YYSYMBOL_14_n_ = 14, /* '\n' */
- YYSYMBOL_15_ = 15, /* '$' */
- YYSYMBOL_Tcount = 16, /* Tcount */
- YYSYMBOL_Tflat = 17, /* Tflat */
- YYSYMBOL_18_ = 18, /* '(' */
- YYSYMBOL_19_ = 19, /* ')' */
- YYSYMBOL_20_ = 20, /* '{' */
- YYSYMBOL_21_ = 21, /* '}' */
- YYSYMBOL_22_ = 22, /* ';' */
- YYSYMBOL_23_ = 23, /* '&' */
- YYSYMBOL_24_ = 24, /* '=' */
- YYSYMBOL_25_ = 25, /* '^' */
- YYSYMBOL_YYACCEPT = 26, /* $accept */
- YYSYMBOL_rc = 27, /* rc */
- YYSYMBOL_line = 28, /* line */
- YYSYMBOL_body = 29, /* body */
- YYSYMBOL_paren = 30, /* paren */
- YYSYMBOL_block = 31, /* block */
- YYSYMBOL_cmds = 32, /* cmds */
- YYSYMBOL_cmdsln = 33, /* cmdsln */
- YYSYMBOL_ifbody = 34, /* ifbody */
- YYSYMBOL_assign = 35, /* assign */
- YYSYMBOL_cmd = 36, /* cmd */
- YYSYMBOL_basic = 37, /* basic */
- YYSYMBOL_atom = 38, /* atom */
- YYSYMBOL_word = 39, /* word */
- YYSYMBOL_executable = 40, /* executable */
- YYSYMBOL_nonkeyword = 41, /* nonkeyword */
- YYSYMBOL_keyword = 42, /* keyword */
- YYSYMBOL_wordsnl = 43, /* wordsnl */
- YYSYMBOL_nl = 44 /* nl */
+ YYSYMBOL_Tsubshell = 8, /* Tsubshell */
+ YYSYMBOL_Targs = 9, /* Targs */
+ YYSYMBOL_Tindex = 10, /* Tindex */
+ YYSYMBOL_Tbasic = 11, /* Tbasic */
+ YYSYMBOL_Tparen = 12, /* Tparen */
+ YYSYMBOL_Tblock = 13, /* Tblock */
+ YYSYMBOL_Twhile = 14, /* Twhile */
+ YYSYMBOL_15_n_ = 15, /* '\n' */
+ YYSYMBOL_16_ = 16, /* '$' */
+ YYSYMBOL_Tcount = 17, /* Tcount */
+ YYSYMBOL_Tflat = 18, /* Tflat */
+ YYSYMBOL_19_ = 19, /* '(' */
+ YYSYMBOL_20_ = 20, /* ')' */
+ YYSYMBOL_21_ = 21, /* '{' */
+ YYSYMBOL_22_ = 22, /* '}' */
+ YYSYMBOL_23_ = 23, /* ';' */
+ YYSYMBOL_24_ = 24, /* '&' */
+ YYSYMBOL_25_ = 25, /* '=' */
+ YYSYMBOL_26_ = 26, /* '^' */
+ YYSYMBOL_YYACCEPT = 27, /* $accept */
+ YYSYMBOL_rc = 28, /* rc */
+ YYSYMBOL_line = 29, /* line */
+ YYSYMBOL_body = 30, /* body */
+ YYSYMBOL_paren = 31, /* paren */
+ YYSYMBOL_block = 32, /* block */
+ YYSYMBOL_cmds = 33, /* cmds */
+ YYSYMBOL_cmdsln = 34, /* cmdsln */
+ YYSYMBOL_ifbody = 35, /* ifbody */
+ YYSYMBOL_assign = 36, /* assign */
+ YYSYMBOL_cmd = 37, /* cmd */
+ YYSYMBOL_basic = 38, /* basic */
+ YYSYMBOL_atom = 39, /* atom */
+ YYSYMBOL_word = 40, /* word */
+ YYSYMBOL_executable = 41, /* executable */
+ YYSYMBOL_nonkeyword = 42, /* nonkeyword */
+ YYSYMBOL_keyword = 43, /* keyword */
+ YYSYMBOL_wordsnl = 44, /* wordsnl */
+ YYSYMBOL_nl = 45 /* nl */
};
typedef enum yysymbol_kind_t yysymbol_kind_t;
@@ -472,21 +473,21 @@ union yyalloc
#endif /* !YYCOPY_NEEDED */
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 31
+#define YYFINAL 37
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 91
+#define YYLAST 97
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 26
+#define YYNTOKENS 27
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 19
/* YYNRULES -- Number of rules. */
-#define YYNRULES 41
+#define YYNRULES 45
/* YYNSTATES -- Number of states. */
-#define YYNSTATES 61
+#define YYNSTATES 67
/* YYMAXUTOK -- Last valid token kind. */
-#define YYMAXUTOK 270
+#define YYMAXUTOK 271
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
@@ -501,18 +502,18 @@ union yyalloc
static const yytype_int8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 14, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 15, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 15, 2, 23, 2,
- 18, 19, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 22,
- 2, 24, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 16, 2, 24, 2,
+ 19, 20, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 23,
+ 2, 25, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 25, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 26, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 20, 2, 21, 2, 2, 2, 2,
+ 2, 2, 2, 21, 2, 22, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -526,8 +527,8 @@ static const yytype_int8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
- 17
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 17, 18
};
#if YYDEBUG
@@ -536,9 +537,9 @@ static const yytype_int8 yyrline[] =
{
0, 36, 36, 37, 40, 41, 44, 45, 48, 51,
54, 55, 58, 59, 62, 63, 66, 69, 70, 71,
- 72, 73, 76, 77, 86, 87, 90, 91, 94, 95,
- 98, 99, 100, 101, 102, 106, 106, 113, 114, 115,
- 117, 119
+ 72, 73, 74, 75, 78, 79, 88, 89, 92, 93,
+ 96, 97, 100, 101, 102, 103, 104, 108, 108, 108,
+ 108, 115, 116, 117, 119, 121
};
#endif
@@ -555,11 +556,12 @@ static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;
static const char *const yytname[] =
{
"\"end of file\"", "error", "\"invalid token\"", "Tword", "Twords",
- "Tif", "Telse", "Tbang", "Targs", "Tindex", "Tbasic", "Tparen", "Tblock",
- "Twhile", "'\\n'", "'$'", "Tcount", "Tflat", "'('", "')'", "'{'", "'}'",
- "';'", "'&'", "'='", "'^'", "$accept", "rc", "line", "body", "paren",
- "block", "cmds", "cmdsln", "ifbody", "assign", "cmd", "basic", "atom",
- "word", "executable", "nonkeyword", "keyword", "wordsnl", "nl", YY_NULLPTR
+ "Tif", "Telse", "Tbang", "Tsubshell", "Targs", "Tindex", "Tbasic",
+ "Tparen", "Tblock", "Twhile", "'\\n'", "'$'", "Tcount", "Tflat", "'('",
+ "')'", "'{'", "'}'", "';'", "'&'", "'='", "'^'", "$accept", "rc", "line",
+ "body", "paren", "block", "cmds", "cmdsln", "ifbody", "assign", "cmd",
+ "basic", "atom", "word", "executable", "nonkeyword", "keyword",
+ "wordsnl", "nl", YY_NULLPTR
};
static const char *
@@ -569,7 +571,7 @@ yysymbol_name (yysymbol_kind_t yysymbol)
}
#endif
-#define YYPACT_NINF (-22)
+#define YYPACT_NINF (-19)
#define yypact_value_is_default(Yyn) \
((Yyn) == YYPACT_NINF)
@@ -583,13 +585,13 @@ yysymbol_name (yysymbol_kind_t yysymbol)
STATE-NUM. */
static const yytype_int8 yypact[] =
{
- 14, -22, -17, 73, 73, 73, -22, 52, 10, 2,
- -22, 52, 52, 1, 73, 16, -22, 52, -22, -22,
- -22, -22, -22, -22, -22, -22, 68, 7, -22, 52,
- 13, -22, -22, -22, -22, -22, -22, -22, -5, 73,
- 73, 18, 46, -22, -22, -5, -22, -22, -22, 73,
- -5, -22, -22, -22, 27, -22, -22, -22, -22, 46,
- -22
+ 18, -19, -18, 24, 24, 78, 78, 78, -19, 24,
+ 5, 7, -19, 24, 24, -4, 78, 41, -19, 24,
+ -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
+ -19, -19, 72, -6, -19, 24, 29, -19, -19, -19,
+ -19, -19, -19, -19, -2, 78, 78, 10, 55, -19,
+ -19, -2, -19, -19, -19, 78, -2, -19, -19, -19,
+ 43, -19, -19, -19, -19, 55, -19
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -597,27 +599,27 @@ static const yytype_int8 yypact[] =
means the default is an error. */
static const yytype_int8 yydefact[] =
{
- 17, 30, 0, 0, 0, 0, 37, 17, 0, 0,
- 19, 17, 17, 4, 18, 22, 28, 17, 40, 35,
- 36, 31, 24, 25, 33, 34, 0, 0, 12, 17,
- 6, 1, 3, 5, 20, 10, 11, 26, 23, 0,
- 0, 0, 17, 38, 32, 39, 9, 7, 13, 0,
- 16, 29, 8, 41, 19, 21, 14, 27, 40, 17,
- 15
+ 17, 32, 0, 17, 17, 0, 0, 0, 41, 17,
+ 0, 0, 19, 17, 17, 4, 18, 24, 30, 17,
+ 44, 22, 23, 37, 38, 39, 40, 33, 26, 27,
+ 35, 36, 0, 0, 12, 17, 6, 1, 3, 5,
+ 20, 10, 11, 28, 25, 0, 0, 0, 17, 42,
+ 34, 43, 9, 7, 13, 0, 16, 31, 8, 45,
+ 19, 21, 14, 29, 44, 17, 15
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -22, -22, 11, -8, -22, 4, 15, -22, -22, -22,
- 0, -22, 3, -21, -22, -1, -22, -22, -14
+ -19, -19, 42, -7, -19, 9, 2, -19, -19, -19,
+ 0, -19, 4, 6, -19, 1, -19, -19, -10
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- 0, 8, 9, 27, 18, 10, 28, 29, 55, 12,
- 30, 14, 37, 38, 15, 16, 23, 26, 42
+ 0, 10, 11, 33, 20, 12, 34, 35, 61, 14,
+ 36, 16, 43, 44, 17, 18, 29, 32, 48
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
@@ -625,53 +627,53 @@ static const yytype_int8 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_int8 yytable[] =
{
- 13, 17, 22, 22, 22, 45, 21, 24, 25, 41,
- 31, 13, 34, 22, -2, 11, 32, 1, 50, 2,
- 49, 47, 33, 35, 36, 22, 11, 48, 46, 3,
- 4, 5, 6, 58, 7, 35, 36, 52, 22, 22,
- 39, 40, 56, 51, 59, 0, 54, 0, 22, 1,
- 0, 2, 57, 0, 0, 1, 0, 2, 0, 60,
- 53, 3, 4, 5, 6, 0, 7, 3, 4, 5,
- 6, 1, 7, 19, 20, 0, 1, 0, 19, 20,
- 0, 0, 43, 3, 4, 5, 6, 44, 3, 4,
- 5, 6
+ 15, 19, 13, 21, 22, 37, 28, 28, 28, 27,
+ 30, 31, 47, 15, 40, 13, 52, 28, -2, 41,
+ 42, 1, 38, 2, 55, 3, 4, 1, 53, 2,
+ 58, 3, 4, 28, 5, 6, 7, 8, 51, 9,
+ 5, 6, 7, 8, 54, 9, 28, 28, 62, 64,
+ 57, 56, 41, 42, 65, 39, 28, 60, 1, 63,
+ 2, 0, 3, 4, 0, 66, 45, 46, 0, 0,
+ 59, 5, 6, 7, 8, 1, 9, 23, 24, 25,
+ 26, 1, 0, 23, 24, 25, 26, 49, 5, 6,
+ 7, 8, 50, 0, 5, 6, 7, 8
};
static const yytype_int8 yycheck[] =
{
- 0, 18, 3, 4, 5, 26, 3, 4, 5, 17,
- 0, 11, 12, 14, 0, 0, 14, 3, 39, 5,
- 25, 29, 11, 22, 23, 26, 11, 14, 21, 15,
- 16, 17, 18, 6, 20, 22, 23, 19, 39, 40,
- 24, 25, 42, 40, 58, -1, 42, -1, 49, 3,
- -1, 5, 49, -1, -1, 3, -1, 5, -1, 59,
- 14, 15, 16, 17, 18, -1, 20, 15, 16, 17,
- 18, 3, 20, 5, 6, -1, 3, -1, 5, 6,
- -1, -1, 14, 15, 16, 17, 18, 19, 15, 16,
- 17, 18
+ 0, 19, 0, 3, 4, 0, 5, 6, 7, 5,
+ 6, 7, 19, 13, 14, 13, 22, 16, 0, 23,
+ 24, 3, 15, 5, 26, 7, 8, 3, 35, 5,
+ 20, 7, 8, 32, 16, 17, 18, 19, 32, 21,
+ 16, 17, 18, 19, 15, 21, 45, 46, 48, 6,
+ 46, 45, 23, 24, 64, 13, 55, 48, 3, 55,
+ 5, -1, 7, 8, -1, 65, 25, 26, -1, -1,
+ 15, 16, 17, 18, 19, 3, 21, 5, 6, 7,
+ 8, 3, -1, 5, 6, 7, 8, 15, 16, 17,
+ 18, 19, 20, -1, 16, 17, 18, 19
};
/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
state STATE-NUM. */
static const yytype_int8 yystos[] =
{
- 0, 3, 5, 15, 16, 17, 18, 20, 27, 28,
- 31, 32, 35, 36, 37, 40, 41, 18, 30, 5,
- 6, 38, 41, 42, 38, 38, 43, 29, 32, 33,
- 36, 0, 14, 28, 36, 22, 23, 38, 39, 24,
- 25, 29, 44, 14, 19, 39, 21, 29, 14, 25,
- 39, 38, 19, 14, 31, 34, 36, 38, 6, 44,
- 36
+ 0, 3, 5, 7, 8, 16, 17, 18, 19, 21,
+ 28, 29, 32, 33, 36, 37, 38, 41, 42, 19,
+ 31, 37, 37, 5, 6, 7, 8, 39, 42, 43,
+ 39, 39, 44, 30, 33, 34, 37, 0, 15, 29,
+ 37, 23, 24, 39, 40, 25, 26, 30, 45, 15,
+ 20, 40, 22, 30, 15, 26, 40, 39, 20, 15,
+ 32, 35, 37, 39, 6, 45, 37
};
/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
static const yytype_int8 yyr1[] =
{
- 0, 26, 27, 27, 28, 28, 29, 29, 30, 31,
- 32, 32, 33, 33, 34, 34, 35, 36, 36, 36,
- 36, 36, 37, 37, 38, 38, 39, 39, 40, 40,
- 41, 41, 41, 41, 41, 42, 42, 43, 43, 43,
- 44, 44
+ 0, 27, 28, 28, 29, 29, 30, 30, 31, 32,
+ 33, 33, 34, 34, 35, 35, 36, 37, 37, 37,
+ 37, 37, 37, 37, 38, 38, 39, 39, 40, 40,
+ 41, 41, 42, 42, 42, 42, 42, 43, 43, 43,
+ 43, 44, 44, 44, 45, 45
};
/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
@@ -679,9 +681,9 @@ static const yytype_int8 yyr2[] =
{
0, 2, 0, 2, 1, 2, 1, 2, 3, 3,
2, 2, 1, 2, 1, 4, 3, 0, 1, 1,
- 2, 4, 1, 2, 1, 1, 1, 3, 1, 3,
- 1, 2, 3, 2, 2, 1, 1, 0, 2, 2,
- 0, 2
+ 2, 4, 2, 2, 1, 2, 1, 1, 1, 3,
+ 1, 3, 1, 2, 3, 2, 2, 1, 1, 1,
+ 1, 0, 2, 2, 0, 2
};
@@ -1417,149 +1419,161 @@ yyreduce:
case 2: /* rc: %empty */
#line 36 "sys/cmd/rc/syntax.y"
{ return 0; }
-#line 1421 "sys/cmd/rc/parse.c"
+#line 1423 "sys/cmd/rc/parse.c"
break;
case 3: /* rc: line '\n' */
#line 37 "sys/cmd/rc/syntax.y"
{ return compile((yyvsp[-1].tree)); }
-#line 1427 "sys/cmd/rc/parse.c"
+#line 1429 "sys/cmd/rc/parse.c"
break;
case 5: /* line: cmds line */
#line 41 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1433 "sys/cmd/rc/parse.c"
+#line 1435 "sys/cmd/rc/parse.c"
break;
case 7: /* body: cmdsln body */
#line 45 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1439 "sys/cmd/rc/parse.c"
+#line 1441 "sys/cmd/rc/parse.c"
break;
case 8: /* paren: '(' body ')' */
#line 48 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tparen, (yyvsp[-1].tree)); }
-#line 1445 "sys/cmd/rc/parse.c"
+#line 1447 "sys/cmd/rc/parse.c"
break;
case 9: /* block: '{' body '}' */
#line 51 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tblock, (yyvsp[-1].tree)); }
-#line 1451 "sys/cmd/rc/parse.c"
+#line 1453 "sys/cmd/rc/parse.c"
break;
case 11: /* cmds: cmd '&' */
#line 55 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1('&', (yyvsp[-1].tree)); }
-#line 1457 "sys/cmd/rc/parse.c"
+#line 1459 "sys/cmd/rc/parse.c"
break;
case 14: /* ifbody: cmd */
#line 62 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(Tif, nil, (yyvsp[0].tree)); }
-#line 1463 "sys/cmd/rc/parse.c"
+#line 1465 "sys/cmd/rc/parse.c"
break;
case 15: /* ifbody: block Telse nl cmd */
#line 63 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree3(Tif, nil, (yyvsp[-3].tree), (yyvsp[-2].tree)); }
-#line 1469 "sys/cmd/rc/parse.c"
+#line 1471 "sys/cmd/rc/parse.c"
break;
case 16: /* assign: executable '=' word */
#line 66 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2('=', (yyvsp[-2].tree), (yyvsp[0].tree)); }
-#line 1475 "sys/cmd/rc/parse.c"
+#line 1477 "sys/cmd/rc/parse.c"
break;
case 17: /* cmd: %empty */
#line 69 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = nil; }
-#line 1481 "sys/cmd/rc/parse.c"
+#line 1483 "sys/cmd/rc/parse.c"
break;
case 18: /* cmd: basic */
#line 70 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tbasic, (yyvsp[0].tree)); }
-#line 1487 "sys/cmd/rc/parse.c"
+#line 1489 "sys/cmd/rc/parse.c"
break;
case 20: /* cmd: assign cmd */
#line 72 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 2); }
-#line 1493 "sys/cmd/rc/parse.c"
+#line 1495 "sys/cmd/rc/parse.c"
break;
case 21: /* cmd: Tif paren nl ifbody */
#line 73 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = hangchild1((yyvsp[-2].tree), (yyvsp[-3].tree), 0); }
-#line 1499 "sys/cmd/rc/parse.c"
+#line 1501 "sys/cmd/rc/parse.c"
+ break;
+
+ case 22: /* cmd: Tbang cmd */
+#line 74 "sys/cmd/rc/syntax.y"
+ { (yyval.tree) = maketree1(Tbang, (yyvsp[0].tree)); }
+#line 1507 "sys/cmd/rc/parse.c"
+ break;
+
+ case 23: /* cmd: Tsubshell cmd */
+#line 75 "sys/cmd/rc/syntax.y"
+ { (yyval.tree) = maketree1(Tsubshell, (yyvsp[0].tree)); }
+#line 1513 "sys/cmd/rc/parse.c"
break;
- case 23: /* basic: basic word */
-#line 77 "sys/cmd/rc/syntax.y"
+ case 25: /* basic: basic word */
+#line 79 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2(Targs, (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1505 "sys/cmd/rc/parse.c"
+#line 1519 "sys/cmd/rc/parse.c"
break;
- case 25: /* atom: keyword */
-#line 87 "sys/cmd/rc/syntax.y"
+ case 27: /* atom: keyword */
+#line 89 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tword, (yyvsp[0].tree)); }
-#line 1511 "sys/cmd/rc/parse.c"
+#line 1525 "sys/cmd/rc/parse.c"
break;
- case 27: /* word: word '^' atom */
-#line 91 "sys/cmd/rc/syntax.y"
+ case 29: /* word: word '^' atom */
+#line 93 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); }
-#line 1517 "sys/cmd/rc/parse.c"
+#line 1531 "sys/cmd/rc/parse.c"
break;
- case 29: /* executable: executable '^' atom */
-#line 95 "sys/cmd/rc/syntax.y"
+ case 31: /* executable: executable '^' atom */
+#line 97 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); }
-#line 1523 "sys/cmd/rc/parse.c"
+#line 1537 "sys/cmd/rc/parse.c"
break;
- case 31: /* nonkeyword: '$' atom */
-#line 99 "sys/cmd/rc/syntax.y"
+ case 33: /* nonkeyword: '$' atom */
+#line 101 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1('$', (yyvsp[0].tree)); }
-#line 1529 "sys/cmd/rc/parse.c"
+#line 1543 "sys/cmd/rc/parse.c"
break;
- case 32: /* nonkeyword: '(' wordsnl ')' */
-#line 100 "sys/cmd/rc/syntax.y"
+ case 34: /* nonkeyword: '(' wordsnl ')' */
+#line 102 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = (yyvsp[-1].tree); }
-#line 1535 "sys/cmd/rc/parse.c"
+#line 1549 "sys/cmd/rc/parse.c"
break;
- case 33: /* nonkeyword: Tcount atom */
-#line 101 "sys/cmd/rc/syntax.y"
+ case 35: /* nonkeyword: Tcount atom */
+#line 103 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tcount, (yyvsp[0].tree)); }
-#line 1541 "sys/cmd/rc/parse.c"
+#line 1555 "sys/cmd/rc/parse.c"
break;
- case 34: /* nonkeyword: Tflat atom */
-#line 102 "sys/cmd/rc/syntax.y"
+ case 36: /* nonkeyword: Tflat atom */
+#line 104 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = maketree1(Tflat, (yyvsp[0].tree)); }
-#line 1547 "sys/cmd/rc/parse.c"
+#line 1561 "sys/cmd/rc/parse.c"
break;
- case 37: /* wordsnl: %empty */
-#line 113 "sys/cmd/rc/syntax.y"
+ case 41: /* wordsnl: %empty */
+#line 115 "sys/cmd/rc/syntax.y"
{ (yyval.tree) = nil; }
-#line 1553 "sys/cmd/rc/parse.c"
+#line 1567 "sys/cmd/rc/parse.c"
break;
- case 39: /* wordsnl: wordsnl word */
-#line 115 "sys/cmd/rc/syntax.y"
+ case 43: /* wordsnl: wordsnl word */
+#line 117 "sys/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 1559 "sys/cmd/rc/parse.c"
+#line 1573 "sys/cmd/rc/parse.c"
break;
-#line 1563 "sys/cmd/rc/parse.c"
+#line 1577 "sys/cmd/rc/parse.c"
default: break;
}
@@ -1783,5 +1797,5 @@ yyreturnlab:
return yyresult;
}
-#line 120 "sys/cmd/rc/syntax.y"
+#line 122 "sys/cmd/rc/syntax.y"
diff --git a/sys/cmd/rc/parse.h b/sys/cmd/rc/parse.h
index 85be043..b42cc2b 100644
--- a/sys/cmd/rc/parse.h
+++ b/sys/cmd/rc/parse.h
@@ -59,14 +59,15 @@ extern int yydebug;
Tif = 260, /* Tif */
Telse = 261, /* Telse */
Tbang = 262, /* Tbang */
- Targs = 263, /* Targs */
- Tindex = 264, /* Tindex */
- Tbasic = 265, /* Tbasic */
- Tparen = 266, /* Tparen */
- Tblock = 267, /* Tblock */
- Twhile = 268, /* Twhile */
- Tcount = 269, /* Tcount */
- Tflat = 270 /* Tflat */
+ Tsubshell = 263, /* Tsubshell */
+ Targs = 264, /* Targs */
+ Tindex = 265, /* Tindex */
+ Tbasic = 266, /* Tbasic */
+ Tparen = 267, /* Tparen */
+ Tblock = 268, /* Tblock */
+ Twhile = 269, /* Twhile */
+ Tcount = 270, /* Tcount */
+ Tflat = 271 /* Tflat */
};
typedef enum yytokentype yytoken_kind_t;
#endif
@@ -80,14 +81,15 @@ extern int yydebug;
#define Tif 260
#define Telse 261
#define Tbang 262
-#define Targs 263
-#define Tindex 264
-#define Tbasic 265
-#define Tparen 266
-#define Tblock 267
-#define Twhile 268
-#define Tcount 269
-#define Tflat 270
+#define Tsubshell 263
+#define Targs 264
+#define Tindex 265
+#define Tbasic 266
+#define Tparen 267
+#define Tblock 268
+#define Twhile 269
+#define Tcount 270
+#define Tflat 271
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@@ -97,7 +99,7 @@ union YYSTYPE
struct Tree *tree;
-#line 101 "sys/cmd/rc/parse.h"
+#line 103 "sys/cmd/rc/parse.h"
};
typedef union YYSTYPE YYSTYPE;
diff --git a/sys/cmd/rc/rc.h b/sys/cmd/rc/rc.h
index 55a4eb2..606ca7b 100644
--- a/sys/cmd/rc/rc.h
+++ b/sys/cmd/rc/rc.h
@@ -207,8 +207,11 @@ void execute(Word *, Word*);
/* wait.c */
void addwait(Thread *, int);
+void delwait(Thread *, int);
void clearwait(Thread*);
+
int waitall(Thread *);
+int waitfor(Thread *, int);
void killzombies(void);
diff --git a/sys/cmd/rc/syntax.y b/sys/cmd/rc/syntax.y
index 469260f..6334819 100644
--- a/sys/cmd/rc/syntax.y
+++ b/sys/cmd/rc/syntax.y
@@ -1,4 +1,4 @@
-%token Tword Twords Tif Telse Tbang
+%token Tword Twords Tif Telse Tbang Tsubshell
%token Targs Tindex
%token Tbasic Tparen Tblock
@@ -14,7 +14,7 @@
/* operator precendence: lowest first */
%left Twhile Telse
%left '\n'
-%left Tbang
+%left Tbang Tsubshell
%right '$' Tcount Tflat
%right Tindex
@@ -24,7 +24,7 @@
}
%type<tree> line cmds cmdsln body paren block ifbody assign;
%type<tree> cmd basic executable nonkeyword keyword word words wordsnl atom arg args;
-%type<tree> Tbang;
+%type<tree> Tbang Tsubshell Tindex;
%type<tree> Tword Tif Telse;
/* grammar */
@@ -71,6 +71,8 @@ cmd:
| block
| assign cmd %prec Tbang { $$ = hangchild1($1, $2, 2); }
| Tif paren nl ifbody { $$ = hangchild1($2, $1, 0); }
+| Tbang cmd { $$ = maketree1(Tbang, $2); }
+| Tsubshell cmd { $$ = maketree1(Tsubshell, $2); }
basic:
executable
@@ -103,7 +105,7 @@ nonkeyword:
//| '`' block { $$ = maketree1('`', $2); }
keyword:
- Tif|Telse
+ Tif|Telse|Tbang|Tsubshell
words:
/* empty */ { $$ = nil; }
diff --git a/sys/cmd/rc/wait.c b/sys/cmd/rc/wait.c
index e3dcea1..6a8d859 100644
--- a/sys/cmd/rc/wait.c
+++ b/sys/cmd/rc/wait.c
@@ -84,6 +84,39 @@ shouldwait(Thread *job)
return 0;
}
+static inline
+void
+notify(Thread *job, struct WaitMsg msg)
+{
+ int i;
+ for(i=0; i < job->wait.len; i++){
+ if(job->wait.on[i].pid == msg.pid){
+ job->status = msg.status;
+ switch(msg.type){
+ case Pstop:
+ print(shell.err, "%d: suspended\n", msg.pid);
+ job->wait.status = Pstop;
+ job->wait.on[i].status = Pstop;
+ break;
+
+ case Psig:
+ print(shell.err, "%d: terminated by signal %d\n", msg.pid, msg.status);
+ /* fallthrough */
+ case Pdone:
+ job->wait.on[i].status = Pdone;
+ delwait(job, msg.pid);
+ if(!job->wait.len)
+ job->wait.status = Pdone;
+ break;
+
+ default:
+ fatal("%d: unrecognized message type %d\n", msg.pid, msg.type);
+ }
+ break;
+ }
+ }
+}
+
// -----------------------------------------------------------------------
// exported
@@ -140,34 +173,31 @@ waitall(Thread *job)
return 0;
}
- for(i=0; i < job->wait.len; i++){
- if(job->wait.on[i].pid == msg.pid){
- job->status = msg.status;
- switch(msg.type){
- case Pstop:
- print(shell.err, "%d: suspended\n", msg.pid);
- job->wait.status = Pstop;
- job->wait.on[i].status = Pstop;
- break;
-
- case Psig:
- print(shell.err, "%d: terminated by signal %d\n", msg.pid, msg.status);
- /* fallthrough */
- case Pdone:
- job->wait.on[i].status = Pdone;
- delwait(job, msg.pid);
- if(!job->wait.len)
- job->wait.status = Pdone;
- break;
-
- default:
- fatal("%d: unrecognized message type %d\n", msg.pid, msg.type);
- }
- break;
- }
+ notify(job, msg);
+ }
+ return 1;
+}
+
+int
+waitfor(Thread *job, int pid)
+{
+ int i;
+ Thread *t;
+ struct WaitMsg msg;
+
+ while(shouldwait(job) && await(-job->pgid, WUNTRACED, &msg)){
+ if(msg.pid == 0){
+ perror("wait for");
+ return 0;
}
+
+ notify(job, msg);
+ /* allow for an early exit */
+ if(msg.pid == pid)
+ return 1;
}
return 1;
+
}
void
@@ -197,30 +227,3 @@ killzombies(void)
}
}
}
-
-#if 0
-int
-waitfor(int pid)
-{
- Thread *t;
- struct WaitMsg w;
-
- if(pid >= 0 && !havewait(pid))
- return 0;
-
- while(await(-proc->pgid, WUNTRACED, &w)){
- delwait(w.pid);
- if(w.pid == pid){
- if(w.signal)
- print(errio, "pid[%d]: signal: %d\n", w.pid, w.status);
- return 1;
- }
- for(t=proc->link; t; t=t->link){
- if(t->pid == w.pid)
- t->pid = -1;
- }
- }
-
- return 0;
-}
-#endif