diff options
-rw-r--r-- | usr.bin/mandoc/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/html.h | 20 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc.h | 3 | ||||
-rw-r--r-- | usr.bin/mandoc/out.c | 208 | ||||
-rw-r--r-- | usr.bin/mandoc/out.h | 43 | ||||
-rw-r--r-- | usr.bin/mandoc/tbl_data.c | 31 | ||||
-rw-r--r-- | usr.bin/mandoc/tbl_html.c | 105 | ||||
-rw-r--r-- | usr.bin/mandoc/tbl_layout.c | 41 | ||||
-rw-r--r-- | usr.bin/mandoc/tbl_opts.c | 14 | ||||
-rw-r--r-- | usr.bin/mandoc/tbl_term.c | 365 | ||||
-rw-r--r-- | usr.bin/mandoc/term.h | 4 |
11 files changed, 502 insertions, 336 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile index 0df572bdefe..872b55dabb5 100644 --- a/usr.bin/mandoc/Makefile +++ b/usr.bin/mandoc/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.51 2011/01/04 22:28:17 schwarze Exp $ +# $OpenBSD: Makefile,v 1.52 2011/01/09 14:30:48 schwarze Exp $ .include <bsd.own.mk> -VERSION=1.10.8 +VERSION=1.10.9 CFLAGS+=-DVERSION=\"${VERSION}\" CFLAGS+=-W -Wall -Wstrict-prototypes diff --git a/usr.bin/mandoc/html.h b/usr.bin/mandoc/html.h index 8ae7bd7db92..0248c8b4171 100644 --- a/usr.bin/mandoc/html.h +++ b/usr.bin/mandoc/html.h @@ -1,6 +1,6 @@ -/* $Id: html.h,v 1.12 2011/01/04 22:28:17 schwarze Exp $ */ +/* $Id: html.h,v 1.13 2011/01/09 14:30:48 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2008, 2009, 2010, 2011 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 @@ -115,13 +115,13 @@ struct html { #define HTML_KEEP (1 << 2) #define HTML_PREKEEP (1 << 3) #define HTML_NONOSPACE (1 << 4) - struct tagq tags; - void *symtab; - char *base; - char *base_man; - char *base_includes; - char *style; - char buf[BUFSIZ]; + struct tagq tags; /* stack of open tags */ + struct rofftbl tbl; /* current table */ + void *symtab; /* character-escapes */ + char *base_man; /* base for manpage href */ + char *base_includes; /* base for include href */ + char *style; /* style-sheet URI */ + char buf[BUFSIZ]; /* see bufcat and friends */ size_t buflen; struct tag *metaf; /* current open font scope */ enum htmlfont metal; /* last used font */ @@ -129,8 +129,6 @@ struct html { enum htmltype type; }; -struct roffsu; - void print_gen_decls(struct html *); void print_gen_head(struct html *); struct tag *print_otag(struct html *, enum htmltag, diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h index 366614ef138..fc317069d5e 100644 --- a/usr.bin/mandoc/mandoc.h +++ b/usr.bin/mandoc/mandoc.h @@ -1,4 +1,4 @@ -/* $Id: mandoc.h,v 1.27 2011/01/04 22:28:17 schwarze Exp $ */ +/* $Id: mandoc.h,v 1.28 2011/01/09 14:30:48 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -152,7 +152,6 @@ struct tbl { char tab; /* cell-separator */ char decimal; /* decimal point */ int linesize; - char delims[2]; /* FIXME: deprecate */ int opts; #define TBL_OPT_CENTRE (1 << 0) #define TBL_OPT_EXPAND (1 << 1) diff --git a/usr.bin/mandoc/out.c b/usr.bin/mandoc/out.c index 6e1f812fa29..026a481aa8f 100644 --- a/usr.bin/mandoc/out.c +++ b/usr.bin/mandoc/out.c @@ -1,6 +1,6 @@ -/* $Id: out.c,v 1.8 2010/09/13 22:04:01 schwarze Exp $ */ +/* $Id: out.c,v 1.9 2011/01/09 14:30:48 schwarze Exp $ */ /* - * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2009, 2010, 2011 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 @@ -23,8 +23,16 @@ #include <string.h> #include <time.h> +#include "mandoc.h" #include "out.h" +static void tblcalc_data(struct rofftbl *, struct roffcol *, + const struct tbl *, const struct tbl_dat *); +static void tblcalc_literal(struct rofftbl *, struct roffcol *, + const struct tbl_dat *); +static void tblcalc_number(struct rofftbl *, struct roffcol *, + const struct tbl *, const struct tbl_dat *); + /* * Convert a `scaling unit' to a consistent form, or fail. Scaling * units are documented in groff.7, mdoc.7, man.7. @@ -354,3 +362,199 @@ a2roffdeco(enum roffdeco *d, const char **word, size_t *sz) return(i); } + +/* + * Calculate the abstract widths and decimal positions of columns in a + * table. This routine allocates the columns structures then runs over + * all rows and cells in the table. The function pointers in "tbl" are + * used for the actual width calculations. + */ +void +tblcalc(struct rofftbl *tbl, const struct tbl_span *sp) +{ + const struct tbl_dat *dp; + const struct tbl_head *hp; + struct roffcol *col; + + /* + * Allocate the master column specifiers. These will hold the + * widths and decimal positions for all cells in the column. It + * must be freed and nullified by the caller. + */ + + assert(NULL == tbl->cols); + tbl->cols = calloc(sp->tbl->cols, sizeof(struct roffcol)); + + hp = sp->head; + + for ( ; sp; sp = sp->next) { + if (TBL_SPAN_DATA != sp->pos) + continue; + /* + * Account for the data cells in the layout, matching it + * to data cells in the data section. + */ + for (dp = sp->first; dp; dp = dp->next) { + if (NULL == dp->layout) + continue; + col = &tbl->cols[dp->layout->head->ident]; + tblcalc_data(tbl, col, sp->tbl, dp); + } + } + + /* + * Calculate width of the spanners. These get one space for a + * vertical line, two for a double-vertical line. + */ + + for ( ; hp; hp = hp->next) { + col = &tbl->cols[hp->ident]; + switch (hp->pos) { + case (TBL_HEAD_VERT): + col->width = (*tbl->len)(1, tbl->arg); + break; + case (TBL_HEAD_DVERT): + col->width = (*tbl->len)(2, tbl->arg); + break; + default: + break; + } + } +} + +static void +tblcalc_data(struct rofftbl *tbl, struct roffcol *col, + const struct tbl *tp, const struct tbl_dat *dp) +{ + size_t sz; + + /* Branch down into data sub-types. */ + + switch (dp->layout->pos) { + case (TBL_CELL_HORIZ): + /* FALLTHROUGH */ + case (TBL_CELL_DHORIZ): + sz = (*tbl->len)(1, tbl->arg); + if (col->width < sz) + col->width = sz; + break; + case (TBL_CELL_LONG): + /* FALLTHROUGH */ + case (TBL_CELL_CENTRE): + /* FALLTHROUGH */ + case (TBL_CELL_LEFT): + /* FALLTHROUGH */ + case (TBL_CELL_RIGHT): + tblcalc_literal(tbl, col, dp); + break; + case (TBL_CELL_NUMBER): + tblcalc_number(tbl, col, tp, dp); + break; + default: + abort(); + /* NOTREACHED */ + } +} + +static void +tblcalc_literal(struct rofftbl *tbl, struct roffcol *col, + const struct tbl_dat *dp) +{ + size_t sz, bufsz, spsz; + + /* + * Calculate our width and use the spacing, with a minimum + * spacing dictated by position (centre, e.g,. gets a space on + * either side, while right/left get a single adjacent space). + */ + + sz = bufsz = spsz = 0; + if (dp->string) + sz = (*tbl->slen)(dp->string, tbl->arg); + + assert(dp->layout); + switch (dp->layout->pos) { + case (TBL_CELL_LONG): + /* FALLTHROUGH */ + case (TBL_CELL_CENTRE): + bufsz = (*tbl->len)(2, tbl->arg); + break; + default: + bufsz = (*tbl->len)(1, tbl->arg); + break; + } + + if (dp->layout->spacing) { + spsz = (*tbl->len)(dp->layout->spacing, tbl->arg); + bufsz = bufsz > spsz ? bufsz : spsz; + } + + sz += bufsz; + if (col->width < sz) + col->width = sz; +} + +static void +tblcalc_number(struct rofftbl *tbl, struct roffcol *col, + const struct tbl *tp, const struct tbl_dat *dp) +{ + int i; + size_t sz, psz, ssz, d, max; + char *cp; + const char *str; + char buf[2]; + + /* + * First calculate number width and decimal place (last + 1 for + * no-decimal numbers). If the stored decimal is subsequent + * ours, make our size longer by that difference + * (right-"shifting"); similarly, if ours is subsequent the + * stored, then extend the stored size by the difference. + * Finally, re-assign the stored values. + */ + + str = dp && dp->string ? dp->string : ""; + max = dp && dp->layout ? dp->layout->spacing : 0; + + sz = (*tbl->slen)(str, tbl->arg); + + buf[0] = tp->decimal; + buf[1] = '\0'; + + psz = (*tbl->slen)(buf, tbl->arg); + + if (NULL != (cp = strrchr(str, tp->decimal))) { + buf[1] = '\0'; + for (ssz = 0, i = 0; cp != &str[i]; i++) { + buf[0] = str[i]; + ssz += (*tbl->slen)(buf, tbl->arg); + } + d = ssz + psz; + } else + d = sz + psz; + + /* Padding. */ + + sz += (*tbl->len)(2, tbl->arg); + d += (*tbl->len)(1, tbl->arg); + + /* Adjust the settings for this column. */ + + if (col->decimal > d) { + sz += col->decimal - d; + d = col->decimal; + } else + col->width += d - col->decimal; + + if (sz > col->width) + col->width = sz; + if (d > col->decimal) + col->decimal = d; + + /* Adjust for stipulated width. */ + + if (col->width < max) + col->width = max; +} + + diff --git a/usr.bin/mandoc/out.h b/usr.bin/mandoc/out.h index bbd24ab54be..bdf04e69fe9 100644 --- a/usr.bin/mandoc/out.h +++ b/usr.bin/mandoc/out.h @@ -1,6 +1,6 @@ -/* $Id: out.h,v 1.6 2010/07/25 18:05:54 schwarze Exp $ */ +/* $Id: out.h,v 1.7 2011/01/09 14:30:48 schwarze Exp $ */ /* - * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2009, 2010, 2011 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 @@ -21,6 +21,21 @@ __BEGIN_DECLS +struct roffcol { + size_t width; /* width of cell */ + size_t decimal; /* decimal position in cell */ +}; + +typedef size_t (*tbl_strlen)(const char *, void *); +typedef size_t (*tbl_len)(size_t, void *); + +struct rofftbl { + tbl_strlen slen; /* calculate string length */ + tbl_len len; /* produce width of empty space */ + struct roffcol *cols; /* master column specifiers */ + void *arg; /* passed to slen and len */ +}; + enum roffscale { SCALE_CM, SCALE_IN, @@ -40,11 +55,11 @@ enum roffdeco { DECO_SPECIAL, /* special character */ DECO_SSPECIAL, /* single-char special */ DECO_RESERVED, /* reserved word */ - DECO_BOLD, - DECO_ITALIC, - DECO_ROMAN, - DECO_PREVIOUS, - DECO_NOSPACE, + DECO_BOLD, /* bold font */ + DECO_ITALIC, /* italic font */ + DECO_ROMAN, /* "normal" undecorated font */ + DECO_PREVIOUS, /* revert to previous font */ + DECO_NOSPACE, /* suppress spacing */ DECO_FONT, /* font */ DECO_FFONT, /* font family */ DECO_MAX @@ -55,10 +70,6 @@ struct roffsu { double scale; }; -#define SCALE_INVERT(p) \ - do { (p)->scale = -(p)->scale; } \ - while (/* CONSTCOND */ 0) - #define SCALE_VS_INIT(p, v) \ do { (p)->unit = SCALE_VS; \ (p)->scale = (v); } \ @@ -69,11 +80,11 @@ struct roffsu { (p)->scale = (v); } \ while (/* CONSTCOND */ 0) -int a2roffsu(const char *, - struct roffsu *, enum roffscale); -int a2roffdeco(enum roffdeco *, const char **, size_t *); -void time2a(time_t, char *, size_t); +int a2roffsu(const char *, struct roffsu *, enum roffscale); +int a2roffdeco(enum roffdeco *, const char **, size_t *); +void time2a(time_t, char *, size_t); +void tblcalc(struct rofftbl *tbl, const struct tbl_span *); __END_DECLS -#endif /*!HTML_H*/ +#endif /*!OUT_H*/ diff --git a/usr.bin/mandoc/tbl_data.c b/usr.bin/mandoc/tbl_data.c index a10404df38a..d1d39755c38 100644 --- a/usr.bin/mandoc/tbl_data.c +++ b/usr.bin/mandoc/tbl_data.c @@ -1,4 +1,4 @@ -/* $Id: tbl_data.c,v 1.4 2011/01/04 22:28:17 schwarze Exp $ */ +/* $Id: tbl_data.c,v 1.5 2011/01/09 14:30:48 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -41,10 +41,14 @@ data(struct tbl_node *tbl, struct tbl_span *dp, else if (NULL == dp->last) cp = dp->layout->first; - /* Skip over spanners to data formats. */ + /* + * Skip over spanners and vertical lines to data formats, since + * we want to match data with data layout cells in the header. + */ while (cp && (TBL_CELL_VERT == cp->pos || - TBL_CELL_DVERT == cp->pos)) + TBL_CELL_DVERT == cp->pos || + TBL_CELL_SPAN == cp->pos)) cp = cp->next; dat = mandoc_calloc(1, sizeof(struct tbl_dat)); @@ -104,20 +108,33 @@ data(struct tbl_node *tbl, struct tbl_span *dp, return(1); } +/* ARGSUSED */ int tbl_cdata(struct tbl_node *tbl, int ln, const char *p) { struct tbl_dat *dat; size_t sz; + int pos; - if (0 == strcmp(p, "T}")) { - tbl->part = TBL_PART_DATA; - return(1); - } + pos = 0; dat = tbl->last_span->last; dat->pos = TBL_DATA_DATA; + if (p[pos] == 'T' && p[pos + 1] == '}') { + pos += 2; + if (p[pos] == tbl->opts.tab) { + tbl->part = TBL_PART_DATA; + pos++; + return(data(tbl, tbl->last_span, ln, p, &pos)); + } else if ('\0' == p[pos]) { + tbl->part = TBL_PART_DATA; + return(1); + } + + /* Fallthrough: T} is part of a word. */ + } + if (dat->string) { sz = strlen(p) + strlen(dat->string) + 2; dat->string = mandoc_realloc(dat->string, sz); diff --git a/usr.bin/mandoc/tbl_html.c b/usr.bin/mandoc/tbl_html.c index b5ca990b274..5c580cb7524 100644 --- a/usr.bin/mandoc/tbl_html.c +++ b/usr.bin/mandoc/tbl_html.c @@ -1,4 +1,4 @@ -/* $Id: tbl_html.c,v 1.1 2011/01/04 22:28:17 schwarze Exp $ */ +/* $Id: tbl_html.c,v 1.2 2011/01/09 14:30:48 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons <kristaps@kth.se> * @@ -27,47 +27,100 @@ #include "out.h" #include "html.h" +static size_t html_tbl_len(size_t, void *); +static size_t html_tbl_strlen(const char *, void *); + +/* ARGSUSED */ +static size_t +html_tbl_len(size_t sz, void *arg) +{ + + return(sz); +} + +/* ARGSUSED */ +static size_t +html_tbl_strlen(const char *p, void *arg) +{ + + return(strlen(p)); +} + void print_tbl(struct html *h, const struct tbl_span *sp) { const struct tbl_head *hp; const struct tbl_dat *dp; - struct tag *tt; + struct tag *tt; + struct htmlpair tag; + struct roffsu su; + struct roffcol *col; + + /* Inhibit printing of spaces: we do padding ourselves. */ + + h->flags |= HTML_NONOSPACE; + h->flags |= HTML_NOSPACE; + + /* First pass: calculate widths. */ + + if (TBL_SPAN_FIRST & sp->flags) { + h->tbl.len = html_tbl_len; + h->tbl.slen = html_tbl_strlen; + tblcalc(&h->tbl, sp); + } switch (sp->pos) { case (TBL_SPAN_HORIZ): /* FALLTHROUGH */ case (TBL_SPAN_DHORIZ): - return; - default: break; - } + default: + PAIR_CLASS_INIT(&tag, "tbl"); + print_otag(h, TAG_TABLE, 1, &tag); + print_otag(h, TAG_TR, 0, NULL); - /* Inhibit printing of spaces: we do padding ourselves. */ + /* Iterate over template headers. */ - h->flags |= HTML_NONOSPACE; - h->flags |= HTML_NOSPACE; + dp = sp->first; + for (hp = sp->head; hp; hp = hp->next) { + switch (hp->pos) { + case (TBL_HEAD_VERT): + /* FALLTHROUGH */ + case (TBL_HEAD_DVERT): + continue; + case (TBL_HEAD_DATA): + break; + } - print_otag(h, TAG_TABLE, 0, NULL); - print_otag(h, TAG_TR, 0, NULL); - - dp = sp->first; - for (hp = sp->head; hp; hp = hp->next) { - switch (hp->pos) { - case (TBL_HEAD_VERT): - /* FALLTHROUGH */ - case (TBL_HEAD_DVERT): - continue; - case (TBL_HEAD_DATA): - break; - } - tt = print_otag(h, TAG_TD, 0, NULL); - if (dp) { - if (dp->string) + /* + * For the time being, use the simplest possible + * table styling: setting the widths of data + * columns. + */ + + col = &h->tbl.cols[hp->ident]; + SCALE_HS_INIT(&su, col->width); + bufcat_su(h, "width", &su); + PAIR_STYLE_INIT(&tag, h); + tt = print_otag(h, TAG_TD, 1, &tag); + + if (dp && dp->string) print_text(h, dp->string); - dp = dp->next; + if (dp) + dp = dp->next; + + print_tagq(h, tt); } - print_tagq(h, tt); + break; } + h->flags &= ~HTML_NONOSPACE; + + /* Close out column specifiers on the last span. */ + + if (TBL_SPAN_LAST & sp->flags) { + assert(h->tbl.cols); + free(h->tbl.cols); + h->tbl.cols = NULL; + } } diff --git a/usr.bin/mandoc/tbl_layout.c b/usr.bin/mandoc/tbl_layout.c index b623af4bdd0..7cd8d63d469 100644 --- a/usr.bin/mandoc/tbl_layout.c +++ b/usr.bin/mandoc/tbl_layout.c @@ -1,4 +1,4 @@ -/* $Id: tbl_layout.c,v 1.5 2011/01/04 23:44:20 schwarze Exp $ */ +/* $Id: tbl_layout.c,v 1.6 2011/01/09 14:30:48 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -29,6 +29,12 @@ struct tbl_phrase { enum tbl_cellt key; }; +/* + * FIXME: we can make this parse a lot nicer by, when an error is + * encountered in a layout key, bailing to the next key (i.e. to the + * next whitespace then continuing). + */ + #define KEYS_MAX 11 static const struct tbl_phrase keys[KEYS_MAX] = { @@ -84,6 +90,20 @@ mod: break; } + /* Throw away parenthesised expression. */ + + if ('(' == p[*pos]) { + (*pos)++; + while (p[*pos] && ')' != p[*pos]) + (*pos)++; + if (')' == p[*pos]) { + (*pos)++; + goto mod; + } + TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos); + return(0); + } + /* Parse numerical spacing from modifier string. */ if (isdigit((unsigned char)p[*pos])) { @@ -110,7 +130,7 @@ mod: /* TODO: GNU has many more extensions. */ - switch (tolower(p[(*pos)++])) { + switch (tolower((unsigned char)p[(*pos)++])) { case ('z'): cp->flags |= TBL_CELL_WIGN; goto mod; @@ -140,7 +160,7 @@ mod: return(0); } - switch (tolower(p[(*pos)++])) { + switch (tolower((unsigned char)p[(*pos)++])) { case ('b'): cp->flags |= TBL_CELL_BOLD; goto mod; @@ -165,7 +185,7 @@ cell(struct tbl_node *tbl, struct tbl_row *rp, /* Parse the column position (`r', `R', `|', ...). */ for (i = 0; i < KEYS_MAX; i++) - if (tolower(p[*pos]) == keys[i].name) + if (tolower((unsigned char)p[*pos]) == keys[i].name) break; if (KEYS_MAX == i) { @@ -173,9 +193,20 @@ cell(struct tbl_node *tbl, struct tbl_row *rp, return(0); } - (*pos)++; c = keys[i].key; + /* + * If a span cell is found first, raise a warning and abort the + * parse. FIXME: recover from this somehow? + */ + + if (NULL == rp->first && TBL_CELL_SPAN == c) { + TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos); + return(0); + } + + (*pos)++; + /* Extra check for the double-vertical. */ if (TBL_CELL_VERT == c && '|' == p[*pos]) { diff --git a/usr.bin/mandoc/tbl_opts.c b/usr.bin/mandoc/tbl_opts.c index 9a8f0aba620..5c2f99108e1 100644 --- a/usr.bin/mandoc/tbl_opts.c +++ b/usr.bin/mandoc/tbl_opts.c @@ -1,6 +1,6 @@ -/* $Id: tbl_opts.c,v 1.1 2011/01/04 22:28:17 schwarze Exp $ */ +/* $Id: tbl_opts.c,v 1.2 2011/01/09 14:30:48 schwarze Exp $ */ /* - * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2009, 2010, 2011 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 @@ -72,12 +72,12 @@ static const struct tbl_phrase keys[KEY_MAXKEYS] = { }; static int arg(struct tbl_node *, int, - const char *, int *, int); + const char *, int *, enum tbl_ident); static void opt(struct tbl_node *, int, const char *, int *); static int -arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key) +arg(struct tbl_node *tbl, int ln, const char *p, int *pos, enum tbl_ident key) { int i; char buf[KEY_MAXNUMSZ]; @@ -102,12 +102,12 @@ arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key) switch (key) { case (KEY_DELIM): - if ('\0' == (tbl->opts.delims[0] = p[(*pos)++])) { + if ('\0' == p[(*pos)++]) { TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1); return(0); } - if ('\0' == (tbl->opts.delims[1] = p[(*pos)++])) { + if ('\0' == p[(*pos)++]) { TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1); return(0); } @@ -188,7 +188,7 @@ again: /* /* Copy up to first non-alpha character. */ for (sv = *pos, i = 0; i < KEY_MAXNAME; i++, (*pos)++) { - buf[i] = tolower(p[*pos]); + buf[i] = tolower((unsigned char)p[*pos]); if ( ! isalpha((unsigned char)buf[i])) break; } diff --git a/usr.bin/mandoc/tbl_term.c b/usr.bin/mandoc/tbl_term.c index 7b7a056ea3c..8165028d6cf 100644 --- a/usr.bin/mandoc/tbl_term.c +++ b/usr.bin/mandoc/tbl_term.c @@ -1,4 +1,4 @@ -/* $Id: tbl_term.c,v 1.5 2011/01/04 22:28:17 schwarze Exp $ */ +/* $Id: tbl_term.c,v 1.6 2011/01/09 14:30:48 schwarze Exp $ */ /* * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@kth.se> * @@ -23,47 +23,49 @@ #include "out.h" #include "term.h" -/* FIXME: `n' modifier doesn't always do the right thing. */ -/* FIXME: `n' modifier doesn't use the cell-spacing buffer. */ - -static inline void tbl_char(struct termp *, char, int); -static void tbl_hframe(struct termp *, - const struct tbl_span *); -static void tbl_data_number(struct termp *, - const struct tbl *, - const struct tbl_dat *, - const struct termp_tbl *); -static void tbl_data_literal(struct termp *, - const struct tbl_dat *, - const struct termp_tbl *); -static void tbl_data(struct termp *, const struct tbl *, - const struct tbl_dat *, - const struct termp_tbl *); -static void tbl_spanner(struct termp *, - const struct tbl_head *); -static void tbl_hrule(struct termp *, - const struct tbl_span *); -static void tbl_vframe(struct termp *, - const struct tbl *); -static void tbl_calc(struct termp *, - const struct tbl_span *); -static void tbl_calc_data(struct termp *, - const struct tbl *, - const struct tbl_dat *, - struct termp_tbl *); -static void tbl_calc_data_literal(struct termp *, - const struct tbl_dat *, - struct termp_tbl *); -static void tbl_calc_data_number(struct termp *, - const struct tbl *, - const struct tbl_dat *, - struct termp_tbl *); +static size_t term_tbl_len(size_t, void *); +static size_t term_tbl_strlen(const char *, void *); +static void tbl_char(struct termp *, char, size_t); +static void tbl_data(struct termp *, const struct tbl *, + const struct tbl_dat *, + const struct roffcol *); +static void tbl_hframe(struct termp *, const struct tbl_span *); +static void tbl_literal(struct termp *, const struct tbl_dat *, + const struct roffcol *); +static void tbl_number(struct termp *, const struct tbl *, + const struct tbl_dat *, + const struct roffcol *); +static void tbl_hrule(struct termp *, const struct tbl_span *); +static void tbl_vframe(struct termp *, const struct tbl *); +static void tbl_vrule(struct termp *, const struct tbl_head *); + + +static size_t +term_tbl_strlen(const char *p, void *arg) +{ + + return(term_strlen((const struct termp *)arg, p)); +} + +static size_t +term_tbl_len(size_t sz, void *arg) +{ + + return(term_len((const struct termp *)arg, sz)); +} void term_tbl(struct termp *tp, const struct tbl_span *sp) { - const struct tbl_head *hp; - const struct tbl_dat *dp; + const struct tbl_head *hp; + const struct tbl_dat *dp; + struct roffcol *col; + size_t rmargin, maxrmargin; + + rmargin = tp->rmargin; + maxrmargin = tp->maxrmargin; + + tp->rmargin = tp->maxrmargin = TERM_MAXMARGIN; /* Inhibit printing of spaces: we do padding ourselves. */ @@ -71,24 +73,18 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) tp->flags |= TERMP_NOSPACE; /* - * The first time we're invoked for a given table block, create - * the termp_tbl structure. This contains the column - * configuration for the entire table, e.g., table-wide column - * width, decimal point, etc. + * The first time we're invoked for a given table block, + * calculate the table widths and decimal positions. */ if (TBL_SPAN_FIRST & sp->flags) { - assert(NULL == tp->tbl); - tp->tbl = calloc - (sp->tbl->cols, sizeof(struct termp_tbl)); - if (NULL == tp->tbl) { - perror(NULL); - exit(EXIT_FAILURE); - } - tbl_calc(tp, sp); - - /* Flush out any preceding data. */ term_flushln(tp); + + tp->tbl.len = term_tbl_len; + tp->tbl.slen = term_tbl_strlen; + tp->tbl.arg = tp; + + tblcalc(&tp->tbl, sp); } /* Horizontal frame at the start of boxed tables. */ @@ -120,13 +116,14 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) case (TBL_HEAD_VERT): /* FALLTHROUGH */ case (TBL_HEAD_DVERT): - tbl_spanner(tp, hp); + tbl_vrule(tp, hp); continue; case (TBL_HEAD_DATA): break; } - tbl_data(tp, sp->tbl, dp, - &tp->tbl[hp->ident]); + + col = &tp->tbl.cols[hp->ident]; + tbl_data(tp, sp->tbl, dp, col); /* Go to the next data cell. */ if (dp) @@ -145,12 +142,14 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) if (TBL_SPAN_LAST & sp->flags) { tbl_hframe(tp, sp); - assert(tp->tbl); - free(tp->tbl); - tp->tbl = NULL; + assert(tp->tbl.cols); + free(tp->tbl.cols); + tp->tbl.cols = NULL; } tp->flags &= ~TERMP_NONOSPACE; + tp->rmargin = rmargin; + tp->maxrmargin = maxrmargin; } @@ -159,7 +158,7 @@ tbl_hrule(struct termp *tp, const struct tbl_span *sp) { const struct tbl_head *hp; char c; - int width; + size_t width; /* * An hrule extends across the entire table and is demarked by a @@ -174,7 +173,7 @@ tbl_hrule(struct termp *tp, const struct tbl_span *sp) /* FIXME: don't use `+' between data and a spanner! */ for (hp = sp->head; hp; hp = hp->next) { - width = tp->tbl[hp->ident].width; + width = tp->tbl.cols[hp->ident].width; switch (hp->pos) { case (TBL_HEAD_DATA): tbl_char(tp, c, width); @@ -196,7 +195,7 @@ static void tbl_hframe(struct termp *tp, const struct tbl_span *sp) { const struct tbl_head *hp; - int width; + size_t width; if ( ! (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts)) @@ -213,7 +212,7 @@ tbl_hframe(struct termp *tp, const struct tbl_span *sp) if (TBL_OPT_DBOX & sp->tbl->opts) { term_word(tp, "+"); for (hp = sp->head; hp; hp = hp->next) { - width = tp->tbl[hp->ident].width; + width = tp->tbl.cols[hp->ident].width; tbl_char(tp, '-', width); } term_word(tp, "+"); @@ -222,7 +221,7 @@ tbl_hframe(struct termp *tp, const struct tbl_span *sp) term_word(tp, "+"); for (hp = sp->head; hp; hp = hp->next) { - width = tp->tbl[hp->ident].width; + width = tp->tbl.cols[hp->ident].width; switch (hp->pos) { case (TBL_HEAD_DATA): tbl_char(tp, '-', width); @@ -239,41 +238,41 @@ tbl_hframe(struct termp *tp, const struct tbl_span *sp) static void tbl_data(struct termp *tp, const struct tbl *tbl, const struct tbl_dat *dp, - const struct termp_tbl *tbp) + const struct roffcol *col) { enum tbl_cellt pos; if (NULL == dp) { - tbl_char(tp, ASCII_NBRSP, tbp->width); + tbl_char(tp, ASCII_NBRSP, col->width); return; } switch (dp->pos) { case (TBL_DATA_NONE): - tbl_char(tp, ASCII_NBRSP, tbp->width); + tbl_char(tp, ASCII_NBRSP, col->width); return; case (TBL_DATA_HORIZ): /* FALLTHROUGH */ case (TBL_DATA_NHORIZ): - tbl_char(tp, '-', tbp->width); + tbl_char(tp, '-', col->width); return; case (TBL_DATA_NDHORIZ): /* FALLTHROUGH */ case (TBL_DATA_DHORIZ): - tbl_char(tp, '=', tbp->width); + tbl_char(tp, '=', col->width); return; default: break; } - pos = dp->layout ? dp->layout->pos : TBL_CELL_LEFT; + pos = dp && dp->layout ? dp->layout->pos : TBL_CELL_LEFT; switch (pos) { case (TBL_CELL_HORIZ): - tbl_char(tp, '-', tbp->width); + tbl_char(tp, '-', col->width); break; case (TBL_CELL_DHORIZ): - tbl_char(tp, '=', tbp->width); + tbl_char(tp, '=', col->width); break; case (TBL_CELL_LONG): /* FALLTHROUGH */ @@ -282,18 +281,19 @@ tbl_data(struct termp *tp, const struct tbl *tbl, case (TBL_CELL_LEFT): /* FALLTHROUGH */ case (TBL_CELL_RIGHT): - tbl_data_literal(tp, dp, tbp); + tbl_literal(tp, dp, col); break; case (TBL_CELL_NUMBER): - tbl_data_number(tp, tbl, dp, tbp); + tbl_number(tp, tbl, dp, col); break; default: abort(); /* NOTREACHED */ } } + static void -tbl_spanner(struct termp *tp, const struct tbl_head *hp) +tbl_vrule(struct termp *tp, const struct tbl_head *hp) { switch (hp->pos) { @@ -311,16 +311,15 @@ tbl_spanner(struct termp *tp, const struct tbl_head *hp) static void tbl_vframe(struct termp *tp, const struct tbl *tbl) { - /* Always just a single vertical line. */ if (TBL_OPT_BOX & tbl->opts || TBL_OPT_DBOX & tbl->opts) term_word(tp, "|"); } -static inline void -tbl_char(struct termp *tp, char c, int len) +static void +tbl_char(struct termp *tp, char c, size_t len) { - int i, sz; + size_t i, sz; char cp[2]; cp[0] = c; @@ -333,178 +332,74 @@ tbl_char(struct termp *tp, char c, int len) } static void -tbl_data_literal(struct termp *tp, - const struct tbl_dat *dp, - const struct termp_tbl *tblp) +tbl_literal(struct termp *tp, const struct tbl_dat *dp, + const struct roffcol *col) { - int padl, padr, ssz; + size_t padl, padr, ssz; enum tbl_cellt pos; + const char *str; padl = padr = 0; - pos = dp->layout ? dp->layout->pos : TBL_CELL_LEFT; + pos = dp && dp->layout ? dp->layout->pos : TBL_CELL_LEFT; + str = dp && dp->string ? dp->string : ""; + ssz = term_len(tp, 1); switch (pos) { case (TBL_CELL_LONG): padl = ssz; - padr = tblp->width - term_strlen(tp, dp->string) - ssz; + padr = col->width - term_strlen(tp, str) - ssz; break; case (TBL_CELL_CENTRE): - padl = tblp->width - term_strlen(tp, dp->string); + padl = col->width - term_strlen(tp, str); if (padl % 2) padr++; padl /= 2; padr += padl; break; case (TBL_CELL_RIGHT): - padl = tblp->width - term_strlen(tp, dp->string); + padl = col->width - term_strlen(tp, str); break; default: - padr = tblp->width - term_strlen(tp, dp->string); + padr = col->width - term_strlen(tp, str); break; } tbl_char(tp, ASCII_NBRSP, padl); - term_word(tp, dp->string); + term_word(tp, str); tbl_char(tp, ASCII_NBRSP, padr); } static void -tbl_data_number(struct termp *tp, const struct tbl *tbl, +tbl_number(struct termp *tp, const struct tbl *tbl, const struct tbl_dat *dp, - const struct termp_tbl *tblp) + const struct roffcol *col) { - char *decp, buf[2]; - int d, padl, sz, psz, ssz, i; + char *cp; + char buf[2]; + const char *str; + size_t sz, psz, ssz, d, padl; + int i; /* * See calc_data_number(). Left-pad by taking the offset of our * and the maximum decimal; right-pad by the remaining amount. */ - sz = term_strlen(tp, dp->string); - psz = term_strlen(tp, "."); - - if (NULL != (decp = strchr(dp->string, tbl->decimal))) { - buf[1] = '\0'; - for (ssz = i = 0; decp != &dp->string[i]; i++) { - buf[0] = dp->string[i]; - ssz += term_strlen(tp, buf); - } - d = ssz + psz; - } else - d = sz + psz; - - assert(d <= tblp->decimal); - assert(sz - d <= tblp->width - tblp->decimal); - - padl = tblp->decimal - d + term_len(tp, 1); - assert(tblp->width - sz - padl); + str = dp && dp->string ? dp->string : ""; - tbl_char(tp, ASCII_NBRSP, padl); - term_word(tp, dp->string); - tbl_char(tp, ASCII_NBRSP, tblp->width - sz - padl); -} - -static void -tbl_calc(struct termp *tp, const struct tbl_span *sp) -{ - const struct tbl_dat *dp; - const struct tbl_head *hp; - struct termp_tbl *p; - - /* Calculate width as the max of column cells' widths. */ - - hp = sp->head; - - for ( ; sp; sp = sp->next) { - if (TBL_SPAN_DATA != sp->pos) - continue; - - for (dp = sp->first; dp; dp = dp->next) { - if (NULL == dp->layout) - continue; - p = &tp->tbl[dp->layout->head->ident]; - tbl_calc_data(tp, sp->tbl, dp, p); - } - } + sz = term_strlen(tp, str); - /* Calculate width as the simple spanner value. */ + buf[0] = tbl->decimal; + buf[1] = '\0'; - for ( ; hp; hp = hp->next) - switch (hp->pos) { - case (TBL_HEAD_VERT): - tp->tbl[hp->ident].width = term_len(tp, 1); - break; - case (TBL_HEAD_DVERT): - tp->tbl[hp->ident].width = term_len(tp, 2); - break; - default: - break; - } -} + psz = term_strlen(tp, buf); -static void -tbl_calc_data(struct termp *tp, const struct tbl *tbl, - const struct tbl_dat *dp, struct termp_tbl *tblp) -{ - int sz; - - /* Branch down into data sub-types. */ - - switch (dp->layout->pos) { - case (TBL_CELL_HORIZ): - /* FALLTHROUGH */ - case (TBL_CELL_DHORIZ): - sz = term_len(tp, 1); - if (tblp->width < sz) - tblp->width = sz; - break; - case (TBL_CELL_LONG): - /* FALLTHROUGH */ - case (TBL_CELL_CENTRE): - /* FALLTHROUGH */ - case (TBL_CELL_LEFT): - /* FALLTHROUGH */ - case (TBL_CELL_RIGHT): - tbl_calc_data_literal(tp, dp, tblp); - break; - case (TBL_CELL_NUMBER): - tbl_calc_data_number(tp, tbl, dp, tblp); - break; - default: - abort(); - /* NOTREACHED */ - } -} - -static void -tbl_calc_data_number(struct termp *tp, const struct tbl *tbl, - const struct tbl_dat *dp, struct termp_tbl *tblp) -{ - int sz, d, psz, i, ssz; - char *cp, buf[2]; - - /* - * First calculate number width and decimal place (last + 1 for - * no-decimal numbers). If the stored decimal is subsequent - * ours, make our size longer by that difference - * (right-"shifting"); similarly, if ours is subsequent the - * stored, then extend the stored size by the difference. - * Finally, re-assign the stored values. - */ - - /* TODO: use spacing modifier. */ - - assert(dp->string); - sz = term_strlen(tp, dp->string); - psz = term_strlen(tp, "."); - - if (NULL != (cp = strchr(dp->string, tbl->decimal))) { + if (NULL != (cp = strrchr(str, tbl->decimal))) { buf[1] = '\0'; - for (ssz = i = 0; cp != &dp->string[i]; i++) { - buf[0] = dp->string[i]; + for (ssz = 0, i = 0; cp != &str[i]; i++) { + buf[0] = str[i]; ssz += term_strlen(tp, buf); } d = ssz + psz; @@ -512,54 +407,12 @@ tbl_calc_data_number(struct termp *tp, const struct tbl *tbl, d = sz + psz; sz += term_len(tp, 2); + d += term_len(tp, 1); - if (tblp->decimal > d) { - sz += tblp->decimal - d; - d = tblp->decimal; - } else - tblp->width += d - tblp->decimal; + padl = col->decimal - d; - if (sz > tblp->width) - tblp->width = sz; - if (d > tblp->decimal) - tblp->decimal = d; + tbl_char(tp, ASCII_NBRSP, padl); + term_word(tp, str); + tbl_char(tp, ASCII_NBRSP, col->width - sz - padl); } -static void -tbl_calc_data_literal(struct termp *tp, - const struct tbl_dat *dp, - struct termp_tbl *tblp) -{ - int sz, bufsz, spsz; - - /* - * Calculate our width and use the spacing, with a minimum - * spacing dictated by position (centre, e.g,. gets a space on - * either side, while right/left get a single adjacent space). - */ - - assert(dp->string); - sz = term_strlen(tp, dp->string); - - switch (dp->layout->pos) { - case (TBL_CELL_LONG): - /* FALLTHROUGH */ - case (TBL_CELL_CENTRE): - bufsz = term_len(tp, 2); - break; - default: - bufsz = term_len(tp, 1); - break; - } - - spsz = 0; - if (dp->layout->spacing) - spsz = term_len(tp, dp->layout->spacing); - - if (spsz) - bufsz = bufsz > spsz ? bufsz : spsz; - - sz += bufsz; - if (tblp->width < sz) - tblp->width = sz; -} diff --git a/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h index dd22b426ec8..1dfeecf0e1f 100644 --- a/usr.bin/mandoc/term.h +++ b/usr.bin/mandoc/term.h @@ -1,4 +1,4 @@ -/* $Id: term.h,v 1.28 2011/01/04 22:28:17 schwarze Exp $ */ +/* $Id: term.h,v 1.29 2011/01/09 14:30:48 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -78,7 +78,7 @@ struct termp_tbl { struct termp { enum termtype type; - struct termp_tbl *tbl; /* table configuration */ + struct rofftbl tbl; /* table configuration */ size_t defrmargin; /* Right margin of the device. */ size_t rmargin; /* Current right margin. */ size_t maxrmargin; /* Max right margin. */ |