X-Git-Url: https://git.cameronkatri.com/mandoc.git/blobdiff_plain/cd3461ed2decce6e980d3a4c93c615bd8f4cb5c0..0d3c1e62ca62e820e20a744760c2767cee37d5c9:/out.c

diff --git a/out.c b/out.c
index 78abc5dc..2a683fae 100644
--- a/out.c
+++ b/out.c
@@ -1,6 +1,6 @@
-/*	$Id: out.c,v 1.6 2009/10/22 18:55:32 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>
@@ -21,10 +25,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
 #include "out.h"
 
-
 /* 
  * Convert a `scaling unit' to a consistent form, or fail.  Scaling
  * units are documented in groff.7, mdoc.7, man.7.
@@ -112,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);
 }
 
@@ -162,3 +165,196 @@ time2a(time_t t, char *dst, size_t sz)
 	(void)strftime(p, sz, "%Y", &tm);
 }
 
+
+int
+a2roffdeco(enum roffdeco *d, const char **word, size_t *sz)
+{
+	int		 i, j, lim;
+	char		 term, c;
+	const char	*wp;
+	enum roffdeco	 dd;
+
+	*d = DECO_NONE;
+	lim = i = 0;
+	term = '\0';
+	wp = *word;
+
+	switch ((c = wp[i++])) {
+	case ('('):
+		*d = DECO_SPECIAL;
+		lim = 2;
+		break;
+	case ('F'):
+		/* FALLTHROUGH */
+	case ('f'):
+		*d = 'F' == c ? DECO_FFONT : DECO_FONT;
+
+		switch (wp[i++]) {
+		case ('('):
+			lim = 2;
+			break;
+		case ('['):
+			term = ']';
+			break;
+		case ('3'):
+			/* FALLTHROUGH */
+		case ('B'):
+			*d = DECO_BOLD;
+			return(i);
+		case ('2'):
+			/* FALLTHROUGH */
+		case ('I'):
+			*d = DECO_ITALIC;
+			return(i);
+		case ('P'):
+			*d = DECO_PREVIOUS;
+			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;
+		}
+
+		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_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);
+	}
+
+	assert(lim > 0);
+	*sz = (size_t)lim;
+
+	for (j = 0; wp[i] && j < lim; j++)
+		i++;
+	if (j < lim)
+		*d = DECO_NONE;
+
+	return(i);
+}