diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2014-12-24 23:32:42 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2014-12-24 23:32:42 +0000 |
commit | 4039dc9d2363717732db9e312b0dcc38973d1a54 (patch) | |
tree | e0732e3c42b57f0a92079aacdde4967354c83e24 /mdoc_man.c | |
parent | 87b33207281eab1594f4681af9e74ecdc86df0ba (diff) | |
download | mandoc-4039dc9d2363717732db9e312b0dcc38973d1a54.tar.gz |
Support negative indentations for mdoc(7) displays and lists.
Not exactly recommended for use, rather for groff compatibility.
While here, introduce similar SHRT_MAX limits as in man(7),
fixing a few cases of infinite output found by jsg@ with afl.
Diffstat (limited to 'mdoc_man.c')
-rw-r--r-- | mdoc_man.c | 55 |
1 files changed, 27 insertions, 28 deletions
@@ -116,8 +116,8 @@ static void print_word(const char *); static void print_line(const char *, int); static void print_block(const char *, int); static void print_offs(const char *, int); -static void print_width(const char *, - const struct mdoc_node *, size_t); +static void print_width(const struct mdoc_bl *, + const struct mdoc_node *); static void print_count(int *); static void print_node(DECL_ARGS); @@ -265,7 +265,7 @@ static int outflags; #define BL_STACK_MAX 32 -static size_t Bl_stack[BL_STACK_MAX]; /* offsets [chars] */ +static int Bl_stack[BL_STACK_MAX]; /* offsets [chars] */ static int Bl_stack_post[BL_STACK_MAX]; /* add final .RE */ static int Bl_stack_len; /* number of nested Bl blocks */ static int TPremain; /* characters before tag is full */ @@ -423,7 +423,7 @@ print_offs(const char *v, int keywords) { char buf[24]; struct roffsu su; - size_t sz; + int sz; print_line(".RS", MMAN_Bk_susp); @@ -435,8 +435,6 @@ print_offs(const char *v, int keywords) else if (keywords && !strcmp(v, "indent-two")) sz = 12; else if (a2roffsu(v, &su, SCALE_EN) > 1) { - if (su.scale < 0.0) - su.scale = 0.0; if (SCALE_EN == su.unit) sz = su.scale; else { @@ -461,7 +459,7 @@ print_offs(const char *v, int keywords) if (Bl_stack_len) sz += Bl_stack[Bl_stack_len - 1]; - (void)snprintf(buf, sizeof(buf), "%zun", sz); + (void)snprintf(buf, sizeof(buf), "%dn", sz); print_word(buf); outflags |= MMAN_nl; } @@ -470,22 +468,19 @@ print_offs(const char *v, int keywords) * Set up the indentation for a list item; used from pre_it(). */ static void -print_width(const char *v, const struct mdoc_node *child, size_t defsz) +print_width(const struct mdoc_bl *bl, const struct mdoc_node *child) { char buf[24]; struct roffsu su; - size_t sz, chsz; - int numeric, remain; + int numeric, remain, sz, chsz; numeric = 1; remain = 0; - /* Convert v into a number (of characters). */ - if (NULL == v) - sz = defsz; - else if (a2roffsu(v, &su, SCALE_MAX) > 1) { - if (su.scale < 0.0) - su.scale = 0.0; + /* Convert the width into a number (of characters). */ + if (bl->width == NULL) + sz = (bl->type == LIST_hang) ? 6 : 0; + else if (a2roffsu(bl->width, &su, SCALE_MAX) > 1) { if (SCALE_EN == su.unit) sz = su.scale; else { @@ -493,11 +488,15 @@ print_width(const char *v, const struct mdoc_node *child, size_t defsz) numeric = 0; } } else - sz = strlen(v); + sz = strlen(bl->width); /* XXX Rough estimation, might have multiple parts. */ - chsz = (NULL != child && MDOC_TEXT == child->type) ? - strlen(child->string) : 0; + if (bl->type == LIST_enum) + chsz = (bl->count > 8) + 1; + else if (child != NULL && child->type == MDOC_TEXT) + chsz = strlen(child->string); + else + chsz = 0; /* Maybe we are inside an enclosing list? */ mid_it(); @@ -509,17 +508,17 @@ print_width(const char *v, const struct mdoc_node *child, size_t defsz) Bl_stack[Bl_stack_len++] = sz + 2; /* Set up the current list. */ - if (defsz && chsz > sz) + if (chsz > sz && bl->type != LIST_tag) print_block(".HP", 0); else { print_block(".TP", 0); remain = sz + 2; } if (numeric) { - (void)snprintf(buf, sizeof(buf), "%zun", sz + 2); + (void)snprintf(buf, sizeof(buf), "%dn", sz + 2); print_word(buf); } else - print_word(v); + print_word(bl->width); TPremain = remain; } @@ -528,7 +527,7 @@ print_count(int *count) { char buf[24]; - (void)snprintf(buf, sizeof(buf), "%d.", ++*count); + (void)snprintf(buf, sizeof(buf), "%d.\\&", ++*count); print_word(buf); } @@ -1366,7 +1365,7 @@ pre_it(DECL_ARGS) case LIST_dash: /* FALLTHROUGH */ case LIST_hyphen: - print_width(bln->norm->Bl.width, NULL, 0); + print_width(&bln->norm->Bl, NULL); TPremain = 0; outflags |= MMAN_nl; font_push('B'); @@ -1378,19 +1377,19 @@ pre_it(DECL_ARGS) outflags |= MMAN_nl; return(0); case LIST_enum: - print_width(bln->norm->Bl.width, NULL, 0); + print_width(&bln->norm->Bl, NULL); TPremain = 0; outflags |= MMAN_nl; print_count(&bln->norm->Bl.count); outflags |= MMAN_nl; return(0); case LIST_hang: - print_width(bln->norm->Bl.width, n->child, 6); + print_width(&bln->norm->Bl, n->child); TPremain = 0; outflags |= MMAN_nl; return(1); case LIST_tag: - print_width(bln->norm->Bl.width, n->child, 0); + print_width(&bln->norm->Bl, n->child); putchar('\n'); outflags &= ~MMAN_spc; return(1); @@ -1422,7 +1421,7 @@ mid_it(void) /* Restore the indentation of the enclosing list. */ print_line(".RS", MMAN_Bk_susp); - (void)snprintf(buf, sizeof(buf), "%zun", + (void)snprintf(buf, sizeof(buf), "%dn", Bl_stack[Bl_stack_len - 1]); print_word(buf); |