From e9ff1c6fbbbac9ece2604876ab589ac282360446 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Mon, 15 Nov 2021 15:08:03 -0800 Subject: Feat: added if/else branching and switch statement Unsure about my modification to the language. I found the parsing of the case body within switches to be odd - specifically that it parses liberally and then checks that it has case -> cmd structuring while it walks the code. This means the language is more permissive than the semantics. I modified it to be more explicit, but at the cost of having to end each case statement with a semicolon. I wanted a colon, but this is a valid word character and thus will be lexed as part of the word. --- src/cmd/rc/exec.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 4 deletions(-) (limited to 'src/cmd/rc/exec.c') diff --git a/src/cmd/rc/exec.c b/src/cmd/rc/exec.c index 5baaf1a..a551d52 100644 --- a/src/cmd/rc/exec.c +++ b/src/cmd/rc/exec.c @@ -360,6 +360,18 @@ count(Word *w) // ----------------------------------------------------------------------- // builtins +static void +setstatus(char *msg) +{ + if(!msg || msg[0] == 0) + runner->status = 0; + else + runner->status = 1; +} + +// ----------------------------------------------------------------------- +// builtins + void xecho(void) { @@ -402,10 +414,13 @@ xexit(void) Word *arg; popword(); // exit + arg = runner->args->word; switch(count(arg)){ default: print(shell.err, "invalid number of arguments to exit, exiting anyways\n"); + case 1: + setstatus(runner->args->word->str); case 0: Xexit(); } @@ -420,19 +435,24 @@ xcd(void) char dir[512]; popword(); // cd + setstatus(nil); arg = runner->args->word; switch(count(arg)){ default: print(shell.err, "usage: cd [directory]\n"); + setstatus("failed cd"); break; case 0: arg = var("home")->val; if(count(arg) >= 1){ - if(chdir(arg->str) < 0) + if(chdir(arg->str) < 0){ print(shell.err, "failed cd: %s\n", strerror(errno)); + setstatus("failed cd"); + } }else{ print(shell.err, "ambiguous cd: $home empty\n"); + setstatus("failed cd"); } break; @@ -443,9 +463,12 @@ xcd(void) 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)); + setstatus("failed cd"); } break; } @@ -510,6 +533,8 @@ xdot(void) if(fd<0){ print(shell.err, "failed open: %s: ", base); + setstatus("failed open"); + Xerror(".: failed open"); return; } /* set up for a new command loop */ @@ -632,13 +657,21 @@ Xword(void) pushword(runner->code.exe[runner->code.i++].s); } +void +Xsettrue(void) +{ + setstatus(nil); +} + void Xtrue(void) { if(!runner->status){ - assert(runner->wait.status == Pdone); runner->code.i++; - deljob(runner); + if(runner->wait.status){ + assert(runner->wait.status == Pdone); + deljob(runner); + } runner->pgid = -1; }else runner->code.i = runner->code.exe[runner->code.i].i; @@ -662,6 +695,27 @@ Xgoto(void) runner->code.i = runner->code.exe[runner->code.i].i; } +void +Xcase(void) +{ + Word *p; // pattern + Word *c; // case value + + for(p=runner->args->word; p; p=p->link){ + for(c=runner->args->link->word; c; c=c->link){ + if(match(c->str, p->str, 0)) + goto hit; + } + } +nohit: + runner->code.i = runner->code.exe[runner->code.i].i; + goto clean; +hit: + runner->code.i++; +clean: + poplist(); // pop case words +} + void Xfor(void) { @@ -678,7 +732,6 @@ Xfor(void) runner->local->val->link = nil; runner->code.i++; } - } static @@ -1261,6 +1314,8 @@ Xerror(char *msg) { print(shell.err, "rc: %s", msg); flush(shell.err); + + setstatus("error"); while(!runner->flag.user) Xreturn(); } -- cgit v1.2.1