=================================================================== RCS file: /cvs/mandoc/eqn.c,v retrieving revision 1.20 retrieving revision 1.27 diff -u -p -r1.20 -r1.27 --- mandoc/eqn.c 2011/07/21 23:30:39 1.20 +++ mandoc/eqn.c 2011/07/22 13:40:15 1.27 @@ -1,4 +1,4 @@ -/* $Id: eqn.c,v 1.20 2011/07/21 23:30:39 kristaps Exp $ */ +/* $Id: eqn.c,v 1.27 2011/07/22 13:40:15 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * @@ -39,16 +39,65 @@ enum eqn_rest { EQN_EOF }; +enum eqn_symt { + EQNSYM_alpha, + EQNSYM_beta, + EQNSYM_chi, + EQNSYM_delta, + EQNSYM_epsilon, + EQNSYM_eta, + EQNSYM_gamma, + EQNSYM_iota, + EQNSYM_kappa, + EQNSYM_lambda, + EQNSYM_mu, + EQNSYM_nu, + EQNSYM_omega, + EQNSYM_omicron, + EQNSYM_phi, + EQNSYM_pi, + EQNSYM_ps, + EQNSYM_rho, + EQNSYM_sigma, + EQNSYM_tau, + EQNSYM_theta, + EQNSYM_upsilon, + EQNSYM_xi, + EQNSYM_zeta, + EQNSYM_DELTA, + EQNSYM_GAMMA, + EQNSYM_LAMBDA, + EQNSYM_OMEGA, + EQNSYM_PHI, + EQNSYM_PI, + EQNSYM_PSI, + EQNSYM_SIGMA, + EQNSYM_THETA, + EQNSYM_UPSILON, + EQNSYM_XI, + EQNSYM__MAX +}; + struct eqnstr { const char *name; size_t sz; }; +#define STRNEQ(p1, sz1, p2, sz2) \ + ((sz1) == (sz2) && 0 == strncmp((p1), (p2), (sz1))) +#define EQNSTREQ(x, p, sz) \ + STRNEQ((x)->name, (x)->sz, (p), (sz)) + struct eqnpart { struct eqnstr str; int (*fp)(struct eqn_node *); }; +struct eqnsym { + struct eqnstr str; + char sym; +}; + enum eqnpartt { EQN_DEFINE = 0, EQN_SET, @@ -56,6 +105,7 @@ enum eqnpartt { EQN__MAX }; +static enum eqn_rest eqn_box(struct eqn_node *, struct eqn_box *); static struct eqn_box *eqn_box_alloc(struct eqn_box *); static void eqn_box_free(struct eqn_box *); static struct eqn_def *eqn_def_find(struct eqn_node *, @@ -63,13 +113,13 @@ static struct eqn_def *eqn_def_find(struct eqn_node *, static int eqn_do_define(struct eqn_node *); static int eqn_do_set(struct eqn_node *); static int eqn_do_undef(struct eqn_node *); +static enum eqn_rest eqn_eqn(struct eqn_node *, struct eqn_box *); +static enum eqn_rest eqn_list(struct eqn_node *, struct eqn_box *); static const char *eqn_nexttok(struct eqn_node *, size_t *); static const char *eqn_nextrawtok(struct eqn_node *, size_t *); static const char *eqn_next(struct eqn_node *, char, size_t *, int); static void eqn_rewind(struct eqn_node *); -static enum eqn_rest eqn_eqn(struct eqn_node *, struct eqn_box *); -static enum eqn_rest eqn_box(struct eqn_node *, struct eqn_box *); static const struct eqnpart eqnparts[EQN__MAX] = { { { "define", 6 }, eqn_do_define }, /* EQN_DEFINE */ @@ -112,6 +162,44 @@ static const struct eqnstr eqnpiles[EQNPILE__MAX] = { { "lpile", 5 }, /* EQNPILE_LPILE */ }; +static const struct eqnsym eqnsyms[EQNSYM__MAX] = { + { { "alpha", 5 }, 'a' }, /* EQNSYM_alpha */ + { { "beta", 4 }, 'b' }, /* EQNSYM_beta */ + { { "chi", 3 }, 'x' }, /* EQNSYM_chi */ + { { "delta", 5 }, 'd' }, /* EQNSYM_delta */ + { { "epsilon", 7 }, 'e' }, /* EQNSYM_epsilon */ + { { "eta", 3 }, 'y' }, /* EQNSYM_eta */ + { { "gamma", 5 }, 'g' }, /* EQNSYM_gamma */ + { { "iota", 4 }, 'i' }, /* EQNSYM_iota */ + { { "kappa", 5 }, 'k' }, /* EQNSYM_kappa */ + { { "lambda", 6 }, 'l' }, /* EQNSYM_lambda */ + { { "mu", 2 }, 'm' }, /* EQNSYM_mu */ + { { "nu", 2 }, 'n' }, /* EQNSYM_nu */ + { { "omega", 5 }, 'w' }, /* EQNSYM_omega */ + { { "omicron", 7 }, 'o' }, /* EQNSYM_omicron */ + { { "phi", 3 }, 'f' }, /* EQNSYM_phi */ + { { "pi", 2 }, 'p' }, /* EQNSYM_pi */ + { { "psi", 2 }, 'q' }, /* EQNSYM_psi */ + { { "rho", 3 }, 'r' }, /* EQNSYM_rho */ + { { "sigma", 5 }, 's' }, /* EQNSYM_sigma */ + { { "tau", 3 }, 't' }, /* EQNSYM_tau */ + { { "theta", 5 }, 'h' }, /* EQNSYM_theta */ + { { "upsilon", 7 }, 'u' }, /* EQNSYM_upsilon */ + { { "xi", 2 }, 'c' }, /* EQNSYM_xi */ + { { "zeta", 4 }, 'z' }, /* EQNSYM_zeta */ + { { "DELTA", 5 }, 'D' }, /* EQNSYM_DELTA */ + { { "GAMMA", 5 }, 'G' }, /* EQNSYM_GAMMA */ + { { "LAMBDA", 6 }, 'L' }, /* EQNSYM_LAMBDA */ + { { "OMEGA", 5 }, 'W' }, /* EQNSYM_OMEGA */ + { { "PHI", 3 }, 'F' }, /* EQNSYM_PHI */ + { { "PI", 2 }, 'P' }, /* EQNSYM_PI */ + { { "PSI", 3 }, 'Q' }, /* EQNSYM_PSI */ + { { "SIGMA", 5 }, 'S' }, /* EQNSYM_SIGMA */ + { { "THETA", 5 }, 'H' }, /* EQNSYM_THETA */ + { { "UPSILON", 7 }, 'U' }, /* EQNSYM_UPSILON */ + { { "XI", 2 }, 'C' }, /* EQNSYM_XI */ +}; + /* ARGSUSED */ enum rofferr eqn_read(struct eqn_node **epp, int ln, @@ -204,11 +292,57 @@ eqn_eqn(struct eqn_node *ep, struct eqn_box *last) } static enum eqn_rest +eqn_list(struct eqn_node *ep, struct eqn_box *last) +{ + struct eqn_box *bp; + const char *start; + size_t sz; + enum eqn_rest c; + + bp = eqn_box_alloc(last); + bp->type = EQN_LIST; + + if (NULL == (start = eqn_nexttok(ep, &sz))) { + EQN_MSG(MANDOCERR_EQNEOF, ep); + return(EQN_ERR); + } + if ( ! STRNEQ(start, sz, "{", 1)) { + EQN_MSG(MANDOCERR_EQNSYNT, ep); + return(EQN_ERR); + } + + while (EQN_DESCOPE == (c = eqn_eqn(ep, bp))) { + eqn_rewind(ep); + start = eqn_nexttok(ep, &sz); + assert(start); + if ( ! STRNEQ(start, sz, "above", 5)) + break; + bp->last->above = 1; + } + + if (EQN_DESCOPE != c) { + if (EQN_ERR != c) + EQN_MSG(MANDOCERR_EQNSCOPE, ep); + return(EQN_ERR); + } + + eqn_rewind(ep); + start = eqn_nexttok(ep, &sz); + assert(start); + if (STRNEQ(start, sz, "}", 1)) + return(EQN_OK); + + EQN_MSG(MANDOCERR_EQNBADSCOPE, ep); + return(EQN_ERR); +} + +static enum eqn_rest eqn_box(struct eqn_node *ep, struct eqn_box *last) { size_t sz; const char *start; char *left; + char sym[5]; enum eqn_rest c; int i, size; struct eqn_box *bp; @@ -216,22 +350,20 @@ eqn_box(struct eqn_node *ep, struct eqn_box *last) if (NULL == (start = eqn_nexttok(ep, &sz))) return(EQN_EOF); - if (1 == sz && 0 == strncmp("}", start, 1)) + if (STRNEQ(start, sz, "}", 1)) return(EQN_DESCOPE); - else if (5 == sz && 0 == strncmp("right", start, 5)) + else if (STRNEQ(start, sz, "right", 5)) return(EQN_DESCOPE); - else if (5 == sz && 0 == strncmp("above", start, 5)) + else if (STRNEQ(start, sz, "above", 5)) return(EQN_DESCOPE); for (i = 0; i < (int)EQN__MAX; i++) { - if (eqnparts[i].str.sz != sz) + if ( ! EQNSTREQ(&eqnparts[i].str, start, sz)) continue; - if (strncmp(eqnparts[i].str.name, start, sz)) - continue; return((*eqnparts[i].fp)(ep) ? EQN_OK : EQN_ERR); } - if (1 == sz && 0 == strncmp("{", start, 1)) { + if (STRNEQ(start, sz, "{", 1)) { if (EQN_DESCOPE != (c = eqn_eqn(ep, last))) { if (EQN_ERR != c) EQN_MSG(MANDOCERR_EQNSCOPE, ep); @@ -240,70 +372,38 @@ eqn_box(struct eqn_node *ep, struct eqn_box *last) eqn_rewind(ep); start = eqn_nexttok(ep, &sz); assert(start); - if (1 == sz && 0 == strncmp("}", start, 1)) + if (STRNEQ(start, sz, "}", 1)) return(EQN_OK); EQN_MSG(MANDOCERR_EQNBADSCOPE, ep); return(EQN_ERR); } for (i = 0; i < (int)EQNPILE__MAX; i++) { - if (eqnpiles[i].sz != sz) + if ( ! EQNSTREQ(&eqnpiles[i], start, sz)) continue; - if (strncmp(eqnpiles[i].name, start, sz)) - continue; - if (NULL == (start = eqn_nexttok(ep, &sz))) { - EQN_MSG(MANDOCERR_EQNEOF, ep); - return(EQN_ERR); - } - if (1 != sz || strncmp("{", start, 1)) { - EQN_MSG(MANDOCERR_EQNSYNT, ep); - return(EQN_ERR); - } - if (EQN_DESCOPE != (c = eqn_eqn(ep, last))) { - if (EQN_ERR != c) - EQN_MSG(MANDOCERR_EQNSCOPE, ep); - return(EQN_ERR); - } - assert(last->last); - last->last->pile = (enum eqn_pilet)i; - eqn_rewind(ep); - start = eqn_nexttok(ep, &sz); - assert(start); - if (1 == sz && 0 == strncmp("}", start, 1)) - return(EQN_OK); - if (5 != sz || strncmp("above", start, 5)) { - EQN_MSG(MANDOCERR_EQNSYNT, ep); - return(EQN_ERR); - } - last->last->above = 1; - if (EQN_DESCOPE != (c = eqn_eqn(ep, last))) { - if (EQN_ERR != c) - EQN_MSG(MANDOCERR_EQNSCOPE, ep); - return(EQN_ERR); - } - eqn_rewind(ep); - start = eqn_nexttok(ep, &sz); - assert(start); - if (1 == sz && 0 == strncmp("}", start, 1)) - return(EQN_OK); - EQN_MSG(MANDOCERR_EQNBADSCOPE, ep); - return(EQN_ERR); + if (EQN_OK == (c = eqn_list(ep, last))) + last->last->pile = (enum eqn_pilet)i; + return(c); } - if (4 == sz && 0 == strncmp("left", start, 4)) { + if (STRNEQ(start, sz, "left", 4)) { if (NULL == (start = eqn_nexttok(ep, &sz))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } left = mandoc_strndup(start, sz); - if (EQN_DESCOPE != (c = eqn_eqn(ep, last))) + c = eqn_eqn(ep, last); + if (last->last) + last->last->left = left; + else + free(left); + if (EQN_DESCOPE != c) return(c); assert(last->last); - last->last->left = left; eqn_rewind(ep); start = eqn_nexttok(ep, &sz); assert(start); - if (5 != sz || strncmp("right", start, 5)) + if ( ! STRNEQ(start, sz, "right", 5)) return(EQN_DESCOPE); if (NULL == (start = eqn_nexttok(ep, &sz))) { EQN_MSG(MANDOCERR_EQNEOF, ep); @@ -314,10 +414,8 @@ eqn_box(struct eqn_node *ep, struct eqn_box *last) } for (i = 0; i < (int)EQNPOS__MAX; i++) { - if (eqnposs[i].sz != sz) + if ( ! EQNSTREQ(&eqnposs[i], start, sz)) continue; - if (strncmp(eqnposs[i].name, start, sz)) - continue; if (NULL == last->last) { EQN_MSG(MANDOCERR_EQNSYNT, ep); return(EQN_ERR); @@ -331,10 +429,8 @@ eqn_box(struct eqn_node *ep, struct eqn_box *last) } for (i = 0; i < (int)EQNMARK__MAX; i++) { - if (eqnmarks[i].sz != sz) + if ( ! EQNSTREQ(&eqnmarks[i], start, sz)) continue; - if (strncmp(eqnmarks[i].name, start, sz)) - continue; if (NULL == last->last) { EQN_MSG(MANDOCERR_EQNSYNT, ep); return(EQN_ERR); @@ -348,10 +444,8 @@ eqn_box(struct eqn_node *ep, struct eqn_box *last) } for (i = 0; i < (int)EQNFONT__MAX; i++) { - if (eqnfonts[i].sz != sz) + if ( ! EQNSTREQ(&eqnfonts[i], start, sz)) continue; - if (strncmp(eqnfonts[i].name, start, sz)) - continue; if (EQN_EOF == (c = eqn_box(ep, last))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); @@ -360,7 +454,7 @@ eqn_box(struct eqn_node *ep, struct eqn_box *last) return(c); } - if (4 == sz && 0 == strncmp("size", start, 4)) { + if (STRNEQ(start, sz, "size", 4)) { if (NULL == (start = eqn_nexttok(ep, &sz))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); @@ -376,6 +470,17 @@ eqn_box(struct eqn_node *ep, struct eqn_box *last) bp = eqn_box_alloc(last); bp->type = EQN_TEXT; + for (i = 0; i < (int)EQNSYM__MAX; i++) + if (EQNSTREQ(&eqnsyms[i].str, start, sz)) { + sym[0] = '\\'; + sym[1] = '('; + sym[2] = '*'; + sym[3] = eqnsyms[i].sym; + sym[4] = '\0'; + bp->text = mandoc_strdup(sym); + return(EQN_OK); + } + bp->text = mandoc_strndup(start, sz); return(EQN_OK); } @@ -456,11 +561,11 @@ eqn_next(struct eqn_node *ep, char quote, size_t *sz, { char *start, *next; int q, diff, lim; - size_t ssz; + size_t ssz, dummy; struct eqn_def *def; if (NULL == sz) - sz = &ssz; + sz = &dummy; lim = 0; ep->rew = ep->cur; @@ -485,14 +590,26 @@ again: } start = &ep->data[(int)ep->cur]; - next = q ? strchr(start, quote) : strchr(start, ' '); + if ( ! q) { + if ('{' == *start || '}' == *start) + ssz = 1; + else + ssz = strcspn(start + 1, " ~\"{}\t") + 1; + next = start + (int)ssz; + if ('\0' == *next) + next = NULL; + } else + next = strchr(start, quote); + if (NULL != next) { *sz = (size_t)(next - start); ep->cur += *sz; if (q) ep->cur++; - while (' ' == ep->data[(int)ep->cur]) + while (' ' == ep->data[(int)ep->cur] || + '\t' == ep->data[(int)ep->cur] || + '~' == ep->data[(int)ep->cur]) ep->cur++; } else { if (q) @@ -619,8 +736,8 @@ eqn_def_find(struct eqn_node *ep, const char *key, siz int i; for (i = 0; i < (int)ep->defsz; i++) - if (ep->defs[i].keysz && ep->defs[i].keysz == sz && - 0 == strncmp(ep->defs[i].key, key, sz)) + if (ep->defs[i].keysz && STRNEQ(ep->defs[i].key, + ep->defs[i].keysz, key, sz)) return(&ep->defs[i]); return(NULL);