X-Git-Url: https://git.cameronkatri.com/mandoc.git/blobdiff_plain/65f8ae861f5855669ce4473e9c89a5a2003a89ac..0d3c1e62ca62e820e20a744760c2767cee37d5c9:/out.c?ds=inline

diff --git a/out.c b/out.c
index 307af614..2a683fae 100644
--- a/out.c
+++ b/out.c
@@ -1,6 +1,6 @@
-/*	$Id: out.c,v 1.8 2009/11/07 08:26:45 kristaps Exp $ */
+/*	$Id: out.c,v 1.29 2010/08/29 11:28:09 kristaps Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * 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
@@ -14,6 +14,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <sys/types.h>
 
 #include <assert.h>
@@ -25,10 +29,6 @@
 
 #include "out.h"
 
-#ifdef __linux__
-extern	size_t	  strlcat(char *, const char *, size_t);
-#endif
-
 /* 
  * Convert a `scaling unit' to a consistent form, or fail.  Scaling
  * units are documented in groff.7, mdoc.7, man.7.
@@ -116,11 +116,10 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
 		return(0);
 	}
 
+	/* FIXME: do this in the caller. */
 	if ((dst->scale = atof(buf)) < 0)
 		dst->scale = 0;
 	dst->unit = unit;
-	dst->pt = hasd;
-
 	return(1);
 }
 
@@ -167,194 +166,195 @@ time2a(time_t t, char *dst, size_t sz)
 }
 
 
-/* Returns length of parsed string. */
 int
