=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/format.c,v retrieving revision 1.262 retrieving revision 1.263 diff -c -r1.262 -r1.263 *** src/usr.bin/tmux/format.c 2020/09/16 18:37:55 1.262 --- src/usr.bin/tmux/format.c 2020/10/06 07:36:05 1.263 *************** *** 1,4 **** ! /* $OpenBSD: format.c,v 1.262 2020/09/16 18:37:55 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: format.c,v 1.263 2020/10/06 07:36:05 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott *************** *** 38,52 **** * string. */ ! static char *format_job_get(struct format_tree *, const char *); ! static void format_job_timer(int, short, void *); ! static int format_replace(struct format_tree *, const char *, size_t, ! char **, size_t *, size_t *); static void format_defaults_session(struct format_tree *, struct session *); static void format_defaults_client(struct format_tree *, struct client *); ! static void format_defaults_winlink(struct format_tree *, struct winlink *); /* Entry in format job tree. */ struct format_job { --- 38,55 ---- * string. */ ! struct format_expand_state; ! static char *format_job_get(struct format_expand_state *, const char *); ! static void format_job_timer(int, short, void *); ! static char *format_expand1(struct format_expand_state *, const char *); ! static int format_replace(struct format_expand_state *, const char *, ! size_t, char **, size_t *, size_t *); static void format_defaults_session(struct format_tree *, struct session *); static void format_defaults_client(struct format_tree *, struct client *); ! static void format_defaults_winlink(struct format_tree *, ! struct winlink *); /* Entry in format job tree. */ struct format_job { *************** *** 99,109 **** /* Limit on recursion. */ #define FORMAT_LOOP_LIMIT 10 /* Entry in format tree. */ struct format_entry { char *key; char *value; ! time_t t; format_cb cb; RB_ENTRY(format_entry) entry; }; --- 102,116 ---- /* Limit on recursion. */ #define FORMAT_LOOP_LIMIT 10 + /* Format expand flags. */ + #define FORMAT_EXPAND_TIME 0x1 + #define FORMAT_EXPAND_NOJOBS 0x2 + /* Entry in format tree. */ struct format_entry { char *key; char *value; ! time_t time; format_cb cb; RB_ENTRY(format_entry) entry; }; *************** *** 120,127 **** struct client *client; int flags; u_int tag; - time_t time; - u_int loop; struct mouse_event m; --- 127,132 ---- *************** *** 130,135 **** --- 135,148 ---- static int format_entry_cmp(struct format_entry *, struct format_entry *); RB_GENERATE_STATIC(format_entry_tree, format_entry, entry, format_entry_cmp); + /* Format expand state. */ + struct format_expand_state { + struct format_tree *ft; + u_int loop; + time_t time; + int flags; + }; + /* Format modifier. */ struct format_modifier { char modifier[3]; *************** *** 215,222 **** /* Log a message if verbose. */ static void printflike(3, 4) ! format_log1(struct format_tree *ft, const char *from, const char *fmt, ...) { va_list ap; char *s; static const char spaces[] = " "; --- 228,237 ---- /* Log a message if verbose. */ static void printflike(3, 4) ! format_log1(struct format_expand_state *es, const char *from, const char *fmt, ! ...) { + struct format_tree *ft = es->ft; va_list ap; char *s; static const char spaces[] = " "; *************** *** 230,241 **** log_debug("%s: %s", from, s); if (ft->item != NULL && (ft->flags & FORMAT_VERBOSE)) ! cmdq_print(ft->item, "#%.*s%s", ft->loop, spaces, s); free(s); } ! #define format_log(ft, fmt, ...) format_log1(ft, __func__, fmt, ##__VA_ARGS__) /* Format job update callback. */ static void format_job_update(struct job *job) --- 245,267 ---- log_debug("%s: %s", from, s); if (ft->item != NULL && (ft->flags & FORMAT_VERBOSE)) ! cmdq_print(ft->item, "#%.*s%s", es->loop, spaces, s); free(s); } ! #define format_log(es, fmt, ...) format_log1(es, __func__, fmt, ##__VA_ARGS__) + /* Copy expand state. */ + static void + format_copy_state(struct format_expand_state *to, + struct format_expand_state *from, int flags) + { + to->ft = from->ft; + to->loop = from->loop; + to->time = from->time; + to->flags = from->flags|flag; + } + /* Format job update callback. */ static void format_job_update(struct job *job) *************** *** 304,316 **** /* Find a job. */ static char * ! format_job_get(struct format_tree *ft, const char *cmd) { ! struct format_job_tree *jobs; ! struct format_job fj0, *fj; ! time_t t; ! char *expanded; ! int force; if (ft->client == NULL) jobs = &format_jobs; --- 330,344 ---- /* Find a job. */ static char * ! format_job_get(struct format_expand_state *es, const char *cmd) { ! struct format_tree *ft = es->ft; ! struct format_job_tree *jobs; ! struct format_job fj0, *fj; ! time_t t; ! char *expanded; ! int force; ! struct format_expand_state next; if (ft->client == NULL) jobs = &format_jobs; *************** *** 335,341 **** RB_INSERT(format_job_tree, jobs, fj); } ! expanded = format_expand(ft, cmd); if (fj->expanded == NULL || strcmp(expanded, fj->expanded) != 0) { free((void *)fj->expanded); fj->expanded = xstrdup(expanded); --- 363,369 ---- RB_INSERT(format_job_tree, jobs, fj); } ! expanded = format_expand1(es, cmd); if (fj->expanded == NULL || strcmp(expanded, fj->expanded) != 0) { free((void *)fj->expanded); fj->expanded = xstrdup(expanded); *************** *** 357,368 **** fj->last = t; fj->updated = 0; } if (ft->flags & FORMAT_STATUS) fj->status = 1; ! ! free(expanded); ! return (format_expand(ft, fj->out)); } /* Remove old jobs. */ --- 385,396 ---- fj->last = t; fj->updated = 0; } + free(expanded); if (ft->flags & FORMAT_STATUS) fj->status = 1; ! format_copy_state(&next, es, FORMAT_EXPAND_NOJOBS); ! return (format_expand1(&next, fj->out)); } /* Remove old jobs. */ *************** *** 1211,1217 **** ft->tag = tag; ft->flags = flags; - ft->time = time(NULL); format_add(ft, "version", "%s", getversion()); format_add_cb(ft, "host", format_cb_host); --- 1239,1244 ---- *************** *** 1261,1268 **** char s[64]; RB_FOREACH(fe, format_entry_tree, &ft->tree) { ! if (fe->t != 0) { ! xsnprintf(s, sizeof s, "%lld", (long long)fe->t); cb(fe->key, s, arg); } else { if (fe->value == NULL && fe->cb != NULL) { --- 1288,1295 ---- char s[64]; RB_FOREACH(fe, format_entry_tree, &ft->tree) { ! if (fe->time != 0) { ! xsnprintf(s, sizeof s, "%lld", (long long)fe->time); cb(fe->key, s, arg); } else { if (fe->value == NULL && fe->cb != NULL) { *************** *** 1295,1301 **** } fe->cb = NULL; ! fe->t = 0; va_start(ap, fmt); xvasprintf(&fe->value, fmt, ap); --- 1322,1328 ---- } fe->cb = NULL; ! fe->time = 0; va_start(ap, fmt); xvasprintf(&fe->value, fmt, ap); *************** *** 1320,1326 **** } fe->cb = NULL; ! fe->t = tv->tv_sec; fe->value = NULL; } --- 1347,1353 ---- } fe->cb = NULL; ! fe->time = tv->tv_sec; fe->value = NULL; } *************** *** 1344,1350 **** } fe->cb = cb; ! fe->t = 0; fe->value = NULL; } --- 1371,1377 ---- } fe->cb = cb; ! fe->time = 0; fe->value = NULL; } *************** *** 1440,1447 **** fe_find.key = (char *)key; fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find); if (fe != NULL) { ! if (fe->t != 0) { ! t = fe->t; goto found; } if (fe->value == NULL && fe->cb != NULL) { --- 1467,1474 ---- fe_find.key = (char *)key; fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find); if (fe != NULL) { ! if (fe->time != 0) { ! t = fe->time; goto found; } if (fe->value == NULL && fe->cb != NULL) { *************** *** 1563,1570 **** /* Return left and right alternatives separated by commas. */ static int ! format_choose(struct format_tree *ft, const char *s, char **left, char **right, ! int expand) { const char *cp; char *left0, *right0; --- 1590,1597 ---- /* Return left and right alternatives separated by commas. */ static int ! format_choose(struct format_expand_state *es, const char *s, char **left, ! char **right, int expand) { const char *cp; char *left0, *right0; *************** *** 1576,1584 **** right0 = xstrdup(cp + 1); if (expand) { ! *left = format_expand(ft, left0); free(left0); ! *right = format_expand(ft, right0); free(right0); } else { *left = left0; --- 1603,1611 ---- right0 = xstrdup(cp + 1); if (expand) { ! *left = format_expand1(es, left0); free(left0); ! *right = format_expand1(es, right0); free(right0); } else { *left = left0; *************** *** 1634,1640 **** /* Build modifier list. */ static struct format_modifier * ! format_build_modifiers(struct format_tree *ft, const char **s, u_int *count) { const char *cp = *s, *end; struct format_modifier *list = NULL; --- 1661,1668 ---- /* Build modifier list. */ static struct format_modifier * ! format_build_modifiers(struct format_expand_state *es, const char **s, ! u_int *count) { const char *cp = *s, *end; struct format_modifier *list = NULL; *************** *** 1702,1708 **** argv = xcalloc(1, sizeof *argv); value = xstrndup(cp + 1, end - (cp + 1)); ! argv[0] = format_expand(ft, value); free(value); argc = 1; --- 1730,1736 ---- argv = xcalloc(1, sizeof *argv); value = xstrndup(cp + 1, end - (cp + 1)); ! argv[0] = format_expand1(es, value); free(value); argc = 1; *************** *** 1726,1732 **** argv = xreallocarray (argv, argc + 1, sizeof *argv); value = xstrndup(cp, end - cp); ! argv[argc++] = format_expand(ft, value); free(value); cp = end; --- 1754,1760 ---- argv = xreallocarray (argv, argc + 1, sizeof *argv); value = xstrndup(cp, end - cp); ! argv[argc++] = format_expand1(es, value); free(value); cp = end; *************** *** 1807,1831 **** /* Loop over sessions. */ static char * ! format_loop_sessions(struct format_tree *ft, const char *fmt) { ! struct client *c = ft->client; ! struct cmdq_item *item = ft->item; ! struct format_tree *nft; ! char *expanded, *value; ! size_t valuelen; ! struct session *s; value = xcalloc(1, 1); valuelen = 1; RB_FOREACH(s, sessions, &sessions) { ! format_log(ft, "session loop: $%u", s->id); nft = format_create(c, item, FORMAT_NONE, ft->flags); ! nft->loop = ft->loop; ! format_defaults(nft, ft->c, s, NULL, NULL); ! expanded = format_expand(nft, fmt); ! format_free(nft); valuelen += strlen(expanded); value = xrealloc(value, valuelen); --- 1835,1862 ---- /* Loop over sessions. */ static char * ! format_loop_sessions(struct format_expand_state *es, const char *fmt) { ! struct format_tree *ft = es->ft; ! struct client *c = ft->client; ! struct cmdq_item *item = ft->item; ! struct format_tree *nft; ! struct format_expand_state next; ! char *expanded, *value; ! size_t valuelen; ! struct session *s; value = xcalloc(1, 1); valuelen = 1; RB_FOREACH(s, sessions, &sessions) { ! format_log(es, "session loop: $%u", s->id); nft = format_create(c, item, FORMAT_NONE, ft->flags); ! format_defaults(next.ft, ft->c, s, NULL, NULL); ! format_copy_state(&next, es, 0); ! next.ft = nft; ! expanded = format_expand1(&next, fmt); ! format_free(next.ft); valuelen += strlen(expanded); value = xrealloc(value, valuelen); *************** *** 1839,1860 **** /* Loop over windows. */ static char * ! format_loop_windows(struct format_tree *ft, const char *fmt) { ! struct client *c = ft->client; ! struct cmdq_item *item = ft->item; ! struct format_tree *nft; ! char *all, *active, *use, *expanded, *value; ! size_t valuelen; ! struct winlink *wl; ! struct window *w; if (ft->s == NULL) { ! format_log(ft, "window loop but no session"); return (NULL); } ! if (format_choose(ft, fmt, &all, &active, 0) != 0) { all = xstrdup(fmt); active = NULL; } --- 1870,1893 ---- /* Loop over windows. */ static char * ! format_loop_windows(struct format_expand_state *es, const char *fmt) { ! struct format_tree *ft = es->ft; ! struct client *c = ft->client; ! struct cmdq_item *item = ft->item; ! struct format_tree *nft; ! struct format_expand_state next; ! char *all, *active, *use, *expanded, *value; ! size_t valuelen; ! struct winlink *wl; ! struct window *w; if (ft->s == NULL) { ! format_log(es, "window loop but no session"); return (NULL); } ! if (format_choose(es, fmt, &all, &active, 0) != 0) { all = xstrdup(fmt); active = NULL; } *************** *** 1864,1878 **** RB_FOREACH(wl, winlinks, &ft->s->windows) { w = wl->window; ! format_log(ft, "window loop: %u @%u", wl->idx, w->id); if (active != NULL && wl == ft->s->curw) use = active; else use = all; nft = format_create(c, item, FORMAT_WINDOW|w->id, ft->flags); - nft->loop = ft->loop; format_defaults(nft, ft->c, ft->s, wl, NULL); ! expanded = format_expand(nft, use); format_free(nft); valuelen += strlen(expanded); --- 1897,1912 ---- RB_FOREACH(wl, winlinks, &ft->s->windows) { w = wl->window; ! format_log(es, "window loop: %u @%u", wl->idx, w->id); if (active != NULL && wl == ft->s->curw) use = active; else use = all; nft = format_create(c, item, FORMAT_WINDOW|w->id, ft->flags); format_defaults(nft, ft->c, ft->s, wl, NULL); ! format_copy_state(&next, es, 0); ! next.ft = nft; ! expanded = format_expand1(&next, use); format_free(nft); valuelen += strlen(expanded); *************** *** 1890,1910 **** /* Loop over panes. */ static char * ! format_loop_panes(struct format_tree *ft, const char *fmt) { ! struct client *c = ft->client; ! struct cmdq_item *item = ft->item; ! struct format_tree *nft; ! char *all, *active, *use, *expanded, *value; ! size_t valuelen; ! struct window_pane *wp; if (ft->w == NULL) { ! format_log(ft, "pane loop but no window"); return (NULL); } ! if (format_choose(ft, fmt, &all, &active, 0) != 0) { all = xstrdup(fmt); active = NULL; } --- 1924,1946 ---- /* Loop over panes. */ static char * ! format_loop_panes(struct format_expand_state *es, const char *fmt) { ! struct format_tree *ft = es->ft; ! struct client *c = ft->client; ! struct cmdq_item *item = ft->item; ! struct format_tree *nft; ! struct format_expand_state next; ! char *all, *active, *use, *expanded, *value; ! size_t valuelen; ! struct window_pane *wp; if (ft->w == NULL) { ! format_log(es, "pane loop but no window"); return (NULL); } ! if (format_choose(es, fmt, &all, &active, 0) != 0) { all = xstrdup(fmt); active = NULL; } *************** *** 1913,1927 **** valuelen = 1; TAILQ_FOREACH(wp, &ft->w->panes, entry) { ! format_log(ft, "pane loop: %%%u", wp->id); if (active != NULL && wp == ft->w->active) use = active; else use = all; nft = format_create(c, item, FORMAT_PANE|wp->id, ft->flags); - nft->loop = ft->loop; format_defaults(nft, ft->c, ft->s, ft->wl, wp); ! expanded = format_expand(nft, use); format_free(nft); valuelen += strlen(expanded); --- 1949,1964 ---- valuelen = 1; TAILQ_FOREACH(wp, &ft->w->panes, entry) { ! format_log(es, "pane loop: %%%u", wp->id); if (active != NULL && wp == ft->w->active) use = active; else use = all; nft = format_create(c, item, FORMAT_PANE|wp->id, ft->flags); format_defaults(nft, ft->c, ft->s, ft->wl, wp); ! format_copy_state(&next, es, 0); ! next.ft = nft; ! expanded = format_expand1(&next, use); format_free(nft); valuelen += strlen(expanded); *************** *** 1938,1952 **** } static char * ! format_replace_expression(struct format_modifier *mexp, struct format_tree *ft, ! const char *copy) { ! int argc = mexp->argc; ! const char *errstr; ! char *endch, *value, *left = NULL, *right = NULL; ! int use_fp = 0; ! u_int prec = 0; ! double mleft, mright, result; enum { ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULUS } operator; if (strcmp(mexp->argv[0], "+") == 0) --- 1975,1989 ---- } static char * ! format_replace_expression(struct format_modifier *mexp, ! struct format_expand_state *es, const char *copy) { ! int argc = mexp->argc; ! const char *errstr; ! char *endch, *value, *left = NULL, *right = NULL; ! int use_fp = 0; ! u_int prec = 0; ! double mleft, mright, result; enum { ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULUS } operator; if (strcmp(mexp->argv[0], "+") == 0) *************** *** 1961,1967 **** strcmp(mexp->argv[0], "m") == 0) operator = MODULUS; else { ! format_log(ft, "expression has no valid operator: '%s'", mexp->argv[0]); goto fail; } --- 1998,2004 ---- strcmp(mexp->argv[0], "m") == 0) operator = MODULUS; else { ! format_log(es, "expression has no valid operator: '%s'", mexp->argv[0]); goto fail; } *************** *** 1976,2001 **** if (argc >= 3) { prec = strtonum(mexp->argv[2], INT_MIN, INT_MAX, &errstr); if (errstr != NULL) { ! format_log (ft, "expression precision %s: %s", errstr, mexp->argv[2]); goto fail; } } ! if (format_choose(ft, copy, &left, &right, 1) != 0) { ! format_log(ft, "expression syntax error"); goto fail; } mleft = strtod(left, &endch); if (*endch != '\0') { ! format_log(ft, "expression left side is invalid: %s", left); goto fail; } mright = strtod(right, &endch); if (*endch != '\0') { ! format_log(ft, "expression right side is invalid: %s", right); goto fail; } --- 2013,2038 ---- if (argc >= 3) { prec = strtonum(mexp->argv[2], INT_MIN, INT_MAX, &errstr); if (errstr != NULL) { ! format_log(es, "expression precision %s: %s", errstr, mexp->argv[2]); goto fail; } } ! if (format_choose(es, copy, &left, &right, 1) != 0) { ! format_log(es, "expression syntax error"); goto fail; } mleft = strtod(left, &endch); if (*endch != '\0') { ! format_log(es, "expression left side is invalid: %s", left); goto fail; } mright = strtod(right, &endch); if (*endch != '\0') { ! format_log(es, "expression right side is invalid: %s", right); goto fail; } *************** *** 2003,2010 **** mleft = (long long)mleft; mright = (long long)mright; } ! format_log(ft, "expression left side is: %.*f", prec, mleft); ! format_log(ft, "expression right side is: %.*f", prec, mright); switch (operator) { case ADD: --- 2040,2047 ---- mleft = (long long)mleft; mright = (long long)mright; } ! format_log(es, "expression left side is: %.*f", prec, mleft); ! format_log(es, "expression right side is: %.*f", prec, mright); switch (operator) { case ADD: *************** *** 2027,2033 **** xasprintf(&value, "%.*f", prec, result); else xasprintf(&value, "%.*f", prec, (double)(long long)result); ! format_log(ft, "expression result is %s", value); free(right); free(left); --- 2064,2070 ---- xasprintf(&value, "%.*f", prec, result); else xasprintf(&value, "%.*f", prec, (double)(long long)result); ! format_log(es, "expression result is %s", value); free(right); free(left); *************** *** 2041,2071 **** /* Replace a key. */ static int ! format_replace(struct format_tree *ft, const char *key, size_t keylen, char **buf, size_t *len, size_t *off) { ! struct window_pane *wp = ft->wp; ! const char *errptr, *copy, *cp, *marker = NULL; ! const char *time_format = NULL; ! char *copy0, *condition, *found, *new; ! char *value, *left, *right; ! size_t valuelen; ! int modifiers = 0, limit = 0, width = 0, j; ! struct format_modifier *list, *fm, *cmp = NULL, *search = NULL; ! struct format_modifier **sub = NULL, *mexp = NULL; ! u_int i, count, nsub = 0; /* Make a copy of the key. */ copy = copy0 = xstrndup(key, keylen); /* Process modifier list. */ ! list = format_build_modifiers(ft, ©, &count); for (i = 0; i < count; i++) { fm = &list[i]; if (format_logging(ft)) { ! format_log(ft, "modifier %u is %s", i, fm->modifier); for (j = 0; j < fm->argc; j++) { ! format_log(ft, "modifier %u argument %d: %s", i, j, fm->argv[j]); } } --- 2078,2111 ---- /* Replace a key. */ static int ! format_replace(struct format_expand_state *es, const char *key, size_t keylen, char **buf, size_t *len, size_t *off) { ! struct format_tree *ft = es->ft; ! struct window_pane *wp = ft->wp; ! const char *errptr, *copy, *cp, *marker = NULL; ! const char *time_format = NULL; ! char *copy0, *condition, *found, *new; ! char *value, *left, *right; ! size_t valuelen; ! int modifiers = 0, limit = 0, width = 0; ! int j; ! struct format_modifier *list, *cmp = NULL, *search = NULL; ! struct format_modifier **sub = NULL, *mexp = NULL, *fm; ! u_int i, count, nsub = 0; ! struct format_expand_state next; /* Make a copy of the key. */ copy = copy0 = xstrndup(key, keylen); /* Process modifier list. */ ! list = format_build_modifiers(es, ©, &count); for (i = 0; i < count; i++) { fm = &list[i]; if (format_logging(ft)) { ! format_log(es, "modifier %u is %s", i, fm->modifier); for (j = 0; j < fm->argc; j++) { ! format_log(es, "modifier %u argument %d: %s", i, j, fm->argv[j]); } } *************** *** 2169,2205 **** /* Is this a loop, comparison or condition? */ if (modifiers & FORMAT_SESSIONS) { ! value = format_loop_sessions(ft, copy); if (value == NULL) goto fail; } else if (modifiers & FORMAT_WINDOWS) { ! value = format_loop_windows(ft, copy); if (value == NULL) goto fail; } else if (modifiers & FORMAT_PANES) { ! value = format_loop_panes(ft, copy); if (value == NULL) goto fail; } else if (search != NULL) { /* Search in pane. */ ! new = format_expand(ft, copy); if (wp == NULL) { ! format_log(ft, "search '%s' but no pane", new); value = xstrdup("0"); } else { ! format_log(ft, "search '%s' pane %%%u", new, wp->id); value = format_search(fm, wp, new); } free(new); } else if (cmp != NULL) { /* Comparison of left and right. */ ! if (format_choose(ft, copy, &left, &right, 1) != 0) { ! format_log(ft, "compare %s syntax error: %s", cmp->modifier, copy); goto fail; } ! format_log(ft, "compare %s left is: %s", cmp->modifier, left); ! format_log(ft, "compare %s right is: %s", cmp->modifier, right); if (strcmp(cmp->modifier, "||") == 0) { if (format_true(left) || format_true(right)) --- 2209,2245 ---- /* Is this a loop, comparison or condition? */ if (modifiers & FORMAT_SESSIONS) { ! value = format_loop_sessions(es, copy); if (value == NULL) goto fail; } else if (modifiers & FORMAT_WINDOWS) { ! value = format_loop_windows(es, copy); if (value == NULL) goto fail; } else if (modifiers & FORMAT_PANES) { ! value = format_loop_panes(es, copy); if (value == NULL) goto fail; } else if (search != NULL) { /* Search in pane. */ ! new = format_expand1(es, copy); if (wp == NULL) { ! format_log(es, "search '%s' but no pane", new); value = xstrdup("0"); } else { ! format_log(es, "search '%s' pane %%%u", new, wp->id); value = format_search(fm, wp, new); } free(new); } else if (cmp != NULL) { /* Comparison of left and right. */ ! if (format_choose(es, copy, &left, &right, 1) != 0) { ! format_log(es, "compare %s syntax error: %s", cmp->modifier, copy); goto fail; } ! format_log(es, "compare %s left is: %s", cmp->modifier, left); ! format_log(es, "compare %s right is: %s", cmp->modifier, right); if (strcmp(cmp->modifier, "||") == 0) { if (format_true(left) || format_true(right)) *************** *** 2250,2260 **** /* Conditional: check first and choose second or third. */ cp = format_skip(copy + 1, ","); if (cp == NULL) { ! format_log(ft, "condition syntax error: %s", copy + 1); goto fail; } condition = xstrndup(copy + 1, cp - (copy + 1)); ! format_log(ft, "condition is: %s", condition); found = format_find(ft, condition, modifiers, time_format); if (found == NULL) { --- 2290,2300 ---- /* Conditional: check first and choose second or third. */ cp = format_skip(copy + 1, ","); if (cp == NULL) { ! format_log(es, "condition syntax error: %s", copy + 1); goto fail; } condition = xstrndup(copy + 1, cp - (copy + 1)); ! format_log(es, "condition is: %s", condition); found = format_find(ft, condition, modifiers, time_format); if (found == NULL) { *************** *** 2263,2294 **** * the expansion doesn't have any effect, then assume * false. */ ! found = format_expand(ft, condition); if (strcmp(found, condition) == 0) { free(found); found = xstrdup(""); ! format_log(ft, "condition '%s' found: %s", condition, found); } else { ! format_log(ft, "condition '%s' not found; assuming false", condition); } } else ! format_log(ft, "condition '%s' found", condition); ! if (format_choose(ft, cp + 1, &left, &right, 0) != 0) { ! format_log(ft, "condition '%s' syntax error: %s", condition, cp + 1); free(found); goto fail; } if (format_true(found)) { ! format_log(ft, "condition '%s' is true", condition); ! value = format_expand(ft, left); } else { ! format_log(ft, "condition '%s' is false", condition); ! value = format_expand(ft, right); } free(right); free(left); --- 2303,2334 ---- * the expansion doesn't have any effect, then assume * false. */ ! found = format_expand1(es, condition); if (strcmp(found, condition) == 0) { free(found); found = xstrdup(""); ! format_log(es, "condition '%s' found: %s", condition, found); } else { ! format_log(es, "condition '%s' not found; assuming false", condition); } } else ! format_log(es, "condition '%s' found", condition); ! if (format_choose(es, cp + 1, &left, &right, 0) != 0) { ! format_log(es, "condition '%s' syntax error: %s", condition, cp + 1); free(found); goto fail; } if (format_true(found)) { ! format_log(es, "condition '%s' is true", condition); ! value = format_expand1(es, left); } else { ! format_log(es, "condition '%s' is false", condition); ! value = format_expand1(es, right); } free(right); free(left); *************** *** 2296,2336 **** free(condition); free(found); } else if (mexp != NULL) { ! value = format_replace_expression(mexp, ft, copy); if (value == NULL) value = xstrdup(""); } else { if (strstr(copy, "#{") != 0) { ! format_log(ft, "expanding inner format '%s'", copy); ! value = format_expand(ft, copy); } else { value = format_find(ft, copy, modifiers, time_format); if (value == NULL) { ! format_log(ft, "format '%s' not found", copy); value = xstrdup(""); ! } else ! format_log(ft, "format '%s' found: %s", copy, value); } } done: /* Expand again if required. */ if (modifiers & FORMAT_EXPAND) { ! new = format_expand(ft, value); free(value); value = new; } else if (modifiers & FORMAT_EXPANDTIME) { ! new = format_expand_time(ft, value); free(value); value = new; } /* Perform substitution if any. */ for (i = 0; i < nsub; i++) { ! left = format_expand(ft, sub[i]->argv[0]); ! right = format_expand(ft, sub[i]->argv[1]); new = format_sub(sub[i], value, left, right); ! format_log(ft, "substitute '%s' to '%s': %s", left, right, new); free(value); value = new; free(right); --- 2336,2379 ---- free(condition); free(found); } else if (mexp != NULL) { ! value = format_replace_expression(mexp, es, copy); if (value == NULL) value = xstrdup(""); } else { if (strstr(copy, "#{") != 0) { ! format_log(es, "expanding inner format '%s'", copy); ! value = format_expand1(es, copy); } else { value = format_find(ft, copy, modifiers, time_format); if (value == NULL) { ! format_log(es, "format '%s' not found", copy); value = xstrdup(""); ! } else { ! format_log(es, "format '%s' found: %s", copy, ! value); ! } } } done: /* Expand again if required. */ if (modifiers & FORMAT_EXPAND) { ! new = format_expand1(es, value); free(value); value = new; } else if (modifiers & FORMAT_EXPANDTIME) { ! format_copy_state(&next, es, FORMAT_EXPAND_TIME); ! new = format_expand1(&next, value); free(value); value = new; } /* Perform substitution if any. */ for (i = 0; i < nsub; i++) { ! left = format_expand1(es, sub[i]->argv[0]); ! right = format_expand1(es, sub[i]->argv[1]); new = format_sub(sub[i], value, left, right); ! format_log(es, "substitute '%s' to '%s': %s", left, right, new); free(value); value = new; free(right); *************** *** 2347,2353 **** free(value); value = new; } ! format_log(ft, "applied length limit %d: %s", limit, value); } else if (limit < 0) { new = format_trim_right(value, -limit); if (marker != NULL && strcmp(new, value) != 0) { --- 2390,2396 ---- free(value); value = new; } ! format_log(es, "applied length limit %d: %s", limit, value); } else if (limit < 0) { new = format_trim_right(value, -limit); if (marker != NULL && strcmp(new, value) != 0) { *************** *** 2357,2363 **** free(value); value = new; } ! format_log(ft, "applied length limit %d: %s", limit, value); } /* Pad the value if needed. */ --- 2400,2406 ---- free(value); value = new; } ! format_log(es, "applied length limit %d: %s", limit, value); } /* Pad the value if needed. */ *************** *** 2365,2376 **** new = utf8_padcstr(value, width); free(value); value = new; ! format_log(ft, "applied padding width %d: %s", width, value); } else if (width < 0) { new = utf8_rpadcstr(value, -width); free(value); value = new; ! format_log(ft, "applied padding width %d: %s", width, value); } /* Replace with the length if needed. */ --- 2408,2419 ---- new = utf8_padcstr(value, width); free(value); value = new; ! format_log(es, "applied padding width %d: %s", width, value); } else if (width < 0) { new = utf8_rpadcstr(value, -width); free(value); value = new; ! format_log(es, "applied padding width %d: %s", width, value); } /* Replace with the length if needed. */ *************** *** 2378,2384 **** xasprintf(&new, "%zu", strlen(value)); free(value); value = new; ! format_log(ft, "replacing with length: %s", new); } /* Expand the buffer and copy in the value. */ --- 2421,2427 ---- xasprintf(&new, "%zu", strlen(value)); free(value); value = new; ! format_log(es, "replacing with length: %s", new); } /* Expand the buffer and copy in the value. */ *************** *** 2390,2396 **** memcpy(*buf + *off, value, valuelen); *off += valuelen; ! format_log(ft, "replaced '%s' with '%s'", copy0, value); free(value); free(sub); --- 2433,2439 ---- memcpy(*buf + *off, value, valuelen); *off += valuelen; ! format_log(es, "replaced '%s' with '%s'", copy0, value); free(value); free(sub); *************** *** 2399,2405 **** return (0); fail: ! format_log(ft, "failed %s", copy0); free(sub); format_free_modifiers(list, count); --- 2442,2448 ---- return (0); fail: ! format_log(es, "failed %s", copy0); free(sub); format_free_modifiers(list, count); *************** *** 2409,2440 **** /* Expand keys in a template. */ static char * ! format_expand1(struct format_tree *ft, const char *fmt, int time) { ! char *buf, *out, *name; ! const char *ptr, *s; ! size_t off, len, n, outlen; ! int ch, brackets; ! struct tm *tm; ! char expanded[8192]; if (fmt == NULL || *fmt == '\0') return (xstrdup("")); ! if (ft->loop == FORMAT_LOOP_LIMIT) return (xstrdup("")); ! ft->loop++; ! format_log(ft, "expanding format: %s", fmt); ! if (time) { ! tm = localtime(&ft->time); if (strftime(expanded, sizeof expanded, fmt, tm) == 0) { ! format_log(ft, "format is too long"); return (xstrdup("")); } if (format_logging(ft) && strcmp(expanded, fmt) != 0) ! format_log(ft, "after time expanded: %s", expanded); fmt = expanded; } --- 2452,2486 ---- /* Expand keys in a template. */ static char * ! format_expand1(struct format_expand_state *es, const char *fmt) { ! struct format_tree *ft = es->ft; ! char *buf, *out, *name; ! const char *ptr, *s; ! size_t off, len, n, outlen; ! int ch, brackets; ! struct tm *tm; ! char expanded[8192]; if (fmt == NULL || *fmt == '\0') return (xstrdup("")); ! if (es->loop == FORMAT_LOOP_LIMIT) return (xstrdup("")); ! es->loop++; ! format_log(es, "expanding format: %s", fmt); ! if (es->flags & FORMAT_EXPAND_TIME) { ! if (es->time == 0) ! es->time = time(NULL); ! tm = localtime(&es->time); if (strftime(expanded, sizeof expanded, fmt, tm) == 0) { ! format_log(es, "format is too long"); return (xstrdup("")); } if (format_logging(ft) && strcmp(expanded, fmt) != 0) ! format_log(es, "after time expanded: %s", expanded); fmt = expanded; } *************** *** 2468,2481 **** n = ptr - fmt; name = xstrndup(fmt, n); ! format_log(ft, "found #(): %s", name); ! if (ft->flags & FORMAT_NOJOBS) { out = xstrdup(""); ! format_log(ft, "#() is disabled"); } else { ! out = format_job_get(ft, name); ! format_log(ft, "#() result: %s", out); } free(name); --- 2514,2528 ---- n = ptr - fmt; name = xstrndup(fmt, n); ! format_log(es, "found #(): %s", name); ! if ((ft->flags & FORMAT_NOJOBS) || ! (es->flags & FORMAT_EXPAND_NOJOBS)) { out = xstrdup(""); ! format_log(es, "#() is disabled"); } else { ! out = format_job_get(es, name); ! format_log(es, "#() result: %s", out); } free(name); *************** *** 2497,2511 **** break; n = ptr - fmt; ! format_log(ft, "found #{}: %.*s", (int)n, fmt); ! if (format_replace(ft, fmt, n, &buf, &len, &off) != 0) break; fmt += n + 1; continue; case '}': case '#': case ',': ! format_log(ft, "found #%c", ch); while (len - off < 2) { buf = xreallocarray(buf, 2, len); len *= 2; --- 2544,2558 ---- break; n = ptr - fmt; ! format_log(es, "found #{}: %.*s", (int)n, fmt); ! if (format_replace(es, fmt, n, &buf, &len, &off) != 0) break; fmt += n + 1; continue; case '}': case '#': case ',': ! format_log(es, "found #%c", ch); while (len - off < 2) { buf = xreallocarray(buf, 2, len); len *= 2; *************** *** 2528,2535 **** continue; } n = strlen(s); ! format_log(ft, "found #%c: %s", ch, s); ! if (format_replace(ft, s, n, &buf, &len, &off) != 0) break; continue; } --- 2575,2582 ---- continue; } n = strlen(s); ! format_log(es, "found #%c: %s", ch, s); ! if (format_replace(es, s, n, &buf, &len, &off) != 0) break; continue; } *************** *** 2538,2545 **** } buf[off] = '\0'; ! format_log(ft, "result is: %s", buf); ! ft->loop--; return (buf); } --- 2585,2592 ---- } buf[off] = '\0'; ! format_log(es, "result is: %s", buf); ! es->loop--; return (buf); } *************** *** 2548,2561 **** char * format_expand_time(struct format_tree *ft, const char *fmt) { ! return (format_expand1(ft, fmt, 1)); } /* Expand keys in a template. */ char * format_expand(struct format_tree *ft, const char *fmt) { ! return (format_expand1(ft, fmt, 0)); } /* Expand a single string. */ --- 2595,2618 ---- char * format_expand_time(struct format_tree *ft, const char *fmt) { ! struct format_expand_state es; ! ! memset(&es, 0, sizeof es); ! es.ft = ft; ! es.flags = FORMAT_EXPAND_TIME; ! return (format_expand1(&es, fmt)); } /* Expand keys in a template. */ char * format_expand(struct format_tree *ft, const char *fmt) { ! struct format_expand_state es; ! ! memset(&es, 0, sizeof es); ! es.ft = ft; ! es.flags = 0; ! return (format_expand1(&es, fmt)); } /* Expand a single string. */