=================================================================== RCS file: /cvs/mandoc/eqn.c,v retrieving revision 1.65 retrieving revision 1.69 diff -u -p -r1.65 -r1.69 --- mandoc/eqn.c 2017/06/21 18:38:26 1.65 +++ mandoc/eqn.c 2017/06/23 21:04:57 1.69 @@ -1,4 +1,4 @@ -/* $Id: eqn.c,v 1.65 2017/06/21 18:38:26 schwarze Exp $ */ +/* $Id: eqn.c,v 1.69 2017/06/23 21:04:57 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,7 +519,7 @@ 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++) @@ -527,7 +530,7 @@ eqn_tok_parse(struct eqn_node *ep, char **p) if (STRNEQ(start, sz, eqnsyms[i].str, strlen(eqnsyms[i].str))) { mandoc_asprintf(p, "\\[%s]", eqnsyms[i].sym); - return EQN_TOK__MAX; + return EQN_TOK_SYM; } } @@ -570,6 +573,7 @@ eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par bp->parent = parent; bp->parent->args++; bp->expectargs = UINT_MAX; + bp->font = bp->parent->font; bp->size = ep->gsize; if (NULL != parent->first) { @@ -718,12 +722,13 @@ 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, *nbox; + const char *cp, *cpn, *start; char *p; size_t sz; enum eqn_tok tok, subtok; enum eqn_post pos; + enum { CCL_LET, CCL_DIG, CCL_PUN } ccl, ccln; int size; assert(parent != NULL); @@ -784,6 +789,7 @@ this_tok: parent = eqn_box_makebinary(ep, EQNPOS_NONE, parent); parent->type = EQN_LISTONE; parent->expectargs = 1; + parent->font = EQNFONT_ROMAN; switch (tok) { case EQN_TOK_DOTDOT: strlcpy(sym, "\\[ad]", sizeof(sym)); @@ -1083,8 +1089,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 @@ -1092,21 +1100,80 @@ 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; - } - } cur = eqn_box_alloc(ep, parent); cur->type = EQN_TEXT; cur->text = p; - + switch (tok) { + case EQN_TOK_FUNC: + cur->font = EQNFONT_ROMAN; + break; + case EQN_TOK_QUOTED: + if (cur->font == EQNFONT_NONE) + cur->font = EQNFONT_ITALIC; + break; + case EQN_TOK_SYM: + break; + default: + if (cur->font != EQNFONT_NONE || *p == '\0') + break; + cpn = p - 1; + ccln = CCL_LET; + for (;;) { + /* Advance to next character. */ + cp = cpn++; + ccl = ccln; + ccln = isalpha((unsigned char)*cpn) ? CCL_LET : + isdigit((unsigned char)*cpn) || + (*cpn == '.' && (ccl == CCL_DIG || + isdigit((unsigned char)cpn[1]))) ? + CCL_DIG : CCL_PUN; + /* No boundary before first character. */ + if (cp < p) + continue; + cur->font = ccl == CCL_LET ? + EQNFONT_ITALIC : EQNFONT_ROMAN; + if (*cp == '\\') + mandoc_escape(&cpn, NULL, NULL); + /* No boundary after last character. */ + if (*cpn == '\0') + break; + if (ccln == ccl) + continue; + /* Boundary found, split the text. */ + if (parent->args == parent->expectargs) { + /* Remove the text from the tree. */ + if (cur->prev == NULL) + parent->first = cur->next; + else + cur->prev->next = NULL; + parent->last = cur->prev; + parent->args--; + /* Set up a list instead. */ + nbox = eqn_box_alloc(ep, parent); + nbox->type = EQN_LIST; + /* Insert the word into the list. */ + nbox->first = nbox->last = cur; + cur->parent = nbox; + cur->prev = NULL; + parent = nbox; + } + /* Append a new text box. */ + nbox = eqn_box_alloc(ep, parent); + nbox->type = EQN_TEXT; + nbox->text = mandoc_strdup(cpn); + /* Truncate the old box. */ + p = mandoc_strndup(cur->text, + cpn - cur->text); + free(cur->text); + cur->text = p; + /* Setup to process the new box. */ + cur = nbox; + p = nbox->text; + cpn = p - 1; + ccln = CCL_LET; + } + break; + } /* * Post-process list status. */