commit 23892fe09be24eb8e53747d4d3752eebb0dd2284
parent 643940b99070750dfd0883df080af72b8031a106
Author: tjg <tjg>
Date: Fri, 28 Sep 2001 10:00:48 +0000
Bug: the ^A bug is fixed.
Diffstat:
M | footobar.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