=================================================================== RCS file: /cvs/mandoc/eqn.c,v retrieving revision 1.64 retrieving revision 1.67 diff -u -p -r1.64 -r1.67 --- mandoc/eqn.c 2017/06/21 18:04:34 1.64 +++ mandoc/eqn.c 2017/06/22 00:30:20 1.67 @@ -1,4 +1,4 @@ -/* $Id: eqn.c,v 1.64 2017/06/21 18:04:34 schwarze Exp $ */ +/* $Id: eqn.c,v 1.67 2017/06/22 00:30:20 schwarze Exp $ /* * Copyright (c) 2011, 2014 Kristaps Dzonsons * Copyright (c) 2014, 2015, 2017 Ingo Schwarze @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -83,6 +84,8 @@ enum eqn_tok { EQN_TOK_ABOVE, EQN_TOK__MAX, EQN_TOK_FUNC, + EQN_TOK_QUOTED, + EQN_TOK_SYM, EQN_TOK_EOF }; @@ -516,13 +519,21 @@ eqn_tok_parse(struct eqn_node *ep, char **p) if (quoted) { if (p != NULL) *p = mandoc_strndup(start, sz); - return EQN_TOK__MAX; + return EQN_TOK_QUOTED; } for (i = 0; i < EQN_TOK__MAX; i++) if (STRNEQ(start, sz, eqn_toks[i], strlen(eqn_toks[i]))) return i; + for (i = 0; i < EQNSYM__MAX; i++) { + if (STRNEQ(start, sz, + eqnsyms[i].str, strlen(eqnsyms[i].str))) { + mandoc_asprintf(p, "\\[%s]", eqnsyms[i].sym); + return EQN_TOK_SYM; + } + } + if (p != NULL) *p = mandoc_strndup(start, sz); @@ -710,10 +721,10 @@ static enum rofferr eqn_parse(struct eqn_node *ep, struct eqn_box *parent) { char sym[64]; - struct eqn_box *cur; - const char *start; + struct eqn_box *cur, *fontp, *nbox; + const char *cp, *cpn, *start; char *p; - size_t i, sz; + size_t sz; enum eqn_tok tok, subtok; enum eqn_post pos; int size; @@ -1075,8 +1086,10 @@ this_tok: * TODO: make sure we're not in an open subexpression. */ return ROFF_EQN; - case EQN_TOK_FUNC: case EQN_TOK__MAX: + case EQN_TOK_FUNC: + case EQN_TOK_QUOTED: + case EQN_TOK_SYM: assert(p != NULL); /* * If we already have something in the stack and we're @@ -1084,30 +1097,61 @@ this_tok: */ while (parent->args == parent->expectargs) parent = parent->parent; - if (tok == EQN_TOK_FUNC) { - for (cur = parent; cur != NULL; cur = cur->parent) - if (cur->font != EQNFONT_NONE) - break; - if (cur == NULL || cur->font != EQNFONT_ROMAN) { - parent = eqn_box_alloc(ep, parent); - parent->type = EQN_LISTONE; - parent->font = EQNFONT_ROMAN; - parent->expectargs = 1; - } + /* + * Wrap well-known function names in a roman box, + * unless they already are in roman context. + */ + for (fontp = parent; fontp != NULL; fontp = fontp->parent) + if (fontp->font != EQNFONT_NONE) + break; + if (tok == EQN_TOK_FUNC && + (fontp == NULL || fontp->font != EQNFONT_ROMAN)) { + parent = fontp = eqn_box_alloc(ep, parent); + parent->type = EQN_LISTONE; + parent->font = EQNFONT_ROMAN; + parent->expectargs = 1; } cur = eqn_box_alloc(ep, parent); cur->type = EQN_TEXT; - for (i = 0; i < EQNSYM__MAX; i++) - if (0 == strcmp(eqnsyms[i].str, p)) { - (void)snprintf(sym, sizeof(sym), - "\\[%s]", eqnsyms[i].sym); - cur->text = mandoc_strdup(sym); - free(p); + cur->text = p; + /* + * If not inside any explicit font context, + * quoted strings become italic, and every letter + * of a bare string gets its own italic box. + */ + do { + if (fontp != NULL || *p == '\0' || + tok == EQN_TOK_SYM) break; + if (tok == EQN_TOK_QUOTED) { + cur->font = EQNFONT_ITALIC; + break; } - - if (i == EQNSYM__MAX) - cur->text = p; + cp = p; + for (;;) { + if (isalpha((unsigned char)*cp)) + cur->font = EQNFONT_ITALIC; + cpn = cp + 1; + if (*cp == '\\') + mandoc_escape(&cpn, NULL, NULL); + if (*cpn == '\0') + break; + if (cur->font != EQNFONT_ITALIC && + isalpha((unsigned char)*cpn) == 0) { + cp = cpn; + continue; + } + nbox = eqn_box_alloc(ep, parent); + nbox->type = EQN_TEXT; + nbox->text = mandoc_strdup(cpn); + p = mandoc_strndup(cur->text, + cpn - cur->text); + free(cur->text); + cur->text = p; + cur = nbox; + cp = nbox->text; + } + } while (0); /* * Post-process list status. */