source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Support negative indentations for mdoc(7) displays and lists.
@ 2014-12-24 23:33 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2014-12-24 23:33 UTC (permalink / raw)
  To: source

Log Message:
-----------
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.

Modified Files:
--------------
    mdocml:
        mdoc_man.c
        mdoc_term.c
        term.c

Revision Data
-------------
Index: term.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/term.c,v
retrieving revision 1.241
retrieving revision 1.242
diff -Lterm.c -Lterm.c -u -p -r1.241 -r1.242
--- term.c
+++ term.c
@@ -273,7 +273,7 @@ term_flushln(struct termp *p)
 	}
 
 	if (TERMP_HANG & p->flags) {
-		p->overstep = (int)(vis - maxvis +
+		p->overstep += (int)(p->offset + vis - p->rmargin +
 		    p->trailspace * (*p->width)(p, ' '));
 
 		/*
Index: mdoc_term.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_term.c,v
retrieving revision 1.301
retrieving revision 1.302
diff -Lmdoc_term.c -Lmdoc_term.c -u -p -r1.301 -r1.302
--- mdoc_term.c
+++ mdoc_term.c
@@ -22,6 +22,7 @@
 
 #include <assert.h>
 #include <ctype.h>
+#include <limits.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -49,7 +50,7 @@ struct	termact {
 	void	(*post)(DECL_ARGS);
 };
 
-static	size_t	  a2width(const struct termp *, const char *);
+static	int	  a2width(const struct termp *, const char *);
 
 static	void	  print_bvspace(struct termp *,
 			const struct mdoc_node *,
@@ -525,7 +526,7 @@ print_mdoc_head(struct termp *p, const v
 	free(volume);
 }
 
-static size_t
+static int
 a2width(const struct termp *p, const char *v)
 {
 	struct roffsu	 su;
@@ -533,9 +534,7 @@ a2width(const struct termp *p, const cha
 	if (a2roffsu(v, &su, SCALE_MAX) < 2) {
 		SCALE_HS_INIT(&su, term_strlen(p, v));
 		su.scale /= term_strlen(p, "0");
-	} else if (su.scale < 0.0)
-		su.scale = 0.0;
-
+	}
 	return(term_hspan(p, &su));
 }
 
@@ -606,10 +605,10 @@ termp_ll_pre(DECL_ARGS)
 static int
 termp_it_pre(DECL_ARGS)
 {
-	const struct mdoc_node *bl, *nn;
 	char			buf[24];
-	int			i;
-	size_t			width, offset, ncols, dcol;
+	const struct mdoc_node *bl, *nn;
+	size_t			ncols, dcol;
+	int			i, offset, width;
 	enum mdoc_list		type;
 
 	if (MDOC_BLOCK == n->type) {
@@ -621,15 +620,46 @@ termp_it_pre(DECL_ARGS)
 	type = bl->norm->Bl.type;
 
 	/*
+	 * Defaults for specific list types.
+	 */
+
+	switch (type) {
+	case LIST_bullet:
+		/* FALLTHROUGH */
+	case LIST_dash:
+		/* FALLTHROUGH */
+	case LIST_hyphen:
+		/* FALLTHROUGH */
+	case LIST_enum:
+		width = term_len(p, 2);
+		break;
+	case LIST_hang:
+		width = term_len(p, 8);
+		break;
+	case LIST_column:
+		/* FALLTHROUGH */
+	case LIST_tag:
+		width = term_len(p, 10);
+		break;
+	default:
+		width = 0;
+		break;
+	}
+	offset = 0;
+
+	/*
 	 * First calculate width and offset.  This is pretty easy unless
 	 * we're a -column list, in which case all prior columns must
 	 * be accounted for.
 	 */
 
-	width = offset = 0;
-
-	if (bl->norm->Bl.offs)
+	if (bl->norm->Bl.offs != NULL) {
 		offset = a2width(p, bl->norm->Bl.offs);
+		if (offset < 0 && (size_t)(-offset) > p->offset)
+			offset = -p->offset;
+		else if (offset > SHRT_MAX)
+			offset = 0;
+	}
 
 	switch (type) {
 	case LIST_column:
@@ -684,39 +714,11 @@ termp_it_pre(DECL_ARGS)
 		 * number for buffering single arguments.  See the above
 		 * handling for column for how this changes.
 		 */
-		assert(bl->norm->Bl.width);
 		width = a2width(p, bl->norm->Bl.width) + term_len(p, 2);
-		break;
-	}
-
-	/*
-	 * List-type can override the width in the case of fixed-head
-	 * values (bullet, dash/hyphen, enum).  Tags need a non-zero
-	 * offset.
-	 */
-
-	switch (type) {
-	case LIST_bullet:
-		/* FALLTHROUGH */
-	case LIST_dash:
-		/* FALLTHROUGH */
-	case LIST_hyphen:
-		/* FALLTHROUGH */
-	case LIST_enum:
-		if (width < term_len(p, 2))
-			width = term_len(p, 2);
-		break;
-	case LIST_hang:
-		if (0 == width)
-			width = term_len(p, 8);
-		break;
-	case LIST_column:
-		/* FALLTHROUGH */
-	case LIST_tag:
-		if (0 == width)
-			width = term_len(p, 10);
-		break;
-	default:
+		if (width < 0 && (size_t)(-width) > p->offset)
+			width = -p->offset;
+		else if (width > SHRT_MAX)
+			width = 0;
 		break;
 	}
 
@@ -762,16 +764,16 @@ termp_it_pre(DECL_ARGS)
 	case LIST_enum:
 		/*
 		 * Weird special case.
-		 * Very narrow enum lists actually hang.
+		 * Some very narrow lists actually hang.
 		 */
-		if (width == term_len(p, 2))
-			p->flags |= TERMP_HANG;
 		/* FALLTHROUGH */
 	case LIST_bullet:
 		/* FALLTHROUGH */
 	case LIST_dash:
 		/* FALLTHROUGH */
 	case LIST_hyphen:
+		if (width <= (int)term_len(p, 2))
+			p->flags |= TERMP_HANG;
 		if (MDOC_HEAD != n->type)
 			break;
 		p->flags |= TERMP_NOBREAK;
@@ -860,7 +862,6 @@ termp_it_pre(DECL_ARGS)
 	case LIST_hyphen:
 		/* FALLTHROUGH */
 	case LIST_tag:
-		assert(width);
 		if (MDOC_HEAD == n->type)
 			p->rmargin = p->offset + width;
 		else
@@ -1540,6 +1541,7 @@ termp_bd_pre(DECL_ARGS)
 {
 	size_t			 tabwidth, lm, len, rm, rmax;
 	struct mdoc_node	*nn;
+	int			 offset;
 
 	if (MDOC_BLOCK == n->type) {
 		print_bvspace(p, n, n);
@@ -1556,8 +1558,13 @@ termp_bd_pre(DECL_ARGS)
 		p->offset += term_len(p, p->defindent + 1);
 	else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
 		p->offset += term_len(p, (p->defindent + 1) * 2);
-	else
-		p->offset += a2width(p, n->norm->Bd.offs);
+	else {
+		offset = a2width(p, n->norm->Bd.offs);
+		if (offset < 0 && (size_t)(-offset) > p->offset)
+			p->offset = 0;
+		else if (offset < SHRT_MAX)
+			p->offset += offset;
+	}
 
 	/*
 	 * If -ragged or -filled are specified, the block does nothing
Index: mdoc_man.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_man.c,v
retrieving revision 1.80
retrieving revision 1.81
diff -Lmdoc_man.c -Lmdoc_man.c -u -p -r1.80 -r1.81
--- mdoc_man.c
+++ mdoc_man.c
@@ -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 
 			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 
 	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);
 
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-12-24 23:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-24 23:33 mdocml: Support negative indentations for mdoc(7) displays and lists schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).