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
if (need <= av->sz) return;
newsz = av->sz ? 2*av->sz : 8;
while (newsz < need) newsz *= 2;
- av->v = xrealloc(av->v - av->o, newsz*sizeof(char *)) + av->o;
+ av->v = xrealloc(av->v - av->o, newsz*sizeof(char *)); av->v += av->o;
av->sz = newsz;
}
/* 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)
{
* This is similar to `treap_lookup', in that it returns the requested node
* if it already exists, or null otherwise, but it also records in P
* information to be used by `treap_insert' to insert a new node with the
- * given key it's not there already.
+ * given key if it's not there already.
*/
void *treap_probe(struct treap *t, const char *k, size_t kn,
struct treap_path *p)
* subtree of U, then we rotate like this:
*
* | |
- * U N
+ * U (N)
* / \ / \
* (N) Z ---> X U
* / \ / \
* 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:
*
* | |
- * U N
+ * U (N)
* / \ / \
* X (N) ---> U Z
* / \ / \
* / \ / \
* L R ---> X (N)
* / \ / \
- * X Y Y Z
+ * X Y Y R
*
* or
*
* Again, these transformations clearly preserve the ordering of nodes in
* the binary search tree, and the heap condition.
*/
- else if (l->wt > r->wt) { *nn = l; n->left = l->right; nn = &l->right; }
- else { *nn = r; n->right = r->left; nn = &r->left; }
+ else if (l->wt > r->wt)
+ { *nn = l; nn = &l->right; l = n->left = l->right; }
+ else
+ { *nn = r; nn = &r->left; r = n->right = r->left; }
/* Release the key buffer, and return the node that we've now detached. */
free(n->k); return (n);
*
* * If the current node's right subtree is not empty, then the next node
* to be visited is the leftmost node in that subtree. All of the
- * nodes on the stack are ancestors of the current nodes, and the right
+ * nodes on the stack are ancestors of the current node, and the right
* subtree consists of its descendants, so none of them are already on
- * the stack, and they're all greater than the current node, and
+ * the stack; and they're all greater than the current node, and
* therefore haven't been visited. Therefore, we must push the current
* node's right child, its /left/ child, and so on, proceeding
* leftwards until we fall off the bottom of the tree.
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);
* to have, so we can allocate the `parents' vector and fill it in.
*/
sect->nparents = av.n/2;
- sect->parents = xmalloc(sect->nparents*sizeof(sect->parents));
+ sect->parents = xmalloc(sect->nparents*sizeof(*sect->parents));
for (i = 0; i < av.n; i += 2) {
n = av.v[i + 1] - av.v[i];
parent = config_find_section_n(conf, 0, av.v[i], n);
* 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;
/* Set variable NAME to VALUE in SECT, with associated flags F.
*
* The names are null-terminated. The flags are variable flags: see `struct
- * config_var' for details.
+ * config_var' for details. Returns the variable.
*
* If the variable is already set and has the `CF_OVERRIDE' flag, then this
* function does nothing unless `CF_OVERRIDE' is /also/ set in F.
*/
-void config_set_var(struct config *conf, struct config_section *sect,
- unsigned f, const char *name, const char *value)
+struct config_var *config_set_var(struct config *conf,
+ struct config_section *sect,
+ unsigned f,
+ const char *name, const char *value)
{
- config_set_var_n(conf, sect, f,
- name, strlen(name),
- value, strlen(value));
+ return (config_set_var_n(conf, sect, f,
+ name, strlen(name),
+ value, strlen(value)));
}
/* As `config_set_var', except that the variable NAME and VALUE have explicit
* lengths (NAMELEN and VALUELEN, respectively) rather than being null-
* terminated.
*/
-void config_set_var_n(struct config *conf, struct config_section *sect,
- unsigned f,
- const char *name, size_t namelen,
- const char *value, size_t valuelen)
+struct config_var *config_set_var_n(struct config *conf,
+ struct config_section *sect,
+ unsigned f,
+ const char *name, size_t namelen,
+ const char *value, size_t valuelen)
{
struct config_var *var =
config_find_var_n(conf, sect, CF_CREAT, name, namelen);
- if (var->f&~f&CF_OVERRIDE) return;
+ if (var->f&~f&CF_OVERRIDE) return (var);
free(var->val); var->val = xstrndup(value, valuelen); var->n = valuelen;
var->f = f;
+ return (var);
}
/* Initialize I to iterate over the variables directly defined in 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 */
/* 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.
*/
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[] = {
* `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
};
* 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 == '\\'))
* 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.