diff --git a/src/cmd/mk/mk.h b/src/cmd/mk/mk.h index ca14e9d67..33f4d3266 100644 --- a/src/cmd/mk/mk.h +++ b/src/cmd/mk/mk.h @@ -164,7 +164,7 @@ extern char *explain; extern Shell *shellt; extern Word *shellcmd; -extern Shell shshell, rcshell; +extern Shell shshell, rcshell, nashshell; #define SYNERR(l) (fprint(2, "mk: %s:%d: syntax error; ", infile, ((l)>=0)?(l):mkinline)) #define RERR(r) (fprint(2, "mk: %s:%d: rule error; ", (r)->file, (r)->line)) diff --git a/src/cmd/mk/mkfile b/src/cmd/mk/mkfile index ec891afc7..b6deb7d81 100644 --- a/src/cmd/mk/mkfile +++ b/src/cmd/mk/mkfile @@ -17,6 +17,7 @@ OFILES=\ parse.$O\ recipe.$O\ rc.$O\ + nash.$O\ rule.$O\ run.$O\ sh.$O\ diff --git a/src/cmd/mk/mkfile.test b/src/cmd/mk/mkfile.test index 8a4e4b964..f9692f601 100644 --- a/src/cmd/mk/mkfile.test +++ b/src/cmd/mk/mkfile.test @@ -10,3 +10,22 @@ use-sh:V: echo $i done +MKSHELL=$HOME/nashroot/bin/nash +use-nash:V: + for i in ("a" "b" "c") { + echo $i + } + +# complex nash syntax +use-nash2:V: + var stdout, stderr, status <= ls / + if $status != "0" { + echo "error: " $stderr + exit(1) + } + var paths <= split($stdout, "\n") + for p in $paths { + echo $p + } + + diff --git a/src/cmd/mk/nash.c b/src/cmd/mk/nash.c new file mode 100644 index 000000000..79ec4dd72 --- /dev/null +++ b/src/cmd/mk/nash.c @@ -0,0 +1,161 @@ +#include "mk.h" + +/* + * This file contains functions that depend on nash's syntax. + */ + +/* + * skip a token in quotes. + */ +static char * +nashsquote(char *cp, int c) +{ + Rune r; + int n; + + while(*cp){ + n = chartorune(&r, cp); + if(r == c) + return cp; + if(r == '\\') + n += chartorune(&r, cp+n); + cp += n; + } + SYNERR(-1); /* should never occur */ + fprint(2, "missing closing '\n"); + return 0; +} +/* + * search a string for unescaped characters in a pattern set + */ +static char * +nashcharin(char *cp, char *pat) +{ + Rune r; + int n, vargen; + + vargen = 0; + while(*cp){ + n = chartorune(&r, cp); + switch(r){ + case '\\': /* skip escaped char */ + cp += n; + n = chartorune(&r, cp); + break; + case '"': + cp = nashsquote(cp+1, r); /* n must = 1 */ + if(!cp) + return 0; + break; + case '$': + if(*(cp+1) == '{') + vargen = 1; + break; + case '}': + if(vargen) + vargen = 0; + else if(utfrune(pat, r)) + return cp; + break; + default: + if(vargen == 0 && utfrune(pat, r)) + return cp; + break; + } + cp += n; + } + if(vargen){ + SYNERR(-1); + fprint(2, "missing closing } in pattern generator\n"); + } + return 0; +} + +/* + * extract an escaped token. Possible escape chars are single-quote, + * double-quote,and backslash. Nash only has double-quotes and + * backslack have to be inserted again into buffer. + */ +char* +nashexpandquote(char *s, Rune r, Bufblock *b) +{ + if(r != '"') { + rinsert(b, r); + return s; + } + + /* inside double-quote */ + while(*s){ + s += chartorune(&r, s); + if(r == '"') { + if(*s == '"') + s++; + else + return s; + } + rinsert(b, r); /* consumes the string */ + } + + return 0; +} + +/* + * Input an escaped token. Possible escape chars are single-quote, + * double-quote and backslash. Only the first is a valid escape for + * rc; the others are just inserted into the receiving buffer. + */ +int +nashescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc) +{ + SYNERR(-1); + return 0; +} + +/* + * check for quoted strings. + * s points to char after opening quote, q. + */ +char * +nashcopyq(char *s, Rune q, Bufblock *buf) +{ + Rune r; + if(q == '"') { + while(*s){ + s += chartorune(&r, s); + rinsert(buf, r); + if(r == '"') + break; + } + } + + return s; +} + +static int +nashmatchname(char *name) +{ + char *p; + + if((p = strrchr(name, '/')) != nil) + name = p+1; + if(strlen(name)!=4) + return 0; + + if(strcmp(name, "nash") == 0) + return 1; + return 0; +} + +Shell nashshell = { + "nash", + "\"= \t", + + /* nash doesn't have IFS but otherwise we + cannot access lists from mk */ + ' ', + nashcharin, + nashexpandquote, + nashescapetoken, + nashcopyq, + nashmatchname +}; diff --git a/src/cmd/mk/run.c b/src/cmd/mk/run.c index dd225c0d0..e38853d93 100644 --- a/src/cmd/mk/run.c +++ b/src/cmd/mk/run.c @@ -78,7 +78,8 @@ sched(void) if(DEBUG(D_EXEC)) fprint(1, "recipe='%s'", j->r->recipe);/**/ Bflush(&bout); - if(j->r->attr&NOMINUSE) + if(j->r->attr&NOMINUSE || + strcmp(j->r->shellt->name, "nash")==0) flags = 0; else flags = "-e"; diff --git a/src/cmd/mk/shell.c b/src/cmd/mk/shell.c index 8c15ec218..b2afe8103 100644 --- a/src/cmd/mk/shell.c +++ b/src/cmd/mk/shell.c @@ -1,6 +1,7 @@ #include "mk.h" static Shell *shells[] = { + &nashshell, &rcshell, &shshell };