Index: libmandoc.h =================================================================== RCS file: /cvsroot/src/external/bsd/mdocml/dist/libmandoc.h,v retrieving revision 1.1.1.9 retrieving revision 1.3 diff -u -p -r1.1.1.9 -r1.3 --- libmandoc.h 30 Jan 2012 16:44:17 -0000 1.1.1.9 +++ libmandoc.h 22 Mar 2013 01:24:46 -0000 1.3 @@ -73,6 +73,8 @@ void roff_reset(struct roff *); enum rofferr roff_parseln(struct roff *, int, char **, size_t *, int, int *); void roff_endparse(struct roff *); +void roff_expand_nr(struct roff *, const char *, int *, size_t, + char **, int *, size_t *); int roff_regisset(const struct roff *, enum regs); unsigned int roff_regget(const struct roff *, enum regs); void roff_regunset(struct roff *, enum regs); Index: read.c =================================================================== RCS file: /cvsroot/src/external/bsd/mdocml/dist/read.c,v retrieving revision 1.1.1.4 diff -u -p -r1.1.1.4 read.c --- read.c 3 Apr 2013 14:46:53 -0000 1.1.1.4 +++ read.c 3 Apr 2013 15:20:11 -0000 @@ -344,15 +344,20 @@ mparse_buf_r(struct mparse *curp, struct continue; } - /* Trailing backslash = a plain char. */ + /* Expand registers inline */ + if ('\\' == blk.buf[i] && 'n' == blk.buf[i + 1]) { + roff_expand_nr(curp->roff, + blk.buf, &i, blk.sz, &ln.buf, &pos, &ln.sz); + continue; + } + /* Trailing backslash = a plain char. */ if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) { if (pos >= (int)ln.sz) resize_buf(&ln, 256); ln.buf[pos++] = blk.buf[i++]; continue; } - /* * Found escape and at least one other character. * When it's a newline character, skip it. Index: roff.c =================================================================== RCS file: /cvsroot/src/external/bsd/mdocml/dist/roff.c,v retrieving revision 1.1.1.9 retrieving revision 1.13 diff -u -p -r1.1.1.9 -r1.13 --- roff.c 30 Jan 2012 16:44:11 -0000 1.1.1.9 +++ roff.c 3 Apr 2013 01:05:16 -0000 1.13 @@ -21,8 +21,10 @@ #include #include +#include #include #include +#include #include "mandoc.h" #include "libroff.h" @@ -70,8 +72,8 @@ enum rofft { }; enum roffrule { - ROFFRULE_ALLOW, - ROFFRULE_DENY + ROFFRULE_DENY, + ROFFRULE_ALLOW }; /* @@ -117,6 +119,7 @@ struct roff { struct eqn_node *last_eqn; /* last equation parsed */ struct eqn_node *first_eqn; /* first equation parsed */ struct eqn_node *eqn; /* current equation being parsed */ + struct roff_nr *nr[64]; /* numbered register set */ }; struct roffnode { @@ -392,7 +395,8 @@ roff_reset(struct roff *r) roff_free1(r); - memset(&r->regs, 0, sizeof(struct reg) * REG__MAX); + memset(&r->regs, 0, sizeof(r->regs)); + memset(&r->nr, 0, sizeof(r->nr)); for (i = 0; i < PREDEFS_MAX; i++) roff_setstr(r, predefs[i].name, predefs[i].str, 0); @@ -574,7 +578,7 @@ roff_parsetext(char *p) /* Skip over escapes. */ p++; esc = mandoc_escape - ((const char **)&p, NULL, NULL); + ((const char **)/*XXX*/(void *)&p, NULL, NULL); if (ESCAPE_ERROR == esc) break; continue; @@ -621,20 +625,16 @@ roff_parseln(struct roff *r, int ln, cha * no matter our state. */ - if (r->last && ! ctl) { - t = r->last->tok; - assert(roffs[t].text); - e = (*roffs[t].text) - (r, t, bufp, szp, ln, pos, pos, offs); - assert(ROFF_IGN == e || ROFF_CONT == e); - if (ROFF_CONT != e) - return(e); - if (r->eqn) - return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); - if (r->tbl) - return(tbl_read(r->tbl, ln, *bufp, pos)); - return(roff_parsetext(*bufp + pos)); - } else if ( ! ctl) { + if (!ctl) { + if (r->last) { + t = r->last->tok; + assert(roffs[t].text); + e = (*roffs[t].text) + (r, t, bufp, szp, ln, pos, pos, offs); + assert(ROFF_IGN == e || ROFF_CONT == e); + if (ROFF_CONT != e) + return(e); + } if (r->eqn) return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); if (r->tbl) @@ -1059,10 +1059,61 @@ roff_cond_text(ROFF_ARGS) return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); } +static int +roff_getnum(const char *v, int *pos, int *res) +{ + int p, n; + + if ((n = (v[*pos] == '-')) != 0) + (*pos)++; + + p = *pos; + for (*res = 0; isdigit((unsigned char)v[p]); p++) + *res += 10 * *res + v[p] - '0'; + if (p == *pos) + return 0; + + if (n) + *res = -*res; + + *pos = p; + return 1; +} + +static int +roff_getop(const char *v, int *pos) +{ + int c; + switch (c = v[*pos]) { + case '=': + case '!': + case '>': + case '<': + (*pos)++; + if (v[*pos] == '=') { + (*pos)++; + return c; + } + switch (c) { + case '=': + return '='; + case '>': + return 'g'; + case '<': + return 'l'; + default: + return -1; + } + default: + return -1; + } +} + static enum roffrule roff_evalcond(const char *v, int *pos) { - + int not = 0; + int lh, rh, op; switch (v[*pos]) { case ('n'): (*pos)++; @@ -1074,13 +1125,45 @@ roff_evalcond(const char *v, int *pos) case ('t'): (*pos)++; return(ROFFRULE_DENY); + case ('!'): + not++; + (*pos)++; + break; default: break; } - - while (v[*pos] && ' ' != v[*pos]) - (*pos)++; - return(ROFFRULE_DENY); + if (!roff_getnum(v, pos, &lh)) + return ROFFRULE_DENY; + if ((op = roff_getop(v, pos)) == -1) + goto out; + if (!roff_getnum(v, pos, &rh)) + return ROFFRULE_DENY; + switch (op) { + case '>': + lh = lh >= rh; + break; + case '<': + lh = lh <= rh; + break; + case '=': + lh = lh == rh; + break; + case '!': + lh = lh != rh; + break; + case 'g': + lh = lh > rh; + break; + case 'l': + lh = lh < rh; + break; + default: + return ROFFRULE_DENY; + } +out: + if (not) + lh = !lh; + return lh ? ROFFRULE_ALLOW : ROFFRULE_DENY; } /* ARGSUSED */ @@ -1234,21 +1317,70 @@ roff_regunset(struct roff *r, enum regs r->regs[(int)reg].set = 0; } +struct roff_nr { + char *str; + uint32_t hash; + intmax_t val; + struct roff_nr *next; +}; + +static uint32_t +hash_str(const char *str) +{ + const uint8_t *s = (const uint8_t *)str; + uint8_t c; + uint32_t hv = 0; + while ((c = *s++) != '\0') + hv = hv * 33 + c; /* "perl": k=33, r=r+r/32 */ + return hv + (hv >> 5); +} + +static struct roff_nr * +hash_find(struct roff *r, const char *str, uint32_t *h) +{ + struct roff_nr *e; + *h = hash_str(str) % (sizeof(r->nr) / sizeof(r->nr[0])); + + for (e = r->nr[*h]; e; e = e->next) + if (e->hash == *h && strcmp(e->str, str) == 0) + return e; + return NULL; +} + +static struct roff_nr * +hash_insert(struct roff *r, const char *str, uint32_t h) +{ + struct roff_nr *e; + + e = mandoc_malloc(sizeof(*e)); + e->str = mandoc_strdup(str); + e->hash = h; + e->next = r->nr[h]; + r->nr[h] = e; + return e; +} + /* ARGSUSED */ static enum rofferr roff_nr(ROFF_ARGS) { const char *key; char *val; - int iv; + uint32_t hv; + struct roff_nr *h; val = *bufp + pos; key = roff_getname(r, &val, ln, pos); + if ((h = hash_find(r, key, &hv)) == NULL) + h = hash_insert(r, key, hv); + + h->val = mandoc_strntoi(val, strlen(val), 10); + if (0 == strcmp(key, "nS")) { r->regs[(int)REG_nS].set = 1; - if ((iv = mandoc_strntoi(val, strlen(val), 10)) >= 0) - r->regs[(int)REG_nS].u = (unsigned)iv; + if (h->val >= 0) + r->regs[(int)REG_nS].u = (unsigned)h->val; else r->regs[(int)REG_nS].u = 0u; } @@ -1256,6 +1388,50 @@ roff_nr(ROFF_ARGS) return(ROFF_IGN); } +void +roff_expand_nr(struct roff *r, const char *src, int *sp, size_t slen, + char **dst, int *dp, size_t *dlenp) +{ + uint32_t hv; + struct roff_nr *h; + int l, s, d; + char e, *key; + + s = *sp + 2; /* skip \\\n */ + d = *dp; + + if ('[' == src[s]) { /* XXX: Support builtins */ + s++; + e = ']'; + } else + e = '\0'; + + for (l = s; src[l] && l < (int)slen; l++) { + if (e) { + if (src[l] == e) + break; + } else { + if (!isalnum((unsigned char)src[l])) + break; + } + } + *sp = l; + l -= s; + key = mandoc_malloc(l + 1); + memcpy(key, src + s, l); + key[l] = '\0'; + + if ((h = hash_find(r, key, &hv)) == NULL) { + free(key); + return; + } + if (*dst == NULL || *dlenp - *dp < 256) + *dst = mandoc_realloc(*dst, *dlenp += 256); + + /* XXX: support .af */ + *dp += snprintf(*dst + *dp, *dlenp - *dp, "%jd", h->val); +} + /* ARGSUSED */ static enum rofferr roff_rm(ROFF_ARGS) Index: tbl_data.c =================================================================== RCS file: /cvsroot/src/external/bsd/mdocml/dist/tbl_data.c,v retrieving revision 1.1.1.2 retrieving revision 1.4 diff -u -p -r1.1.1.2 -r1.4 --- tbl_data.c 15 Apr 2011 13:45:36 -0000 1.1.1.2 +++ tbl_data.c 24 Nov 2012 22:29:09 -0000 1.4 @@ -29,13 +29,13 @@ #include "libmandoc.h" #include "libroff.h" -static int data(struct tbl_node *, struct tbl_span *, +static int getdata(struct tbl_node *, struct tbl_span *, int, const char *, int *); static struct tbl_span *newspan(struct tbl_node *, int, struct tbl_row *); static int -data(struct tbl_node *tbl, struct tbl_span *dp, +getdata(struct tbl_node *tbl, struct tbl_span *dp, int ln, const char *p, int *pos) { struct tbl_dat *dat; @@ -154,7 +154,7 @@ tbl_cdata(struct tbl_node *tbl, int ln, if (p[pos] == tbl->opts.tab) { tbl->part = TBL_PART_DATA; pos++; - return(data(tbl, tbl->last_span, ln, p, &pos)); + return(getdata(tbl, tbl->last_span, ln, p, &pos)); } else if ('\0' == p[pos]) { tbl->part = TBL_PART_DATA; return(1); @@ -269,7 +269,7 @@ tbl_data(struct tbl_node *tbl, int ln, c /* This returns 0 when TBL_PART_CDATA is entered. */ while ('\0' != p[pos]) - if ( ! data(tbl, dp, ln, p, &pos)) + if ( ! getdata(tbl, dp, ln, p, &pos)) return(0); return(1);