X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/runlisp/blobdiff_plain/f50ecbe185f8866970ab62157b2e45bf613907d2..refs/heads/master:/lib.c diff --git a/lib.c b/lib.c index 251d932..f0fb6e2 100644 --- a/lib.c +++ b/lib.c @@ -51,7 +51,7 @@ void set_progname(const char *prog) const char *p; p = strrchr(prog, '/'); - progname = p ? p + 1 : progname; + progname = p ? p + 1 : prog; } /* Report an error or warning in Unix style, given a captured argument @@ -232,19 +232,21 @@ PRINTF_LIKE(2, 3) void dstr_putf(struct dstr *d, const char *p, ...) */ int dstr_readline(struct dstr *d, FILE *fp) { + char *p = d->p + d->len, *lim = d->p + d->sz; size_t n; - int any = 0; + int ch; + ch = getc(fp); if (ch == EOF) return (-1); for (;;) { - dstr_ensure(d, 2); - if (!fgets(d->p + d->len, d->sz - d->len, fp)) break; - n = strlen(d->p + d->len); assert(n > 0); any = 1; - d->len += n; - if (d->p[d->len - 1] == '\n') { d->p[--d->len] = 0; break; } + if (p == lim) { + n = d->len = p - d->p; dstr_ensure(d, 1); + p = d->p + n; lim = d->p + d->sz; + } + if (ch == EOF || ch == '\n') break; + *p++ = ch; ch = getc(fp); } - - if (!any) return (-1); - else return (0); + d->len = p - d->p; *p++ = 0; + return (0); } /*----- Dynamic vectors of strings ----------------------------------------*/ @@ -377,7 +379,7 @@ void argv_prependl(struct argv *av, ...) /* Return nonzero if the AN-byte string A is strictly precedes the BN-byte * string B in a lexicographic ordering. * - * All comparisons of keys is handled by this function. + * All comparison of keys is handled by this function. */ static int str_lt(const char *a, size_t an, const char *b, size_t bn) { @@ -515,7 +517,7 @@ void treap_insert(struct treap *t, const struct treap_path *p, * / \ / \ * X Y Y Z * - * On the other hand, if we ere planning to hook N as the right subtree + * On the other hand, if we were planning to hook N as the right subtree * of U, then we do the opposite rotation: * * | | @@ -735,7 +737,7 @@ static void check_subtree(struct treap_node *n, unsigned maxwt, if (khi) assert(STRCMP(n->k, <, khi)); /* Check the left subtree. Node weights must be bounded above by our own - * weight. And everykey in the left subtree must be smaller than our + * weight. And every key in the left subtree must be smaller than our * current key. We propagate the lower bound. */ if (n->left) check_subtree(n->left, n->wt, klo, n->k); @@ -953,9 +955,9 @@ static void set_config_section_parents(struct config *conf, * Inheritance cycles and ambiguous inheritance are diagnosed as fatal * errors. */ -struct config_var *search_recursive(struct config *conf, - struct config_section *sect, - const char *name, size_t sz) +static struct config_var *search_recursive(struct config *conf, + struct config_section *sect, + const char *name, size_t sz) { struct config_cache_entry *cache; struct treap_path path; @@ -1251,7 +1253,7 @@ void config_read_env(struct config *conf, struct config_section *sect) * * This only keeps track of the immutable parameters for the substitution * task: stuff which changes (flags, filtering state, cursor position) is - * maintained separately. + * maintained separately. */ struct subst { struct config *config; /* configuration state */ @@ -1336,8 +1338,9 @@ static void filter_string(const char *p, const char *l, /* Scan and resolve a `[SECT:]VAR' specifier at P. * - * Return the address of the next character following the specifier. L is a - * limit on the region of the buffer that we should process; SB is the + * Return the address of the next character following the specifier; and set + * *VAR_OUT to point to the variable we found, or null if it's not there. L + * is a limit on the region of the buffer that we should process; SB is the * substitution state which provides the home section if none is given * explicitly; FILE and LINE are the source location to blame for problems. */ @@ -1379,7 +1382,12 @@ static const char *subst(const char *p, const char *l, size_t n; /* It would be best if we could process literal text at high speed. To - * this end, + * this end, we have a table, indexed by the low-order bits of F, to tell + * us which special characters we need to stop at. This way, we can use + * `strcspn' to skip over literal text and stop at the next character which + * needs special handling. Entries in this table with a null pointer + * correspond to impossible flag settings: notably, `SF_QUOT' can only be + * set when `SF_SUBST' is also set. */ static const char *const delimtab[] = { @@ -1391,26 +1399,27 @@ static const char *subst(const char *p, const char *l, * `SF_QUOT' */ #define DELIM "|}" /* end delimiters of `SF_SUBEXPR' */ - ESCAPE, - ESCAPE WORDSEP, - 0, - ESCAPE QUOT, - ESCAPE SUBST, - ESCAPE SUBST WORDSEP, - 0, - ESCAPE SUBST QUOT, - ESCAPE DELIM, - ESCAPE DELIM WORDSEP, - 0, - ESCAPE DELIM QUOT, - ESCAPE DELIM SUBST, - ESCAPE DELIM SUBST WORDSEP, - 0, - ESCAPE DELIM SUBST QUOT - -#undef COMMON + ESCAPE, /* --- */ + ESCAPE WORDSEP, /* SPLIT */ + 0, /* QUOT */ + ESCAPE QUOT, /* SPLIT | QUOT */ + ESCAPE SUBST, /* SUBST */ + ESCAPE SUBST WORDSEP, /* SPLIT | SUBST */ + 0, /* QUOT | SUBST */ + ESCAPE SUBST QUOT, /* SPLIT | QUOT | SUBST */ + ESCAPE DELIM, /* SUBEXPR */ + ESCAPE DELIM WORDSEP, /* SPLIT | SUBEXPR */ + 0, /* QUOT | SUBEXPR */ + ESCAPE DELIM QUOT, /* SPLIT | QUOT | SUBEXPR */ + ESCAPE DELIM SUBST, /* SUBST | SUBEXPR */ + ESCAPE DELIM SUBST WORDSEP, /* SPLIT | SUBST | SUBEXPR */ + 0, /* QUOT | SUBST | SUBEXPR */ + ESCAPE DELIM SUBST QUOT /* SPLIT | QUOT | SUBST | SUBEXPR */ + +#undef ESCAPE +#undef SUBST #undef WORDSEP -#undef SQUOT +#undef QUOT #undef DELIM }; @@ -1451,12 +1460,12 @@ static const char *subst(const char *p, const char *l, * to it. */ - /* If there's no next charact3er then we should be upset. */ + /* If there's no next character then we should be upset. */ p++; if (p >= l) lose("%s:%u: unfinished `\\' escape", file, line); if (!(f&SF_SKIP)) { - /* If this is a double quote or backslash then check DFLT to see if + /* If this is a double quote or backslash then check QFILT to see if * it needs escaping. */ if (qfilt && (*p == '"' || *p == '\\')) @@ -1583,13 +1592,13 @@ static const char *subst(const char *p, const char *l, * toothpick, so now we need Q + (Q + 1) = 2 Q + 1 toothpicks. * * Calculate this here rather than at each point toothpicks - * needs to be deployed. + * need to be deployed. */ subqfilt = 2*subqfilt + 1; else if (t - p == 1 && *p == 'l') - /* `u' -- convert to uppercase. + /* `l' -- convert to lowercase. * * If a case conversion is already set, then that will override * whatever we do here, so don't bother. @@ -1631,7 +1640,7 @@ static const char *subst(const char *p, const char *l, /* If there's an alternative, then we need to process (or maybe * skip) it. Otherwise, we should complain if there was no - * veriable, and we're not skipping. + * variable, and we're not skipping. */ if (p < l && *p == '?') p = subst(p + 1, l, sb, file, line, subqfilt,