Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
9 changes: 7 additions & 2 deletions glom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand Down
7 changes: 5 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion rc.1
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
rc \- shell
.SH SYNOPSIS
.B rc
.RB [ \-deiIlnopsvx ]
.RB [ \-deiIlnopsuvx ]
.RB [ \-c
.IR command ]
.RI [ arguments ]
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion rc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 *);
Expand Down
5 changes: 3 additions & 2 deletions trip.rc
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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
Expand Down
25 changes: 21 additions & 4 deletions var.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* var.c: provide "public" functions for adding and removing variables from the symbol table */

#include <stdio.h>
Copy link
Owner

@rakitzis rakitzis Jun 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer the nalloc helper, do not include stdio or use malloc here. nalloc is scoped to command-lifetime allocations.

#include "rc.h"

#include "input.h"
Expand Down Expand Up @@ -52,14 +52,21 @@ extern bool varassign_string(char *extdef) {
return TRUE;
}

char* get_message(char *format, char *msg) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer char *-style decl syntax

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole helper function actually is unneeded -- and allocating error messages with malloc will leak memory.

Incidentally, trip.rc probably doesn't verify leak-free behavior but at one time I ran rc through valgrind to catch leaks. I wonder if the state of the art of leak detection for C has advanced to the point where we could run a tool in-line for pull requests.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a while since I ran this, but AFAICR trip.rc only succeeds with this flag OFF. Because there are undefined variables being used in there 😃 . Notwithstanding I have been using this branch as my daily drive. I will have a look at this again.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trip.rc can exercise features selectively. It's not all-or-nothing.

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).
Also check to see if $status is being dereferenced. (we lazily evaluate the List
associated with $status)
*/

extern List *varlookup(char *name) {
List *varlookupAux(char *name, bool strict) {
Variable *look;
List *ret, *l;
int sub;
Expand All @@ -79,19 +86,29 @@ extern List *varlookup(char *name) {
return ret;
}
look = lookup_var(name);
if (look == NULL)
return NULL; /* not found */
if (look == NULL) {
if (strict && dashewe)
rc_error(get_message("Undefined variable '%s'\n", name));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inconsistent capitalization

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you prefer "undefined ?

return NULL; /* not found */
}
if (look->def != NULL)
return look->def;
if (look->extdef == NULL)
return NULL; /* variable was set to null, e.g., a=() echo foo */
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;
}
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() */

Expand Down