=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.268 retrieving revision 1.271 diff -u -p -r1.268 -r1.271 --- mandoc/roff.c 2015/04/19 14:57:38 1.268 +++ mandoc/roff.c 2015/05/31 23:13:22 1.271 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.268 2015/04/19 14:57:38 schwarze Exp $ */ +/* $Id: roff.c,v 1.271 2015/05/31 23:13:22 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * Copyright (c) 2010-2015 Ingo Schwarze @@ -397,8 +397,7 @@ static enum rofferr roff_cond_text(ROFF_ARGS); static enum rofferr roff_cond_sub(ROFF_ARGS); static enum rofferr roff_ds(ROFF_ARGS); static enum rofferr roff_eqndelim(struct roff *, struct buf *, int); -static int roff_evalcond(struct roff *r, int, - const char *, int *); +static int roff_evalcond(struct roff *r, int, char *, int *); static int roff_evalnum(struct roff *, int, const char *, int *, int *, int); static int roff_evalpar(struct roff *, int, @@ -415,6 +414,8 @@ static int roff_getregn(const struct roff *, static int roff_getregro(const char *name); static const char *roff_getstrn(const struct roff *, const char *, size_t); +static int roff_hasregn(const struct roff *, + const char *, size_t); static enum rofferr roff_insec(ROFF_ARGS); static enum rofferr roff_it(ROFF_ARGS); static enum rofferr roff_line_ignore(ROFF_ARGS); @@ -1022,6 +1023,7 @@ roff_node_append(struct roff_man *man, struct roff_nod /* NOTREACHED */ } n->parent->nchild++; + n->parent->last = n; /* * Copy over the normalised-data pointer of our parent. Not @@ -1230,6 +1232,52 @@ roff_node_delete(struct roff_man *man, struct roff_nod roff_node_free(n); } +void +deroff(char **dest, const struct roff_node *n) +{ + char *cp; + size_t sz; + + if (n->type != ROFFT_TEXT) { + for (n = n->child; n != NULL; n = n->next) + deroff(dest, n); + return; + } + + /* Skip leading whitespace and escape sequences. */ + + cp = n->string; + while (*cp != '\0') { + if ('\\' == *cp) { + cp++; + mandoc_escape((const char **)&cp, NULL, NULL); + } else if (isspace((unsigned char)*cp)) + cp++; + else + break; + } + + /* Skip trailing whitespace. */ + + for (sz = strlen(cp); sz; sz--) + if ( ! isspace((unsigned char)cp[sz-1])) + break; + + /* Skip empty strings. */ + + if (sz == 0) + return; + + if (*dest == NULL) { + *dest = mandoc_strndup(cp, sz); + return; + } + + mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp); + free(*dest); + *dest = cp; +} + /* --- main functions of the roff parser ---------------------------------- */ /* @@ -2087,8 +2135,10 @@ out: * or string condition. */ static int -roff_evalcond(struct roff *r, int ln, const char *v, int *pos) +roff_evalcond(struct roff *r, int ln, char *v, int *pos) { + char *cp, *name; + size_t sz; int number, savepos, wanttrue; if ('!' == v[*pos]) { @@ -2111,13 +2161,16 @@ roff_evalcond(struct roff *r, int ln, const char *v, i /* FALLTHROUGH */ case 'e': /* FALLTHROUGH */ - case 'r': - /* FALLTHROUGH */ case 't': /* FALLTHROUGH */ case 'v': (*pos)++; return(!wanttrue); + case 'r': + cp = name = v + ++*pos; + sz = roff_getname(r, &cp, ln, *pos); + *pos = cp - v; + return((sz && roff_hasregn(r, name, sz)) == wanttrue); default: break; } @@ -2576,6 +2629,26 @@ roff_getregn(const struct roff *r, const char *name, s if (len == reg->key.sz && 0 == strncmp(name, reg->key.p, len)) return(reg->val); + + return(0); +} + +static int +roff_hasregn(const struct roff *r, const char *name, size_t len) +{ + struct roffreg *reg; + int val; + + if ('.' == name[0] && 2 == len) { + val = roff_getregro(name + 1); + if (-1 != val) + return(1); + } + + for (reg = r->regtab; reg; reg = reg->next) + if (len == reg->key.sz && + 0 == strncmp(name, reg->key.p, len)) + return(1); return(0); }