diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | libroff.h | 31 | ||||
-rw-r--r-- | roff.c | 122 | ||||
-rw-r--r-- | roff.h | 1 | ||||
-rw-r--r-- | tbl.c | 94 |
5 files changed, 195 insertions, 61 deletions
@@ -31,11 +31,11 @@ CFLAGS += -g $(WFLAGS) $(VFLAGS) -DHAVE_CONFIG_H LINTFLAGS += $(VFLAGS) -ROFFLNS = roff.ln +ROFFLNS = roff.ln tbl.ln -ROFFSRCS = roff.c +ROFFSRCS = roff.c tbl.c -ROFFOBJS = roff.o +ROFFOBJS = roff.o tbl.o MANDOCLNS = mandoc.ln @@ -94,7 +94,7 @@ DATAS = arch.in att.in lib.in msec.in st.in \ HEADS = mdoc.h libmdoc.h man.h libman.h term.h \ libmandoc.h html.h chars.h out.h main.h roff.h \ - mandoc.h + mandoc.h libroff.h GSGMLS = mandoc.1.sgml mdoc.3.sgml mdoc.7.sgml \ mandoc_char.7.sgml man.7.sgml man.3.sgml roff.7.sgml \ diff --git a/libroff.h b/libroff.h new file mode 100644 index 00000000..b9a153d2 --- /dev/null +++ b/libroff.h @@ -0,0 +1,31 @@ +/* $Id$ */ +/* + * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef LIBROFF_H +#define LIBROFF_H + +__BEGIN_DECLS + +struct tbl; + +struct tbl *tbl_alloc(void); +void tbl_free(struct tbl *); +void tbl_reset(struct tbl *); +enum rofferr tbl_read(struct tbl *, int, const char *, int); + +__END_DECLS + +#endif /*LIBROFF_H*/ @@ -29,6 +29,7 @@ #include "mandoc.h" #include "roff.h" +#include "libroff.h" #include "libmandoc.h" #define RSTACK_MAX 128 @@ -36,14 +37,6 @@ #define ROFF_CTL(c) \ ('.' == (c) || '\'' == (c)) -#if 1 -#define ROFF_DEBUG(fmt, args...) \ - do { /* Nothing. */ } while (/*CONSTCOND*/ 0) -#else -#define ROFF_DEBUG(fmt, args...) \ - do { fprintf(stderr, fmt , ##args); } while (/*CONSTCOND*/ 0) -#endif - enum rofft { ROFF_ad, ROFF_am, @@ -64,6 +57,8 @@ enum rofft { ROFF_rm, ROFF_so, ROFF_tr, + ROFF_TS, + ROFF_TE, ROFF_cblock, ROFF_ccond, /* FIXME: remove this. */ ROFF_USERDEF, @@ -75,7 +70,6 @@ enum roffrule { ROFFRULE_DENY }; - struct roffstr { char *name; /* key of symbol */ char *string; /* current value */ @@ -91,6 +85,7 @@ struct roff { struct regset *regs; /* read/writable registers */ struct roffstr *first_string; /* user-defined strings & macros */ const char *current_string; /* value of last called user macro */ + struct tbl *tbl; }; struct roffnode { @@ -146,6 +141,8 @@ static int roff_res(struct roff *, static void roff_setstr(struct roff *, const char *, const char *, int); static enum rofferr roff_so(ROFF_ARGS); +static enum rofferr roff_TE(ROFF_ARGS); +static enum rofferr roff_TS(ROFF_ARGS); static enum rofferr roff_userdef(ROFF_ARGS); /* See roff_hash_find() */ @@ -176,6 +173,8 @@ static struct roffmac roffs[ROFF_MAX] = { { "rm", roff_line_error, NULL, NULL, 0, NULL }, { "so", roff_so, NULL, NULL, 0, NULL }, { "tr", roff_line_ignore, NULL, NULL, 0, NULL }, + { "TS", roff_TS, NULL, NULL, 0, NULL }, + { "TE", roff_TE, NULL, NULL, 0, NULL }, { ".", roff_cblock, NULL, NULL, 0, NULL }, { "\\}", roff_ccond, NULL, NULL, 0, NULL }, { NULL, roff_userdef, NULL, NULL, 0, NULL }, @@ -264,7 +263,6 @@ roffnode_pop(struct roff *r) if (r->rstackpos > -1) r->rstackpos--; - ROFF_DEBUG("roff: popping scope\n"); r->last = r->last->parent; free(p->name); free(p->end); @@ -299,8 +297,14 @@ static void roff_free1(struct roff *r) { + if (r->tbl) { + tbl_free(r->tbl); + r->tbl = NULL; + } + while (r->last) roffnode_pop(r); + roff_freestr(r); } @@ -417,8 +421,6 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int pos) /* Replace the escape sequence by the string. */ - ROFF_DEBUG("roff: splicing reserved: [%.*s]\n", i, st); - nsz = *szp + strlen(res) + 1; n = mandoc_malloc(nsz); @@ -442,6 +444,7 @@ roff_parseln(struct roff *r, int ln, char **bufp, size_t *szp, int pos, int *offs) { enum rofft t; + enum rofferr e; int ppos; /* @@ -461,13 +464,17 @@ roff_parseln(struct roff *r, int ln, char **bufp, if (r->last && ! ROFF_CTL((*bufp)[pos])) { t = r->last->tok; assert(roffs[t].text); - ROFF_DEBUG("roff: intercept scoped text: %s, [%s]\n", - roffs[t].name, &(*bufp)[pos]); - return((*roffs[t].text) - (r, t, bufp, szp, - ln, pos, pos, offs)); - } else if ( ! ROFF_CTL((*bufp)[pos])) + e = (*roffs[t].text) + (r, t, bufp, szp, ln, pos, pos, offs); + assert(ROFF_IGN == e || ROFF_CONT == e); + if (ROFF_CONT == e && r->tbl) + return(tbl_read(r->tbl, ln, *bufp, *offs)); + return(e); + } else if ( ! ROFF_CTL((*bufp)[pos])) { + if (r->tbl) + return(tbl_read(r->tbl, ln, *bufp, *offs)); return(ROFF_CONT); + } /* * If a scope is open, go to the child handler for that macro, @@ -477,8 +484,6 @@ roff_parseln(struct roff *r, int ln, char **bufp, if (r->last) { t = r->last->tok; assert(roffs[t].sub); - ROFF_DEBUG("roff: intercept scoped context: %s, [%s]\n", - roffs[t].name, &(*bufp)[pos]); return((*roffs[t].sub) (r, t, bufp, szp, ln, pos, pos, offs)); @@ -494,10 +499,6 @@ roff_parseln(struct roff *r, int ln, char **bufp, if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) return(ROFF_CONT); - ROFF_DEBUG("roff: intercept new-scope: [%s], [%s]\n", - ROFF_USERDEF == t ? r->current_string : roffs[t].name, - &(*bufp)[pos]); - assert(roffs[t].proc); return((*roffs[t].proc) (r, t, bufp, szp, @@ -509,10 +510,10 @@ int roff_endparse(struct roff *r) { - if (NULL == r->last) - return(1); - return((*r->msg)(MANDOCERR_SCOPEEXIT, r->data, r->last->line, - r->last->col, NULL)); + if (r->last || r->tbl) + (*r->msg)(MANDOCERR_SCOPEEXIT, r->data, + r->last->line, r->last->col, NULL); + return(1); } @@ -581,8 +582,7 @@ roff_cblock(ROFF_ARGS) */ if (NULL == r->last) { - if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL)) - return(ROFF_ERR); + (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); return(ROFF_IGN); } @@ -601,14 +601,12 @@ roff_cblock(ROFF_ARGS) case (ROFF_ig): break; default: - if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL)) - return(ROFF_ERR); + (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); return(ROFF_IGN); } if ((*bufp)[pos]) - if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL)) - return(ROFF_ERR); + (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL); roffnode_pop(r); roffnode_cleanscope(r); @@ -635,8 +633,7 @@ roff_ccond(ROFF_ARGS) { if (NULL == r->last) { - if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL)) - return(ROFF_ERR); + (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); return(ROFF_IGN); } @@ -648,20 +645,17 @@ roff_ccond(ROFF_ARGS) case (ROFF_if): break; default: - if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL)) - return(ROFF_ERR); + (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); return(ROFF_IGN); } if (r->last->endspan > -1) { - if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL)) - return(ROFF_ERR); + (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); return(ROFF_IGN); } if ((*bufp)[pos]) - if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL)) - return(ROFF_ERR); + (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL); roffnode_pop(r); roffnode_cleanscope(r); @@ -986,9 +980,6 @@ roff_cond(ROFF_ARGS) r->last->rule = rule; - ROFF_DEBUG("roff: cond: %s -> %s\n", roffs[tok].name, - ROFFRULE_ALLOW == rule ? "allow" : "deny"); - if (ROFF_ie == tok) { /* * An if-else will put the NEGATION of the current @@ -1003,11 +994,8 @@ roff_cond(ROFF_ARGS) /* If the parent has false as its rule, then so do we. */ - if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule) { + if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule) r->last->rule = ROFFRULE_DENY; - ROFF_DEBUG("roff: cond override: %s -> deny\n", - roffs[tok].name); - } /* * Determine scope. If we're invoked with "\{" trailing the @@ -1020,11 +1008,7 @@ roff_cond(ROFF_ARGS) if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) { r->last->endspan = -1; pos += 2; - ROFF_DEBUG("roff: cond-scope: %s, multi-line\n", - roffs[tok].name); - } else - ROFF_DEBUG("roff: cond-scope: %s, one-line\n", - roffs[tok].name); + } /* * If there are no arguments on the line, the next-line scope is @@ -1117,11 +1101,35 @@ roff_nr(ROFF_ARGS) rg[(int)REG_nS].set = 1; if ( ! roff_parse_nat(val, &rg[(int)REG_nS].v.u)) rg[(int)REG_nS].v.u = 0; + } + + return(ROFF_IGN); +} + +/* ARGSUSED */ +static enum rofferr +roff_TE(ROFF_ARGS) +{ + + if (NULL == r->tbl) + (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); + else + tbl_free(r->tbl); + + r->tbl = NULL; + return(ROFF_IGN); +} + +/* ARGSUSED */ +static enum rofferr +roff_TS(ROFF_ARGS) +{ - ROFF_DEBUG("roff: register nS: %u\n", - rg[(int)REG_nS].v.u); + if (r->tbl) { + (*r->msg)(MANDOCERR_SCOPEBROKEN, r->data, ln, ppos, NULL); + tbl_reset(r->tbl); } else - ROFF_DEBUG("roff: ignoring register: %s\n", key); + r->tbl = tbl_alloc(); return(ROFF_IGN); } @@ -24,6 +24,7 @@ enum rofferr { ROFF_REPARSE, /* re-run main parser on the result */ ROFF_SO, /* include another file */ ROFF_IGN, /* ignore current line */ + ROFF_TBL, /* a table row was successfully parsed */ ROFF_ERR /* badness: puke and stop */ }; @@ -0,0 +1,94 @@ +/* $Id$ */ +/* + * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@kth.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "mandoc.h" +#include "roff.h" +#include "libmandoc.h" +#include "libroff.h" + +enum tbl_part { + TBL_PART_OPTS, /* in options (first line) */ + TBL_PART_LAYOUT, /* describing layout */ + TBL_PART_DATA /* creating data rows */ +}; + + +struct tbl { + enum tbl_part part; +}; + +static void tbl_init(struct tbl *); +static void tbl_clear(struct tbl *); + +static void +tbl_clear(struct tbl *tbl) +{ + +} + +static void +tbl_init(struct tbl *tbl) +{ + + tbl->part = TBL_PART_OPTS; +} + +enum rofferr +tbl_read(struct tbl *tbl, int ln, const char *p, int offs) +{ + int len; + const char *cp; + + cp = &p[offs]; + len = (int)strlen(cp); + + if (len && TBL_PART_OPTS == tbl->part) + if (';' != cp[len - 1]) + tbl->part = TBL_PART_LAYOUT; + + return(1); +} + +struct tbl * +tbl_alloc(void) +{ + struct tbl *p; + + p = mandoc_malloc(sizeof(struct tbl)); + tbl_init(p); + return(p); +} + +void +tbl_free(struct tbl *p) +{ + + tbl_clear(p); + free(p); +} + +void +tbl_reset(struct tbl *tbl) +{ + + tbl_clear(tbl); + tbl_init(tbl); +} |