rc

[fork] interactive rc shell
Log | Files | Refs | README | LICENSE

commit 23892fe09be24eb8e53747d4d3752eebb0dd2284
parent 643940b99070750dfd0883df080af72b8031a106
Author: tjg <tjg>
Date:   Fri, 28 Sep 2001 10:00:48 +0000

  Bug: the ^A bug is fixed.

Diffstat:
Mfootobar.c | 111++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 71 insertions(+), 40 deletions(-)

diff --git a/footobar.c b/footobar.c @@ -212,45 +212,51 @@ extern char *get_name(char *s) { } } -/* - Hacky routine to split a ^A-separated environment variable. Scans - backwards. Be VERY CAREFUL with the loop boundary conditions. e.g., - notice what happens when there is no ^A in the extdef. (It does - the right thing, of course :-) -*/ - -#define skipleft(p) do --p; while (*p != '\0' && *p != '\001'); +/* interpret a variable from environment. ^A separates list elements; + ^B escapes a literal ^A or ^B. For minimal surprise, ^B followed + by anything other than ^A or ^B is preserved. */ extern List *parse_var(char *extdef) { - char *endp, *realend, *sepp; - List *tailp, *new; - - extdef = strchr(extdef, '='); - *extdef++ = '\0'; /* null "initiate" the string for rtol scanning */ - - sepp = realend = strchr(extdef, '\0'); - tailp = NULL; - - while (1) { - endp = sepp; /* set endp to end of current mebmer */ - skipleft(sepp); /* advance sepp to the previous \1, */ - *endp = '\0'; /* and null terminate the member. */ - + char *begin, *end, *from, *to; + int len; + List *first, *last, *new; + + last = NULL; + begin = strchr(extdef, '='); + while (*begin) { + ++begin; + end = begin; + len = 0; + while (*end != ENV_SEP && *end != '\0') { + if (*end == ENV_ESC) { + ++end; + if (*end != ENV_SEP && *end != ENV_ESC) --end; + } + ++end; ++len; + } new = enew(List); - new->w = ecpy(sepp+1); + if (last) + last->n = new; + else + first = new; + last = new; + new->w = ealloc(len + 1); new->m = NULL; - new->n = tailp; - tailp = new; - - if (sepp < extdef) /* break when sepp hits the null "initiator" */ - break; - if (endp != realend) /* else restore the \1 in between members */ - *endp = '\001'; + new->n = NULL; + to = new->w; + for (from = begin; from < end; ++from) { + if (*from == ENV_ESC) { + ++from; + if (*from != ENV_SEP && *from != ENV_ESC) + --from; + } + *to = *from; + ++to; + } + *to = '\0'; + begin = end; } - if (endp != realend) - *endp = '\001'; - *--extdef = '='; /* restore extdef '=' */ - return tailp; + return first; } /* get an environment entry for a function and have rc parse it. */ @@ -279,16 +285,40 @@ static bool Aconv(Format *f, int ignore) { return FALSE; } +/* %L -- print a list */ static bool Lconv(Format *f, int ignore) { - List *l = va_arg(f->args, List *); - char *sep = va_arg(f->args, char *); - char *fmt = (f->flags & FMT_leftside) ? "%s%s" : "%-S%s"; + List *l, *n; + char *sep; + + l = va_arg(f->args, List *); + sep = va_arg(f->args, char *); if (l == NULL && (f->flags & FMT_leftside) == 0) fmtprint(f, "()"); else { - List *s; - for (s = l; s != NULL; s = s->n) - fmtprint(f, fmt, s->w, s->n == NULL ? "" : sep); + for (; l != NULL; l = n) { + n = l->n; + fmtprint(f, (f->flags & FMT_leftside) ? "%s" : "%-S", l->w); + if (n != NULL) fmtputc(f, *sep); + } + } + return FALSE; +} + +/* %W -- print a list for exporting */ +static bool Wconv(Format *f, int ignore) { + List *l, *n; + + l = va_arg(f->args, List *); + for (; l != NULL; l = n) { + char c, *s; + + for (s = l->w; (c = *s) != '\0'; ++s) { + if (c == ENV_SEP || c == ENV_ESC) + fmtputc(f, ENV_ESC); + fmtputc(f, c); + } + n = l->n; + if (n != NULL) fmtputc(f, ENV_SEP); } return FALSE; } @@ -329,6 +359,7 @@ void initprint(void) { fmtinstall('S', Sconv); fmtinstall('T', Tconv); fmtinstall('D', Dconv); + fmtinstall('W', Wconv); #if PROTECT_ENV fmtinstall('F', Fconv); #else