From 6df8f3cbec8b9a81b82e15ca6d1b5d31cb305855 Mon Sep 17 00:00:00 2001 From: Bill Birch Date: Thu, 7 Jul 2022 18:18:39 +1000 Subject: [PATCH 1/2] add -u flag, print warnings if undefined --- builtins.c | 1 + input.c | 4 ++-- main.c | 7 +++++-- rc.1 | 7 ++++++- rc.h | 2 +- trip.rc | 5 +++-- var.c | 16 +++++++++++++--- 7 files changed, 31 insertions(+), 11 deletions(-) diff --git a/builtins.c b/builtins.c index 6abbff01..005fcb11 100644 --- a/builtins.c +++ b/builtins.c @@ -244,6 +244,7 @@ static void b_flag(char **av) { case 's': if (mode != 2) goto flag_immutable; flagp = &dashess; break; + case 'u': flagp = &dashewe; break; case 'v': flagp = &dashvee; break; case 'x': flagp = &dashex; break; } diff --git a/input.c b/input.c index a6a18983..267c97cd 100644 --- a/input.c +++ b/input.c @@ -68,9 +68,9 @@ static void history() { List *hist; size_t a; - if (!interactive || (hist = varlookup("history")) == NULL) + if (!interactive || lookup_var("history") == NULL) return; - + hist = varlookup("history"); for (a = 0; a < chars_in; a++) { char c = inbuf[a]; diff --git a/main.c b/main.c index 870d104d..ed9c6370 100644 --- a/main.c +++ b/main.c @@ -7,7 +7,7 @@ #include "input.h" bool dashdee, dashee, dasheye, dashell, dashen; -bool dashpee, dashoh, dashess, dashvee, dashex; +bool dashpee, dashoh, dashess, dashvee, dashewe, dashex; bool interactive; static bool dashEYE; char *dashsee[2]; @@ -25,7 +25,7 @@ extern int main(int argc, char *argv[], char *envp[]) { dollarzero = argv[0]; rc_pid = getpid(); dashell = (*argv[0] == '-'); /* Unix tradition */ - while ((c = rc_getopt(argc, argv, "c:deiIlnopsvx")) != -1) + while ((c = rc_getopt(argc, argv, "c:deiIlnopsuvx")) != -1) switch (c) { case 'c': dashsee[0] = rc_optarg; @@ -58,6 +58,9 @@ extern int main(int argc, char *argv[], char *envp[]) { case 's': dashess = TRUE; break; + case 'u': + dashewe = TRUE; + break; case 'v': dashvee = TRUE; break; diff --git a/rc.1 b/rc.1 index 4da360f1..a635439a 100644 --- a/rc.1 +++ b/rc.1 @@ -166,7 +166,7 @@ rc \- shell .SH SYNOPSIS .B rc -.RB [ \-deiIlnopsvx ] +.RB [ \-deiIlnopsuvx ] .RB [ \-c .IR command ] .RI [ arguments ] @@ -323,6 +323,11 @@ to read from standard input. Any arguments are placed in .Cr $* . .TP +.Cr \-u +This flag causes +.I rc +to raise an error if a an undefined variable is used, rather than evaluating it to (). +.TP .Cr \-v This flag causes .I rc diff --git a/rc.h b/rc.h index c3b22431..5c72bf6b 100644 --- a/rc.h +++ b/rc.h @@ -174,7 +174,7 @@ enum { /* main.c */ extern Rq *redirq; extern bool dashdee, dashee, dasheye, dashell, dashen; -extern bool dashpee, dashoh, dashess, dashvee, dashex; +extern bool dashpee, dashoh, dashess, dashvee, dashewe, dashex; extern bool interactive; extern char *dashsee[]; extern pid_t rc_pid; diff --git a/trip.rc b/trip.rc index 43af11b6..0e3cc6a4 100644 --- a/trip.rc +++ b/trip.rc @@ -1,6 +1,8 @@ # trip.rc -- take a tour of rc +# -*-rc-*- # Invoke as "path-to-new-rc < trip.rc" + rc=$0 echo tripping $rc $version @@ -411,8 +413,7 @@ if (!~ `{echo '#echo' | $rc -v |[2] sed 's/#//'} echo) if (~ `` '' . ?*) fail null dot if (~ `` '' {. -i} ?*) - fail null dot -i - + fail null dot -i cat > $tmpdir/dot.$pid << eof echo hi eof diff --git a/var.c b/var.c index 2fa7c350..5ad3853e 100644 --- a/var.c +++ b/var.c @@ -1,5 +1,5 @@ /* var.c: provide "public" functions for adding and removing variables from the symbol table */ - +#include #include "rc.h" #include "input.h" @@ -52,6 +52,13 @@ extern bool varassign_string(char *extdef) { return TRUE; } +char* get_message(char *format, char *msg) { + size_t needed = snprintf(NULL, 0, format, msg); + char *buffer = malloc(needed+1); + sprintf(buffer, format, msg); + return buffer; +} + /* Return a List based on a name lookup. If the list is in external (string) form, convert it to internal (List) form. Treat $n (n is an integer) specially as $*(n). @@ -79,8 +86,10 @@ extern List *varlookup(char *name) { return ret; } look = lookup_var(name); - if (look == NULL) - return NULL; /* not found */ + if (look == NULL) { + if (dashewe) rc_error(get_message("Undefined variable '%s'\n", name)); + return NULL; /* not found */ + } if (look->def != NULL) return look->def; if (look->extdef == NULL) @@ -88,6 +97,7 @@ extern List *varlookup(char *name) { ret = parse_var(look->extdef); if (ret == NULL) { look->extdef = NULL; + if (dashewe) rc_error(get_message("undefined variable '%s'\n", name)); return NULL; } return look->def = ret; From e2c6fd224b92859a229015d873d2392bdc9aa6b4 Mon Sep 17 00:00:00 2001 From: Bill Birch Date: Fri, 2 Sep 2022 11:58:46 +1000 Subject: [PATCH 2/2] -u flag, print warnings if undefined unless getting count with $# --- glom.c | 9 +++++++-- rc.h | 1 + var.c | 11 +++++++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/glom.c b/glom.c index 7f90d9dc..98355e26 100644 --- a/glom.c +++ b/glom.c @@ -420,14 +420,19 @@ extern List *glom(Node *n) { rc_error("multi-word variable name"); if (*v->w == '\0') rc_error("zero-length variable name"); + if (n->type == nCount) { + /* + Allow programmer to get length of undefined variables for idiom: if( ~ $#variable 0) { . . . } + */ + v = (*v->w == '*' && v->w[1] == '\0') ? varlookupNonStrict(v->w)->n : varlookupNonStrict(v->w); + return count(v); + } v = (*v->w == '*' && v->w[1] == '\0') ? varlookup(v->w)->n : varlookup(v->w); switch (n->type) { default: panic("unexpected node in glom"); exit(1); /* NOTREACHED */ - case nCount: - return count(v); case nFlat: return flatten(v); case nVar: diff --git a/rc.h b/rc.h index 5c72bf6b..eb90f08e 100644 --- a/rc.h +++ b/rc.h @@ -238,6 +238,7 @@ extern Htab *fp, *vp; extern void *lookup(char *, Htab *); extern rc_Function *get_fn_place(char *); extern List *varlookup(char *); +extern List *varlookupNonStrict(char *); extern Node *fnlookup(char *); extern Variable *get_var_place(char *, bool); extern bool varassign_string(char *); diff --git a/var.c b/var.c index 5ad3853e..2a5220c2 100644 --- a/var.c +++ b/var.c @@ -66,7 +66,7 @@ char* get_message(char *format, char *msg) { associated with $status) */ -extern List *varlookup(char *name) { +List *varlookupAux(char *name, bool strict) { Variable *look; List *ret, *l; int sub; @@ -87,7 +87,8 @@ extern List *varlookup(char *name) { } look = lookup_var(name); if (look == NULL) { - if (dashewe) rc_error(get_message("Undefined variable '%s'\n", name)); + if (strict && dashewe) + rc_error(get_message("Undefined variable '%s'\n", name)); return NULL; /* not found */ } if (look->def != NULL) @@ -102,6 +103,12 @@ extern List *varlookup(char *name) { } return look->def = ret; } +extern List *varlookup(char *name) { + return varlookupAux(name, TRUE); +} +extern List *varlookupNonStrict(char *name) { + return varlookupAux(name, FALSE); +} /* lookup a variable in external (string) form, converting if necessary. Used by makeenv() */