-a2roffdeco(enum roffdeco *d,
-		const char **word, size_t *sz)
+a2roffdeco(enum roffdeco *d, const char **word, size_t *sz)
 {
-	int		 j, type, sv, t, lim;
+	int		 i, j, lim;
+	char		 term, c;
 	const char	*wp;
+	enum roffdeco	 dd;
 
 	*d = DECO_NONE;
-
+	lim = i = 0;
+	term = '\0';
 	wp = *word;
-	type = 1;
-
-	switch (*wp) {
-	case ('\0'):
-		return(0);
 
+	switch ((c = wp[i++])) {
 	case ('('):
-		wp++;
-		if ('\0' == *wp)
-			return(1);
-		if ('\0' == *(wp + 1))
-			return(2);
-
 		*d = DECO_SPECIAL;
-		*sz = 2;
-		*word = wp;
-		return(3);
-
-	case ('*'):
-		wp++;
-
-		switch (*wp) {
-		case ('\0'):
-			return(1);
+		lim = 2;
+		break;
+	case ('F'):
+		/* FALLTHROUGH */
+	case ('f'):
+		*d = 'F' == c ? DECO_FFONT : DECO_FONT;
 
+		switch (wp[i++]) {
 		case ('('):
-			wp++;
-			if ('\0' == *wp)
-				return(2);
-			if ('\0' == *(wp + 1))
-				return(3);
-
-			*d = DECO_RESERVED;
-			*sz = 2;
-			*word = wp;
-			return(4);
-
+			lim = 2;
+			break;
 		case ('['):
-			type = 0;
+			term = ']';
 			break;
-
-		default:
-			*d = DECO_RESERVED;
-			*sz = 1;
-			*word = wp;
-			return(3);
-		}
-		break;
-
-#if 0
-	case ('s'):
-		wp++;
-
-		/* This closely follows mandoc_special(). */
-		if ('\0' == *wp) 
-			return(1);
-
-		t = 0;
-		lim = 1;
-
-		if (*wp == '\'') {
-			lim = 0;
-			t = 1;
-			++wp;
-		} else if (*wp == '[') {
-			lim = 0;
-			t = 2;
-			++wp;
-		} else if (*wp == '(') {
-			lim = 2;
-			t = 3;
-			++wp;
-		}
-
-		if (*wp == '+' || *wp == '-')
-			++wp;
-
-		if (*wp == '\'') {
-			if (t) {
-				*word = wp;
-				return;
-			}
-			lim = 0;
-			t = 1;
-			++wp;
-		} else if (*wp == '[') {
-			if (t) {
-				*word = wp;
-				return;
-			}
-			lim = 0;
-			t = 2;
-			++wp;
-		} else if (*wp == '(') {
-			if (t) {
-				*word = wp;
-				return;
-			}
-			lim = 2;
-			t = 3;
-			++wp;
-		}
-
-		if ( ! isdigit((u_char)*wp)) {
-			*word = --wp;
-			return;
-		}
-
-		for (j = 0; isdigit((u_char)*wp); j++) {
-			if (lim && j >= lim)
-				break;
-			++wp;
-		}
-
-		if (t && t < 3) {
-			if (1 == t && *wp != '\'') {
-				*word = --wp;
-				return;
-			}
-			if (2 == t && *wp != ']') {
-				*word = --wp;
-				return;
-			}
-			++wp;
-		}
-		*word = --wp;
-		return;
-#endif
-
-	case ('f'):
-		wp++;
-
-		switch (*wp) {
-		case ('\0'):
-			return(1);
 		case ('3'):
 			/* FALLTHROUGH */
 		case ('B'):
 			*d = DECO_BOLD;
-			break;
+			return(i);
 		case ('2'):
 			/* FALLTHROUGH */
 		case ('I'):
 			*d = DECO_ITALIC;
-			break;
+			return(i);
 		case ('P'):
 			*d = DECO_PREVIOUS;
-			break;
+			return(i);
 		case ('1'):
 			/* FALLTHROUGH */
 		case ('R'):
 			*d = DECO_ROMAN;
+			return(i);
+		default:
+			i--;
+			lim = 1;
+			break;
+		}
+		break;
+	case ('k'):
+		/* FALLTHROUGH */
+	case ('M'):
+		/* FALLTHROUGH */
+	case ('m'):
+		/* FALLTHROUGH */
+	case ('*'):
+		if ('*' == c)
+			*d = DECO_RESERVED;
+
+		switch (wp[i++]) {
+		case ('('):
+			lim = 2;
+			break;
+		case ('['):
+			term = ']';
+			break;
+		default:
+			i--;
+			lim = 1;
+			break;
+		}
+		break;
+	case ('h'):
+		/* FALLTHROUGH */
+	case ('v'):
+		/* FALLTHROUGH */
+	case ('s'):
+		j = 0;
+		if ('+' == wp[i] || '-' == wp[i]) {
+			i++;
+			j = 1;
+		}
+
+		switch (wp[i++]) {
+		case ('('):
+			lim = 2;
 			break;
+		case ('['):
+			term = ']';
+			break;
+		case ('\''):
+			term = '\'';
+			break;
+		case ('0'):
+			j = 1;
+			/* FALLTHROUGH */
 		default:
+			i--;
+			lim = 1;
 			break;
 		}
 
-		return(2);
+		if ('+' == wp[i] || '-' == wp[i]) {
+			if (j)
+				return(i);
+			i++;
+		} 
 
+		/* Handle embedded numerical subexp or escape. */
+
+		if ('(' == wp[i]) {
+			while (wp[i] && ')' != wp[i])
+				if ('\\' == wp[i++]) {
+					/* Handle embedded escape. */
+					*word = &wp[i];
+					i += a2roffdeco(&dd, word, sz);
+				}
+
+			if (')' == wp[i++])
+				break;
+
+			*d = DECO_NONE;
+			return(i - 1);
+		} else if ('\\' == wp[i]) {
+			*word = &wp[++i];
+			i += a2roffdeco(&dd, word, sz);
+		}
+
+		break;
 	case ('['):
+		*d = DECO_SPECIAL;
+		term = ']';
 		break;
-
+	case ('c'):
+		*d = DECO_NOSPACE;
+		return(i);
+	case ('z'):
+		*d = DECO_NONE;
+		if ('\\' == wp[i]) {
+			*word = &wp[++i];
+			return(i + a2roffdeco(&dd, word, sz));
+		} else
+			lim = 1;
+		break;
+	case ('o'):
+		/* FALLTHROUGH */
+	case ('w'):
+		if ('\'' == wp[i++]) {
+			term = '\'';
+			break;
+		} 
+		/* FALLTHROUGH */
 	default:
-		*d = DECO_SPECIAL;
-		*word = wp;
-		*sz = 1;
-		return(1);
+		*d = DECO_SSPECIAL;
+		i--;
+		lim = 1;
+		break;
+	}
+
+	assert(term || lim);
+	*word = &wp[i];
+
+	if (term) {
+		j = i;
+		while (wp[i] && wp[i] != term)
+			i++;
+		if ('\0' == wp[i]) {
+			*d = DECO_NONE;
+			return(i);
+		}
+
+		assert(i >= j);
+		*sz = (size_t)(i - j);
+
+		return(i + 1);
 	}
 
-	*word = ++wp;
-	for (j = 0; *wp && ']' != *wp; wp++, j++)
-		/* Loop... */ ;
+	assert(lim > 0);
+	*sz = (size_t)lim;
 
-	if ('\0' == *wp)
-		return(j + 1);
+	for (j = 0; wp[i] && j < lim; j++)
+		i++;
+	if (j < lim)
+		*d = DECO_NONE;
 
-	*d = type ? DECO_SPECIAL : DECO_RESERVED;
-	*sz = j;
-	return (j + 2);
+	return(i);
 }