source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* texi2mdoc: Completely re-write @value and @macro handling to work
@ 2015-02-25 14:37 kristaps
  0 siblings, 0 replies; only message in thread
From: kristaps @ 2015-02-25 14:37 UTC (permalink / raw)
  To: source

Log Message:
-----------
Completely re-write @value and @macro handling to work exactly as Texinfo
specifies and not how I really want it to work.
In a word, macros and values are pasted into the text: they're not self-
contained bodies that can be recursively executed.

In other words,
  @macro hello{}
  @ifset foo
  @end macro
  @hello
  @end ifset
...is completely valid.

While here, stop paying attention to the manual's lies about macro newlines.
The terminal newline (i.e., before "@end macro") is part of the macro, which
is why so many macros are @r{}@c -- to swallow the newline.

This required a significant mechanical change to get the buffer pointer and
size out of all arguments, as the buffer can now be reallocated.

Modified Files:
--------------
    texi2mdoc:
        extern.h
        main.c
        texi2mdoc.1
        util.c
        version_0_1_2.xml

Revision Data
-------------
Index: texi2mdoc.1
===================================================================
RCS file: /home/cvs/mdocml/texi2mdoc/texi2mdoc.1,v
retrieving revision 1.11
retrieving revision 1.12
diff -Ltexi2mdoc.1 -Ltexi2mdoc.1 -u -p -r1.11 -r1.12
--- texi2mdoc.1
+++ texi2mdoc.1
@@ -108,13 +108,7 @@ The comma in Texinfo macro arguments may
 This is
 .Em not
 supported.
-.Sh BUGS
-Macros in
-.Nm
-are assumed to be self-contained (with matching block and respective
-.Li @end
-pairs).
-In Texinfo, they aren't: they're considered as if typed in place.
+.\" .Sh BUGS
 .Sh SECURITY CONSIDERATIONS
 As a security precaution,
 .Nm
Index: main.c
===================================================================
RCS file: /home/cvs/mdocml/texi2mdoc/main.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -Lmain.c -Lmain.c -u -p -r1.45 -r1.46
--- main.c
+++ main.c
@@ -38,43 +38,43 @@ static	const char *const sects[SECTSZ] =
 	"No",
 };
 
-static	void doaccent(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doblock(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dobracket(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dobye(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dodefindex(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dodefn(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dodisplay(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doend(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doenumerate(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doexample(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doignargn(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doignblock(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doignbracket(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doignline(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doinline(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doinclude(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doitem(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doitemize(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dolink(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void domacro(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void domath(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void domultitable(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doquotation(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dotable(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dotop(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dosecoffs(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dosection(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dosp(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dosubsection(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dosubsubsection(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dosymbol(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dotab(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dotitle(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void dovalue(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doverb(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doverbatim(struct texi *, enum texicmd, const char *, size_t, size_t *);
-static	void doverbinclude(struct texi *, enum texicmd, const char *, size_t, size_t *);
+static	void doaccent(struct texi *, enum texicmd, size_t *);
+static	void doblock(struct texi *, enum texicmd, size_t *);
+static	void dobracket(struct texi *, enum texicmd, size_t *);
+static	void dobye(struct texi *, enum texicmd, size_t *);
+static	void dodefindex(struct texi *, enum texicmd, size_t *);
+static	void dodefn(struct texi *, enum texicmd, size_t *);
+static	void dodisplay(struct texi *, enum texicmd, size_t *);
+static	void doend(struct texi *, enum texicmd, size_t *);
+static	void doenumerate(struct texi *, enum texicmd, size_t *);
+static	void doexample(struct texi *, enum texicmd, size_t *);
+static	void doignargn(struct texi *, enum texicmd, size_t *);
+static	void doignblock(struct texi *, enum texicmd, size_t *);
+static	void doignbracket(struct texi *, enum texicmd, size_t *);
+static	void doignline(struct texi *, enum texicmd, size_t *);
+static	void doinline(struct texi *, enum texicmd, size_t *);
+static	void doinclude(struct texi *, enum texicmd, size_t *);
+static	void doitem(struct texi *, enum texicmd, size_t *);
+static	void doitemize(struct texi *, enum texicmd, size_t *);
+static	void dolink(struct texi *, enum texicmd, size_t *);
+static	void domacro(struct texi *, enum texicmd, size_t *);
+static	void domath(struct texi *, enum texicmd, size_t *);
+static	void domultitable(struct texi *, enum texicmd, size_t *);
+static	void doquotation(struct texi *, enum texicmd, size_t *);
+static	void dotable(struct texi *, enum texicmd, size_t *);
+static	void dotop(struct texi *, enum texicmd, size_t *);
+static	void dosecoffs(struct texi *, enum texicmd, size_t *);
+static	void dosection(struct texi *, enum texicmd, size_t *);
+static	void dosp(struct texi *, enum texicmd, size_t *);
+static	void dosubsection(struct texi *, enum texicmd, size_t *);
+static	void dosubsubsection(struct texi *, enum texicmd, size_t *);
+static	void dosymbol(struct texi *, enum texicmd, size_t *);
+static	void dotab(struct texi *, enum texicmd, size_t *);
+static	void dotitle(struct texi *, enum texicmd, size_t *);
+static	void dovalue(struct texi *, enum texicmd, size_t *);
+static	void doverb(struct texi *, enum texicmd, size_t *);
+static	void doverbatim(struct texi *, enum texicmd, size_t *);
+static	void doverbinclude(struct texi *, enum texicmd, size_t *);
 
 static	const struct texitok __texitoks[TEXICMD__MAX] = {
 	/* TEXICMD__BEGIN */
@@ -342,26 +342,25 @@ static	const struct texitok __texitoks[T
 const	struct texitok *const texitoks = __texitoks;
 
 static void
-dodefindex(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dodefindex(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	size_t	 start, end;
 	char	*cp;
 
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
 
 	start = end = *pos;
-	while (end < sz && ! ismspace(buf[end]))
+	while (end < BUFSZ(p) && ! ismspace(BUF(p)[end]))
 		end++;
 
 	if (start == end) {
-		advanceeoln(p, buf, sz, pos, 1);
+		advanceeoln(p, pos, 1);
 		return;
 	} else if (NULL == (cp = malloc(end - start + 1)))
 		texiabort(p, NULL);
 
-	memcpy(cp, &buf[start], end - start);
+	memcpy(cp, &BUF(p)[start], end - start);
 	cp[end - start] = '\0';
 
 	p->indexs = realloc(p->indexs, 
@@ -373,8 +372,7 @@ dodefindex(struct texi *p, enum texicmd 
 }
 
 static void
-dodefn(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dodefn(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	const char	*blk;
 
@@ -399,8 +397,8 @@ dodefn(struct texi *p, enum texicmd cmd,
 
 	if (p->ign) {
 		NULL != blk ?
-			parseto(p, buf, sz, pos, blk) :
-			parseeoln(p, buf, sz, pos);
+			parseto(p, pos, blk) :
+			parseeoln(p, pos);
 		return;
 	}
 
@@ -429,7 +427,7 @@ dodefn(struct texi *p, enum texicmd cmd,
 		texiputchars(p, "Function");
 		break;
 	default:
-		parselinearg(p, buf, sz, pos);
+		parselinearg(p, pos);
 		break;
 	}
 
@@ -439,7 +437,7 @@ dodefn(struct texi *p, enum texicmd cmd,
 	case (TEXICMD_DEFMAC):
 	case (TEXICMD_DEFMACX):
 		teximacroopen(p, "Dv");
-		while (parselinearg(p, buf, sz, pos)) 
+		while (parselinearg(p, pos)) 
 			/* Spin. */ ;
 		teximacroclose(p);
 		break;
@@ -448,10 +446,10 @@ dodefn(struct texi *p, enum texicmd cmd,
 	case (TEXICMD_DEFUN):
 	case (TEXICMD_DEFUNX):
 		teximacroopen(p, "Fo");
-		parselinearg(p, buf, sz, pos);
+		parselinearg(p, pos);
 		teximacroclose(p);
 		teximacroopen(p, "Fa");
-		while (parselinearg(p, buf, sz, pos)) 
+		while (parselinearg(p, pos)) 
 			/* Spin. */ ;
 		teximacroclose(p);
 		teximacro(p, "Fc");
@@ -463,13 +461,13 @@ dodefn(struct texi *p, enum texicmd cmd,
 	case (TEXICMD_DEFTYPEMETHOD):
 	case (TEXICMD_DEFTYPEMETHODX):
 		teximacroopen(p, "Ft");
-		parselinearg(p, buf, sz, pos);
+		parselinearg(p, pos);
 		teximacroclose(p);
 		teximacroopen(p, "Fo");
-		parselinearg(p, buf, sz, pos);
+		parselinearg(p, pos);
 		teximacroclose(p);
 		teximacroopen(p, "Fa");
-		while (parselinearg(p, buf, sz, pos)) 
+		while (parselinearg(p, pos)) 
 			/* Spin. */ ;
 		teximacroclose(p);
 		teximacro(p, "Fc");
@@ -481,7 +479,7 @@ dodefn(struct texi *p, enum texicmd cmd,
 	case (TEXICMD_DEFTYPEVR):
 	case (TEXICMD_DEFTYPEVRX):
 		teximacroopen(p, "Vt");
-		while (parselinearg(p, buf, sz, pos)) 
+		while (parselinearg(p, pos)) 
 			/* Spin. */ ;
 		teximacroclose(p);
 		break;
@@ -490,7 +488,7 @@ dodefn(struct texi *p, enum texicmd cmd,
 	case (TEXICMD_DEFVR):
 	case (TEXICMD_DEFVRX):
 		teximacroopen(p, "Va");
-		while (parselinearg(p, buf, sz, pos)) 
+		while (parselinearg(p, pos)) 
 			/* Spin. */ ;
 		teximacroclose(p);
 		break;
@@ -500,12 +498,11 @@ dodefn(struct texi *p, enum texicmd cmd,
 
 	texivspace(p);
 	if (NULL != blk)
-		parseto(p, buf, sz, pos, blk);
+		parseto(p, pos, blk);
 }
 
 static void
-domacro(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+domacro(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	size_t		  start, end, endtoksz, len;
 	struct teximacro  m;
@@ -513,42 +510,58 @@ domacro(struct texi *p, enum texicmd cmd
 
 	memset(&m, 0, sizeof(struct teximacro));
 
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
 
-	for (start = end = *pos; end < sz; end++)
-		if (ismspace(buf[end]) || '{' == buf[end])
+	for (start = end = *pos; end < BUFSZ(p); end++)
+		if (ismspace(BUF(p)[end]) || '{' == BUF(p)[end])
 			break;
 
 	if (start == end)
 		texierr(p, "zero-length macro name");
 
-	advanceto(p, buf, pos, end);
+	advanceto(p, pos, end);
 
 	m.key = malloc(end - start + 1);
 	if (NULL == m.key)
 		texiabort(p, NULL);
-	memcpy(m.key, &buf[start], end - start);
+	memcpy(m.key, &BUF(p)[start], end - start);
 	m.key[end - start] = '\0';
 
-	m.args = argparse(p, buf, sz, pos, &m.argsz, 0);
-	advanceeoln(p, buf, sz, pos, 0);
+	m.args = argparse(p, pos, &m.argsz, 0);
 
+	/* Note: we advance to the beginning of the macro. */
+	advanceeoln(p, pos, 1);
+
+	/*
+	 * According to the Texinfo manual, the macro ends on the
+	 * newline subsequent the @end macro.
+	 * That's COMPLETELY FUCKING WRONG.
+	 * It ends inclusive the newline, which is why so many macros
+	 * say things like @r{hello}@c, where the subsequent @c swallows
+	 * the newline.
+	 * However, it does swallow the leading newline, so look for the
+	 * @end macro without the leading newline else we might look
+	 * past empty macros.
+	 */
 	start = *pos;
-	endtok = "\n@end macro\n";
+	endtok = "@end macro\n";
 	endtoksz = strlen(endtok);
-	blk = memmem(&buf[start], sz - start, endtok, endtoksz);
+	blk = memmem(&BUF(p)[start], BUFSZ(p) - start, endtok, endtoksz);
 	if (NULL == blk)
 		texierr(p, "unterminated macro body");
-	while (&buf[*pos] != blk)
-		advance(p, buf, pos);
-	assert('\n' == buf[*pos]);
-	advance(p, buf, pos);
-	len = blk - &buf[start];
+	/* Roll us back one character. */
+	while (&BUF(p)[*pos] != blk)
+		advance(p, pos);
+	assert('@' == BUF(p)[*pos]);
+	if ('\n' != BUF(p)[*pos - 1]) 
+		texierr(p, "cannot handle @end macro in-line");
+
+	len = blk - &BUF(p)[start];
 	m.value = malloc(len + 1);
 	if (NULL == m.value)
 		texiabort(p, NULL);
-	memcpy(m.value, &buf[start], len);
+	memcpy(m.value, &BUF(p)[start], len);
 	m.value[len] = '\0';
 
 	p->macros = realloc
@@ -559,12 +572,11 @@ domacro(struct texi *p, enum texicmd cmd
 		texiabort(p, NULL);
 
 	p->macros[p->macrosz++] = m;
-	advanceeoln(p, buf, sz, pos, 1);
+	advanceeoln(p, pos, 1);
 }
 
 static void
-doignblock(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doignblock(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	char		 end[32], start[32];
 	const char	*endt, *startt;
@@ -599,44 +611,42 @@ doignblock(struct texi *p, enum texicmd 
 	 * then there'll be an "end" token of the same kind between us.
 	 * Thus, we keep track of scopes for matching "end" blocks.
 	 */
-	while (stack > 0 && *pos < sz) {
+	while (stack > 0 && *pos < BUFSZ(p)) {
 		if (stack > 10)
 			abort();
-		endt = memmem(&buf[*pos], sz - *pos, end, esz);
-		startt = memmem(&buf[*pos], sz - *pos, start, ssz);
+		endt = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, end, esz);
+		startt = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, start, ssz);
 		if (NULL == endt) {
 			texiwarn(p, "unterminated \"%s\" "
 				"block", texitoks[cmd].tok);
-			*pos = sz;
+			*pos = BUFSZ(p);
 			break;
 		} 
 
 		newpos = *pos;
 		if (NULL == startt || startt > endt) {
-			newpos += esz + (size_t)(endt - &buf[*pos]);
+			newpos += esz + (size_t)(endt - &BUF(p)[*pos]);
 			stack--;
 		} else {
-			newpos += ssz + (size_t)(startt - &buf[*pos]);
+			newpos += ssz + (size_t)(startt - &BUF(p)[*pos]);
 			stack++;
 		}
 
-		assert(newpos <= sz);
+		assert(newpos <= BUFSZ(p));
 		while (*pos < newpos)
-			advance(p, buf, pos);
+			advance(p, pos);
 	}
 }
 
 static void
-doblock(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doblock(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	
-	parseto(p, buf, sz, pos, texitoks[cmd].tok);
+	parseto(p, pos, texitoks[cmd].tok);
 }
 
 static void
-doinline(struct texi *p, enum texicmd cmd,
-	const char *buf, size_t sz, size_t *pos)
+doinline(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	const char	*macro = NULL;
 
@@ -678,59 +688,57 @@ doinline(struct texi *p, enum texicmd cm
 	}
 
 	if (NULL == macro || p->literal || TEXILIST_TABLE == p->list) {
-		parsebracket(p, buf, sz, pos);
+		parsebracket(p, pos);
 		return;
 	}
 
 	teximacroopen(p, macro);
 	p->seenws = 0;
-	parsebracket(p, buf, sz, pos);
-	texipunctuate(p, buf, sz, pos);
+	parsebracket(p, pos);
+	texipunctuate(p, pos);
 	teximacroclose(p);
 }
 
 static void
-doverb(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doverb(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	char	 delim;
 	size_t	 start;
 
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
-	if (*pos == sz || '{' != buf[*pos])
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
+	if (*pos == BUFSZ(p) || '{' != BUF(p)[*pos])
 		return;
-	advance(p, buf, pos);
-	if (*pos == sz)
+	advance(p, pos);
+	if (*pos == BUFSZ(p))
 		return;
 
-	delim = buf[*pos];
-	advance(p, buf, pos);
+	delim = BUF(p)[*pos];
+	advance(p, pos);
 	/* Make sure we flush out our initial whitespace... */
 	if (p->seenws && p->outcol && 0 == p->literal)
 		texiputchar(p, ' ');
 	p->seenws = 0;
 	start = *pos;
 	/* Read until we see the delimiter then end-brace. */
-	while (*pos < sz - 1) {
-		if (buf[*pos] == delim && buf[*pos + 1] == '}') 
+	while (*pos < BUFSZ(p) - 1) {
+		if (BUF(p)[*pos] == delim && BUF(p)[*pos + 1] == '}') 
 			break;
-		advance(p, buf, pos);
+		advance(p, pos);
 	}
-	if (*pos == sz - 1)
+	if (*pos == BUFSZ(p) - 1)
 		return;
-	texiputbuf(p, buf, start, *pos);
+	texiputbuf(p, start, *pos);
 
 	/* Make sure we read after the end-brace. */
-	assert(delim == buf[*pos]);
-	advance(p, buf, pos);
-	assert('}' == buf[*pos]);
-	advance(p, buf, pos);
+	assert(delim == BUF(p)[*pos]);
+	advance(p, pos);
+	assert('}' == BUF(p)[*pos]);
+	advance(p, pos);
 }
 
 static void
-doverbatim(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doverbatim(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	const char	*end, *term;
 	size_t		 endsz, endpos;
@@ -738,35 +746,34 @@ doverbatim(struct texi *p, enum texicmd 
 	/* We read from the @verbatim\n newline inclusive! */
 	end = "\n@end verbatim\n";
 	endsz = strlen(end);
-	advanceeoln(p, buf, sz, pos, 0);
-	if (*pos == sz) {
+	advanceeoln(p, pos, 0);
+	if (*pos == BUFSZ(p)) {
 		texiwarn(p, "unexpected end of file");
 		return;
 	}
 
-	term = memmem(&buf[*pos], sz - *pos, end, endsz);
+	term = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, end, endsz);
 	if (NULL == term) {
 		texiwarn(p, "unterminated verbatim block");
-		endpos = sz;
+		endpos = BUFSZ(p);
 	} else
-		endpos = *pos + (size_t)(term - &buf[*pos]);
+		endpos = *pos + (size_t)(term - &BUF(p)[*pos]);
 
-	assert(endpos <= sz);
-	assert('\n' == buf[*pos]);
-	advance(p, buf, pos);
+	assert(endpos <= BUFSZ(p));
+	assert('\n' == BUF(p)[*pos]);
+	advance(p, pos);
 	teximacro(p, "Bd -literal -offset indent");
 	while (*pos < endpos) {
-		texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+		texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 	}
 	teximacro(p, "Ed");
-	if (*pos < sz)
-		advanceto(p, buf, pos, endpos + endsz);
+	if (*pos < BUFSZ(p))
+		advanceto(p, pos, endpos + endsz);
 }
 
 static void
-doverbinclude(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doverbinclude(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	char	 	 fname[PATH_MAX], path[PATH_MAX];
 	int	 	 rc;
@@ -774,22 +781,22 @@ doverbinclude(struct texi *p, enum texic
 	const char	*v;
 	enum texicmd	 type;
 
-	while (*pos < sz && ' ' == buf[*pos])
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && ' ' == BUF(p)[*pos])
+		advance(p, pos);
 
-	for (i = 0; *pos < sz && '\n' != buf[*pos]; ) {
+	for (i = 0; *pos < BUFSZ(p) && '\n' != BUF(p)[*pos]; ) {
 		if (i == sizeof(fname) - 1)
 			break;
-		if ('@' != buf[*pos]) {
-			fname[i++] = buf[*pos];
-			advance(p, buf, pos);
+		if ('@' != BUF(p)[*pos]) {
+			fname[i++] = BUF(p)[*pos];
+			advance(p, pos);
 			continue;
 		}
-		type = texicmd(p, buf, *pos, sz, &end, NULL);
-		advanceto(p, buf, pos, end);
+		type = texicmd(p, *pos, &end, NULL);
+		advanceto(p, pos, end);
 		if (TEXICMD_VALUE != type) 
 			texierr(p, "unknown verbatiminclude command");
-		v = valueblookup(p, buf, sz, pos);
+		v = valueblookup(p, pos);
 		if (NULL == v)
 			continue;
 		while ('\0' != *v) {
@@ -803,7 +810,7 @@ doverbinclude(struct texi *p, enum texic
 
 	if (i == 0)
 		texierr(p, "path too short");
-	else if ('\n' != buf[*pos])
+	else if ('\n' != BUF(p)[*pos])
 		texierr(p, "path too long");
 	else if ('/' == fname[0])
 		texierr(p, "no absolute paths");
@@ -823,8 +830,7 @@ doverbinclude(struct texi *p, enum texic
 }
 
 static void
-doinclude(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doinclude(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	char	 	 fname[PATH_MAX], path[PATH_MAX];
 	size_t	 	 i, end;
@@ -832,23 +838,23 @@ doinclude(struct texi *p, enum texicmd c
 	const char	*v;
 	enum texicmd	 type;
 
-	while (*pos < sz && ' ' == buf[*pos])
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && ' ' == BUF(p)[*pos])
+		advance(p, pos);
 
 	/* Read in the filename. */
-	for (i = 0; *pos < sz && '\n' != buf[*pos]; ) {
+	for (i = 0; *pos < BUFSZ(p) && '\n' != BUF(p)[*pos]; ) {
 		if (i == sizeof(fname) - 1)
 			break;
-		if ('@' != buf[*pos]) {
-			fname[i++] = buf[*pos];
-			advance(p, buf, pos);
+		if ('@' != BUF(p)[*pos]) {
+			fname[i++] = BUF(p)[*pos];
+			advance(p, pos);
 			continue;
 		}
-		type = texicmd(p, buf, *pos, sz, &end, NULL);
-		advanceto(p, buf, pos, end);
+		type = texicmd(p, *pos, &end, NULL);
+		advanceto(p, pos, end);
 		if (TEXICMD_VALUE != type) 
 			texierr(p, "unknown include command");
-		v = valueblookup(p, buf, sz, pos);
+		v = valueblookup(p, pos);
 		if (NULL == v)
 			continue;
 		while ('\0' != *v) {
@@ -862,7 +868,7 @@ doinclude(struct texi *p, enum texicmd c
 
 	if (i == 0)
 		texierr(p, "path too short");
-	else if ('\n' != buf[*pos])
+	else if ('\n' != BUF(p)[*pos])
 		texierr(p, "path too long");
 	else if ('/' == fname[0])
 		texierr(p, "no absolute paths");
@@ -889,16 +895,14 @@ doinclude(struct texi *p, enum texicmd c
 }
 
 static void
-dobracket(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dobracket(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
-	parsebracket(p, buf, sz, pos);
+	parsebracket(p, pos);
 }
 
 static void
-dodisplay(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dodisplay(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	switch (cmd) {
@@ -913,28 +917,26 @@ dodisplay(struct texi *p, enum texicmd c
 
 	p->seenvs = 1;
 	/* FIXME: ignore and parseeoln. */
-	advanceeoln(p, buf, sz, pos, 1);
-	parseto(p, buf, sz, pos, texitoks[cmd].tok);
+	advanceeoln(p, pos, 1);
+	parseto(p, pos, texitoks[cmd].tok);
 	teximacro(p, "Ed");
 }
 
 static void
-doexample(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doexample(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	teximacro(p, "Bd -literal -offset indent");
 	/* FIXME: ignore and parseeoln. */
-	advanceeoln(p, buf, sz, pos, 1);
+	advanceeoln(p, pos, 1);
 	p->literal++;
-	parseto(p, buf, sz, pos, texitoks[cmd].tok);
+	parseto(p, pos, texitoks[cmd].tok);
 	p->literal--;
 	teximacro(p, "Ed");
 }
 
 static void
-dobye(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dobye(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	texiexit(p);
@@ -942,32 +944,30 @@ dobye(struct texi *p, enum texicmd cmd, 
 }
 
 static void
-dotitle(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dotitle(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	size_t	 start, end;
 
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
 	start = end = *pos;
-	while (end < sz && '\n' != buf[end])
+	while (end < BUFSZ(p) && '\n' != BUF(p)[end])
 		end++;
-	advanceeoln(p, buf, sz, pos, 1);
+	advanceeoln(p, pos, 1);
 	free(p->subtitle);
 	p->subtitle = malloc(end - start + 1);
 	if (NULL == p->subtitle)
 		texiabort(p, NULL);
-	memcpy(p->subtitle, &buf[start], end - start);
+	memcpy(p->subtitle, &BUF(p)[start], end - start);
 	p->subtitle[end - start] = '\0';
 }
 
 static void
-doaccent(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doaccent(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	int	 brace = 0;
 
-	if (*pos == sz) {
+	if (*pos == BUFSZ(p)) {
 		texiwarn(p, "truncated: @%s", texitoks[cmd].tok);
 		return;
 	}
@@ -985,21 +985,21 @@ doaccent(struct texi *p, enum texicmd cm
 	 * the critical one.
 	 * Otherwise, space can sit between us and our argument.
 	 */
-	if ('{' == buf[*pos]) {
+	if ('{' == BUF(p)[*pos]) {
 		brace = 1;
-		advance(p, buf, pos);
+		advance(p, pos);
 	} else if (isalpha(texitoks[cmd].tok[0])) 
-		while (*pos < sz && isws(buf[*pos]))
-			advance(p, buf, pos);
+		while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+			advance(p, pos);
 
-	if (*pos == sz) {
+	if (*pos == BUFSZ(p)) {
 		texiwarn(p, "truncated: @%s", texitoks[cmd].tok);
 		return;
 	}
 
 	switch (cmd) {
 	case (TEXICMD_ACUTE):
-		switch (buf[*pos]) {
+		switch (BUF(p)[*pos]) {
 		case ('a'): case ('A'):
 		case ('e'): case ('E'):
 		case ('i'): case ('I'):
@@ -1011,19 +1011,19 @@ doaccent(struct texi *p, enum texicmd cm
 			texiwarn(p, "ignoring accent");
 			break;
 		}
-		texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+		texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 		break;
 	case (TEXICMD_CEDILLA):
-		if ('c' == buf[*pos] || 'C' == buf[*pos])
+		if ('c' == BUF(p)[*pos] || 'C' == BUF(p)[*pos])
 			texiputchars(p, "\\(,");
 		else
 			texiwarn(p, "ignoring accent");
-		texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+		texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 		break;
 	case (TEXICMD_CIRCUMFLEX):
-		switch (buf[*pos]) {
+		switch (BUF(p)[*pos]) {
 		case ('a'): case ('A'):
 		case ('e'): case ('E'):
 		case ('i'): case ('I'):
@@ -1035,19 +1035,19 @@ doaccent(struct texi *p, enum texicmd cm
 			texiwarn(p, "ignoring accent");
 			break;
 		}
-		texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+		texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 		break;
 	case (TEXICMD_DOTLESS):
-		if ('i' == buf[*pos] || 'j' == buf[*pos])
+		if ('i' == BUF(p)[*pos] || 'j' == BUF(p)[*pos])
 			texiputchars(p, "\\(.");
 		else
 			texiwarn(p, "ignoring accent");
-		texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+		texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 		break;
 	case (TEXICMD_GRAVE):
-		switch (buf[*pos]) {
+		switch (BUF(p)[*pos]) {
 		case ('a'): case ('A'):
 		case ('e'): case ('E'):
 		case ('i'): case ('I'):
@@ -1059,11 +1059,11 @@ doaccent(struct texi *p, enum texicmd cm
 			texiwarn(p, "ignoring accent");
 			break;
 		}
-		texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+		texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 		break;
 	case (TEXICMD_TILDE):
-		switch (buf[*pos]) {
+		switch (BUF(p)[*pos]) {
 		case ('a'): case ('A'):
 		case ('n'): case ('N'):
 		case ('o'): case ('O'):
@@ -1073,11 +1073,11 @@ doaccent(struct texi *p, enum texicmd cm
 			texiwarn(p, "ignoring accent");
 			break;
 		}
-		texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+		texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 		break;
 	case (TEXICMD_UMLAUT):
-		switch (buf[*pos]) {
+		switch (BUF(p)[*pos]) {
 		case ('a'): case ('A'):
 		case ('e'): case ('E'):
 		case ('i'): case ('I'):
@@ -1090,22 +1090,22 @@ doaccent(struct texi *p, enum texicmd cm
 			texiwarn(p, "ignoring accent");
 			break;
 		}
-		texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+		texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 		break;
 	default:
-		texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+		texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 		break;
 	}
 
 	if (brace) {
-		while (*pos < sz && '}' != buf[*pos]) {
-			texiputchar(p, buf[*pos]);
-			advance(p, buf, pos);
+		while (*pos < BUFSZ(p) && '}' != BUF(p)[*pos]) {
+			texiputchar(p, BUF(p)[*pos]);
+			advance(p, pos);
 		}
-		if (*pos < sz)
-			advance(p, buf, pos);
+		if (*pos < BUFSZ(p))
+			advance(p, pos);
 	} 
 
 	switch (cmd) {
@@ -1121,8 +1121,7 @@ doaccent(struct texi *p, enum texicmd cm
 }
 
 static void
-dosymbol(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dosymbol(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	/* Remember to pad us. */
@@ -1312,22 +1311,20 @@ dosymbol(struct texi *p, enum texicmd cm
 
 	/* Alphabetic commands have braces we ignore. */
 	if (isalpha(texitoks[cmd].tok[0]))
-		doignbracket(p, cmd, buf, sz, pos);
+		doignbracket(p, cmd, pos);
 }
 
 static void
-doquotation(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doquotation(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	
 	teximacro(p, "Qo");
-	parseto(p, buf, sz, pos, "quotation");
+	parseto(p, pos, "quotation");
 	teximacro(p, "Qc");
 }
 
 static void
-domath(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+domath(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	size_t	 nest, start;
 
@@ -1337,102 +1334,91 @@ domath(struct texi *p, enum texicmd cmd,
 	 * terms of @-commands.
 	 * This departs from GNU's rules, but whatever.
 	 */
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
-	if (*pos == sz || '{' != buf[*pos])
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
+	if (*pos == BUFSZ(p) || '{' != BUF(p)[*pos])
 		return;
-	advance(p, buf, pos);
+	advance(p, pos);
 	if (p->seenws && p->outcol && 0 == p->literal)
 		texiputchar(p, ' ');
 	p->seenws = 0;
-	for (nest = 1, start = *pos; *pos < sz && nest > 0; ) {
-		if ('{' == buf[*pos])
+	for (nest = 1, start = *pos; *pos < BUFSZ(p) && nest > 0; ) {
+		if ('{' == BUF(p)[*pos])
 			nest++;
-		else if ('}' == buf[*pos])
+		else if ('}' == BUF(p)[*pos])
 			if (0 == --nest)
 				continue;
-		advance(p, buf, pos);
+		advance(p, pos);
 	}
-	if (*pos == sz)
+	if (*pos == BUFSZ(p))
 		return;
-	assert('}' == buf[*pos]);
-	texiputbuf(p, buf, start, *pos);
-	advance(p, buf, pos);
+	assert('}' == BUF(p)[*pos]);
+	texiputbuf(p, start, *pos);
+	advance(p, pos);
 }
 
 static void
-dovalue(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dovalue(struct texi *p, enum texicmd cmd, size_t *pos)
 {
-	size_t		 start, end, i;
+	size_t		 start, end;
 	char		*key, *val;
 	const char	*cp;
 
 	if (TEXICMD_SET == cmd) {
-		while (*pos < sz && isws(buf[*pos]))
-			advance(p, buf, pos);
-		for (start = end = *pos; end < sz; end++)
-			if (ismspace(buf[end]))
+		while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+			advance(p, pos);
+		for (start = end = *pos; end < BUFSZ(p); end++)
+			if (ismspace(BUF(p)[end]))
 				break;
 		/* We don't allow empty keys. */
 		if (start == end)
 			return;
-		advanceto(p, buf, pos, end);
+		advanceto(p, pos, end);
 
 		key = malloc(end - start + 1);
 		if (NULL == key)
 			texiabort(p, NULL);
-		memcpy(key, &buf[start], end - start);
+		memcpy(key, &BUF(p)[start], end - start);
 		key[end - start] = '\0';
 
-		while (*pos < sz && isws(buf[*pos]))
-			advance(p, buf, pos);
-		for (start = end = *pos; end < sz; end++)
-			if ('\n' == buf[end])
+		while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+			advance(p, pos);
+		for (start = end = *pos; end < BUFSZ(p); end++)
+			if ('\n' == BUF(p)[end])
 				break;
 		/* We do allow empty values. */
-		advanceeoln(p, buf, sz, pos, 1);
+		advanceeoln(p, pos, 1);
 
 		val = malloc(end - start + 1);
 		if (NULL == val)
 			texiabort(p, NULL);
-		memcpy(val, &buf[start], end - start);
+		memcpy(val, &BUF(p)[start], end - start);
 		val[end - start] = '\0';
 		valueadd(p, key, val);
 	} else if (TEXICMD_VALUE == cmd) {
 		if (p->seenws)
 			texiputchar(p, ' ');
 		p->seenws = 0;
-		if (NULL != (cp = valueblookup(p, buf, sz, pos))) {
-			for (i = 0; i < p->valstackpos; i++)
-				if (cp == p->valstack[i])
-					break;
-			if (i < p->valstackpos)
-				texierr(p, "recursive value");
-			if (64 == p->valstackpos) 
-				texierr(p, "too many nested values");
-			p->valstack[p->valstackpos++] = cp;
-			parsemembuf(p, cp, strlen(cp));
-			p->valstackpos--;
-		} else
+		if (NULL != (cp = valueblookup(p, pos)))
+			texisplice(p, cp, strlen(cp), pos);
+		else
 			texiputchars(p, "{No value}");
 	} else if (TEXICMD_IFCLEAR == cmd) {
-		if (NULL != valuellookup(p, buf, sz, pos))
-			doignblock(p, cmd, buf, sz, pos);
+		if (NULL != valuellookup(p, pos))
+			doignblock(p, cmd, pos);
 		else
-			parseto(p, buf, sz, pos, texitoks[cmd].tok);
+			parseto(p, pos, texitoks[cmd].tok);
 	} else if (TEXICMD_IFSET == cmd) {
-		if (NULL == valuellookup(p, buf, sz, pos))
-			doignblock(p, cmd, buf, sz, pos);
+		if (NULL == valuellookup(p, pos))
+			doignblock(p, cmd,  pos);
 		else
-			parseto(p, buf, sz, pos, texitoks[cmd].tok);
+			parseto(p, pos, texitoks[cmd].tok);
 	} else if (TEXICMD_CLEAR == cmd)
-		valuelclear(p, buf, sz, pos);
+		valuelclear(p, pos);
 }
 
 static void
-dolink(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dolink(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	int	 c;
 
@@ -1461,26 +1447,25 @@ dolink(struct texi *p, enum texicmd cmd,
 		abort();
 	}
 
-	c = parsearg(p, buf, sz, pos, 0);
+	c = parsearg(p, pos, 0);
 	p->ign++;
 	while (c > 0)
-		c = parsearg(p, buf, sz, pos, 1);
+		c = parsearg(p, pos, 1);
 	p->ign--;
 
-	texipunctuate(p, buf, sz, pos);
+	texipunctuate(p, pos);
 	teximacroclose(p);
 }
 
 static void
-doignargn(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doignargn(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	int	 c;
 
-	c = parsearg(p, buf, sz, pos, 0);
+	c = parsearg(p, pos, 0);
 	p->ign++;
 	while (c > 0)
-		c = parsearg(p, buf, sz, pos, 1);
+		c = parsearg(p, pos, 1);
 	p->ign--;
 }
 
@@ -1505,8 +1490,7 @@ sectioner(struct texi *p, int sec)
 }
 
 static void
-dosubsubsection(struct texi *p, enum texicmd cmd, 
-		const char *buf, size_t sz, size_t *pos)
+dosubsubsection(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	int	 sec;
 
@@ -1515,14 +1499,13 @@ dosubsubsection(struct texi *p, enum tex
 	/* We don't have a subsubsubsection, so make one up. */
 	texivspace(p);
 	teximacroopen(p, sects[sec]);
-	parseeoln(p, buf, sz, pos);
+	parseeoln(p, pos);
 	teximacroclose(p);
 	texivspace(p);
 }
 
 static void
-dosubsection(struct texi *p, enum texicmd cmd, 
-		const char *buf, size_t sz, size_t *pos)
+dosubsection(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	int	 sec;
 
@@ -1537,15 +1520,14 @@ dosubsection(struct texi *p, enum texicm
 	if (sec > 1)
 		texivspace(p);
 	teximacroopen(p, sects[sec]);
-	parseeoln(p, buf, sz, pos);
+	parseeoln(p, pos);
 	teximacroclose(p);
 	if (sec > 1)
 		texivspace(p);
 }
 
 static void
-dosecoffs(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dosecoffs(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	if (TEXICMD_RAISESECTIONS == cmd)
@@ -1555,8 +1537,7 @@ dosecoffs(struct texi *p, enum texicmd c
 }
 
 static void
-dosection(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dosection(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	int		 sec;
 
@@ -1583,14 +1564,13 @@ dosection(struct texi *p, enum texicmd c
 		texierr(p, "\"%s\" in a literal scope!?", sects[sec]);
 
 	teximacroopen(p, sects[sec]);
-	parseeoln(p, buf, sz, pos);
+	parseeoln(p, pos);
 	teximacroclose(p);
 	p->seenvs = 1;
 }
 
 static void
-dosp(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dosp(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	if (p->literal)
@@ -1598,19 +1578,18 @@ dosp(struct texi *p, enum texicmd cmd, 
 	else
 		texivspace(p);
 	/* FIXME: ignore and parseeoln. */
-	advanceeoln(p, buf, sz, pos, 1);
+	advanceeoln(p, pos, 1);
 }
 
 static void
-dotop(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dotop(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	const char	*cp;
 	time_t		 t;
 	char		 date[32];
 
 	if (--p->ign)
-		texierr(p, "@top command while ignoring (%d)", p->ign);
+		texierr(p, "@top command while ignoring");
 
 	/*
 	 * Here we print our standard mdoc(7) prologue.
@@ -1644,12 +1623,11 @@ dotop(struct texi *p, enum texicmd cmd, 
 		texiputchars(p, "Unknown description");
 	teximacroclose(p);
 	p->seenvs = 1;
-	dosection(p, cmd, buf, sz, pos);
+	dosection(p, cmd, pos);
 }
 
 static void
-doitem(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doitem(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	/* Multitable is using raw tbl(7). */
@@ -1677,7 +1655,7 @@ doitem(struct texi *p, enum texicmd cmd,
 
 	/* Trick so we don't start with Pp. */
 	p->seenvs = 1;
-	parseeoln(p, buf, sz, pos);
+	parseeoln(p, pos);
 
 	if (TEXILIST_ITEM == p->list)
 		teximacroclose(p);
@@ -1686,8 +1664,7 @@ doitem(struct texi *p, enum texicmd cmd,
 }
 
 static void
-dotab(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dotab(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	/* This command is only useful in @multitable. */
@@ -1696,8 +1673,7 @@ dotab(struct texi *p, enum texicmd cmd, 
 }
 
 static void
-domultitable(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+domultitable(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	enum texilist	sv = p->list;
 	int		svliteral = p->literal;
@@ -1714,29 +1690,29 @@ domultitable(struct texi *p, enum texicm
 	columns = 0;
 
 	/* Advance to the first argument... */
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
 
 	/* Make sure we don't print anything when scanning. */
 	p->ign++;
-	if ('@' == buf[*pos]) {
+	if ('@' == BUF(p)[*pos]) {
 		/* 
 		 * Look for @columnfractions.
 		 * We ignore these, but we do use the number of
 		 * arguments to set the number of columns that we'll
 		 * have.
 		 */
-		type = texicmd(p, buf, *pos, sz, &end, NULL);
-		advanceto(p, buf, pos, end);
+		type = texicmd(p, *pos, &end, NULL);
+		advanceto(p, pos, end);
 		if (TEXICMD_COLUMNFRACTIONS != type) 
 			texierr(p, "unknown multitable command");
-		while (*pos < sz && '\n' != buf[*pos]) {
-			while (*pos < sz && isws(buf[*pos]))
-				advance(p, buf, pos);
-			while (*pos < sz && ! isws(buf[*pos])) {
-				if ('\n' == buf[*pos])
+		while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) {
+			while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+				advance(p, pos);
+			while (*pos < BUFSZ(p) && ! isws(BUF(p)[*pos])) {
+				if ('\n' == BUF(p)[*pos])
 					break;
-				advance(p, buf, pos);
+				advance(p, pos);
 			}
 			columns++;
 		}
@@ -1747,7 +1723,7 @@ domultitable(struct texi *p, enum texicm
 		 * tbl(7) figure it out.
 		 * So use this only to count arguments.
 		 */
-		while (parselinearg(p, buf, sz, pos) > 0)
+		while (parselinearg(p, pos) > 0)
 			columns++;
 	p->ign--;
 
@@ -1759,7 +1735,7 @@ domultitable(struct texi *p, enum texicm
 	}
 	texiputchars(p, ".\n");
 	p->outmacro++;
-	parseto(p, buf, sz, pos, texitoks[cmd].tok);
+	parseto(p, pos, texitoks[cmd].tok);
 	p->outmacro--;
 	teximacro(p, "TE");
 	p->literal = svliteral;
@@ -1767,40 +1743,37 @@ domultitable(struct texi *p, enum texicm
 }
 
 static void
-dotable(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+dotable(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	enum texilist	sv = p->list;
 
 	p->list = TEXILIST_ITEM;
 	teximacro(p, "Bl -tag -width Ds");
 	/* FIXME: ignore and parseeoln. */
-	advanceeoln(p, buf, sz, pos, 1);
+	advanceeoln(p, pos, 1);
 	p->seenvs = 1;
-	parseto(p, buf, sz, pos, texitoks[cmd].tok);
+	parseto(p, pos, texitoks[cmd].tok);
 	teximacro(p, "El");
 	p->list = sv;
 }
 
 static void
-doend(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doend(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	size_t	 start;
 
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
 	start = *pos;
-	while (*pos < sz && '\n' != buf[*pos])
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos])
+		advance(p, pos);
 
-	texiwarn(p, "unexpected \"end\": %.*s", (int)(*pos - start), &buf[start]);
-	advanceeoln(p, buf, sz, pos, 1);
+	texiwarn(p, "unexpected \"end\": %.*s", (int)(*pos - start), &BUF(p)[start]);
+	advanceeoln(p, pos, 1);
 }
 
 static void
-doenumerate(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doenumerate(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	enum texilist	 sv = p->list;
 
@@ -1808,15 +1781,14 @@ doenumerate(struct texi *p, enum texicmd
 	teximacro(p, "Bl -enum");
 	p->seenvs = 1;
 	/* FIXME: ignore and parseeoln. */
-	advanceeoln(p, buf, sz, pos, 1);
-	parseto(p, buf, sz, pos, "enumerate");
+	advanceeoln(p, pos, 1);
+	parseto(p, pos, "enumerate");
 	teximacro(p, "El");
 	p->list = sv;
 }
 
 static void
-doitemize(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doitemize(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 	enum texilist	sv = p->list;
 
@@ -1824,29 +1796,27 @@ doitemize(struct texi *p, enum texicmd c
 	teximacro(p, "Bl -bullet");
 	p->seenvs = 1;
 	/* FIXME: ignore and parseeoln. */
-	advanceeoln(p, buf, sz, pos, 1);
-	parseto(p, buf, sz, pos, "itemize");
+	advanceeoln(p, pos, 1);
+	parseto(p, pos, "itemize");
 	teximacro(p, "El");
 	p->list = sv;
 }
 
 static void
-doignbracket(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doignbracket(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	p->ign++;
-	parsebracket(p, buf, sz, pos);
+	parsebracket(p, pos);
 	p->ign--;
 }
 
 static void
-doignline(struct texi *p, enum texicmd cmd, 
-	const char *buf, size_t sz, size_t *pos)
+doignline(struct texi *p, enum texicmd cmd, size_t *pos)
 {
 
 	/* FIXME: ignore and parseeoln. */
-	advanceeoln(p, buf, sz, pos, 1);
+	advanceeoln(p,  pos, 1);
 }
 
 /*
Index: extern.h
===================================================================
RCS file: /home/cvs/mdocml/texi2mdoc/extern.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -Lextern.h -Lextern.h -u -p -r1.14 -r1.15
--- extern.h
+++ extern.h
@@ -298,8 +298,9 @@ struct	texifile {
 	const char	*name; /* name of the file */
 	size_t	  	 line; /* current line (from zero) */
 	size_t	  	 col; /* current column in line (from zero) */
-	char		*map; /* mmap'd file OR allocated buffer */
-	size_t		 mapsz; /* size of mmap */
+	char		*map; /* allocated file buffer */
+	size_t		 mapsz; /* size of map */
+	size_t		 mapmaxsz; /* full size of map */
 };
 
 struct	texi;
@@ -307,8 +308,7 @@ struct	texi;
 /*
  * Callback for functions implementing texi commands.
  */
-typedef	void (*texicmdfp)(struct texi *, 
-	enum texicmd, const char *, size_t, size_t *);
+typedef	void (*texicmdfp)(struct texi *, enum texicmd, size_t *);
 
 /*
  * Describes Texinfo commands, whether native or overriden.
@@ -383,6 +383,9 @@ struct	texi {
 	int		  literal; /* if >0, literal context */
 };
 
+#define	BUF(_p) ((_p)->files[(_p)->filepos - 1].map)
+#define	BUFSZ(_p) ((_p)->files[(_p)->filepos - 1].mapsz)
+
 #define	isws(_x) \
 	(' ' == (_x) || '\t' == (_x))
 #define	ismspace(_x) \
@@ -390,27 +393,24 @@ struct	texi {
 
 __BEGIN_DECLS
 
-void	advance(struct texi *, const char *, size_t *);
-size_t	advanceeoln(struct texi *, const char *, size_t, size_t *, int);
-void	advanceto(struct texi *, const char *, size_t *, size_t);
+void	advance(struct texi *, size_t *);
+size_t	advanceeoln(struct texi *, size_t *, int);
+void	advanceto(struct texi *, size_t *, size_t);
 
-char  **argparse(struct texi *, const char *, size_t, size_t *, size_t *, size_t);
+char  **argparse(struct texi *, size_t *, size_t *, size_t);
 
-int	parsearg(struct texi *, const char *, size_t, size_t *, size_t);
-void	parsebracket(struct texi *, const char *, size_t, size_t *);
+int	parsearg(struct texi *, size_t *, size_t);
+void	parsebracket(struct texi *, size_t *);
 void	parsestdin(struct texi *);
 void	parsefile(struct texi *, const char *, int);
-int	parselinearg(struct texi *, const char *, size_t, size_t *);
-void	parseeof(struct texi *, const char *, size_t);
-void	parsemembuf(struct texi *, const char *, size_t);
-void	parseeoln(struct texi *, const char *, size_t, size_t *);
-void	parsesingle(struct texi *, const char *, size_t, size_t *);
-void	parseto(struct texi *, const char *, size_t, size_t *, const char *);
+int	parselinearg(struct texi *, size_t *);
+void	parseeoln(struct texi *, size_t *);
+void	parseto(struct texi *, size_t *, const char *);
 
 void	texiabort(struct texi *, const char *)
 		__attribute__((noreturn));
 enum texicmd
-	texicmd(struct texi *, const char *, size_t, size_t, 
+	texicmd(struct texi *, size_t, 
 		size_t *, struct teximacro **);
 void	texierr(struct texi *, const char *, ...)
 		__attribute__((format(printf, 2, 3)))
@@ -420,20 +420,21 @@ void	texifilepop(struct texi *);
 void	teximacro(struct texi *, const char *);
 void	teximacroclose(struct texi *);
 void	teximacroopen(struct texi *, const char *);
-void 	texipunctuate(struct texi *, const char *, size_t, size_t *);
-void	texiputbuf(struct texi *p, const char *, size_t, size_t);
+void 	texipunctuate(struct texi *, size_t *);
+void	texiputbuf(struct texi *p, size_t, size_t);
 void	texiputchar(struct texi *p, char);
 void	texiputchars(struct texi *, const char *);
 void	texivspace(struct texi *);
 void	texiwarn(const struct texi *, const char *, ...)
 		__attribute__((format(printf, 2, 3)));
+void	texisplice(struct texi *, const char *, size_t, size_t *);
 
 void	valueadd(struct texi *, char *, char *);
 const char *
-	valueblookup(struct texi *, const char *, size_t, size_t *);
-void	valuelclear(struct texi *, const char *, size_t, size_t *);
+	valueblookup(struct texi *, size_t *);
+void	valuelclear(struct texi *, size_t *);
 const char *
-	valuellookup(struct texi *, const char *, size_t, size_t *);
+	valuellookup(struct texi *, size_t *);
 
 extern	const struct texitok *const texitoks;
 
Index: util.c
===================================================================
RCS file: /home/cvs/mdocml/texi2mdoc/util.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -Lutil.c -Lutil.c -u -p -r1.13 -r1.14
--- util.c
+++ util.c
@@ -43,10 +43,7 @@ texifilepop(struct texi *p)
 
 	assert(p->filepos > 0);
 	f = &p->files[--p->filepos];
-	if (TEXISRC_FILE == f->type)
-		munmap(f->map, f->mapsz);
-	else
-		free(f->map);
+	free(f->map);
 }
 
 static void
@@ -206,16 +203,14 @@ texiputchars(struct texi *p, const char 
 /*
  * This puts all characters onto the output stream but makes sure to
  * escape mdoc(7) slashes.
+ * FIXME: useless.
  */
 void
-texiputbuf(struct texi *p, const char *buf, size_t start, size_t end)
+texiputbuf(struct texi *p, size_t start, size_t end)
 {
 
-	for ( ; start < end; start++) {
-		texiputchar(p, buf[start]);
-		if ('\\' == buf[start])
-			texiputchar(p, 'e');
-	}
+	for ( ; start < end; start++)
+		texiputchar(p, BUF(p)[start]);
 }
 
 /*
@@ -309,10 +304,10 @@ texivspace(struct texi *p)
  * in the current input file.
  */
 void
-advance(struct texi *p, const char *buf, size_t *pos)
+advance(struct texi *p, size_t *pos)
 {
 
-	if ('\n' == buf[*pos]) {
+	if ('\n' == BUF(p)[*pos]) {
 		p->files[p->filepos - 1].line++;
 		p->files[p->filepos - 1].col = 0;
 	} else
@@ -329,15 +324,15 @@ advance(struct texi *p, const char *buf,
  * appropriately flush-left punctuation alongside the macro.
  */
 void
-texipunctuate(struct texi *p, const char *buf, size_t sz, size_t *pos)
+texipunctuate(struct texi *p, size_t *pos)
 {
 	size_t	 start, end;
 
 	if (1 != p->outmacro)
 		return;
 
-	for (start = end = *pos; end < sz; end++) {
-		switch (buf[end]) {
+	for (start = end = *pos; end < BUFSZ(p); end++) {
+		switch (BUF(p)[end]) {
 		case (','):
 		case (')'):
 		case ('.'):
@@ -353,11 +348,12 @@ texipunctuate(struct texi *p, const char
 	}
 	if (end == *pos)
 		return;
-	if (end + 1 == sz || ' ' == buf[end] || '\n' == buf[end]) {
+	if (end + 1 == BUFSZ(p) || ' ' == BUF(p)[end] || 
+		'\n' == BUF(p)[end]) {
 		for ( ; start < end; start++) {
 			texiputchar(p, ' ');
-			texiputchar(p, buf[start]);
-			advance(p, buf, pos);
+			texiputchar(p, BUF(p)[start]);
+			advance(p, pos);
 		}
 	}
 }
@@ -368,27 +364,27 @@ texipunctuate(struct texi *p, const char
  * doing so.
  */
 static size_t
-advancenext(struct texi *p, const char *buf, size_t sz, size_t *pos)
+advancenext(struct texi *p, size_t *pos)
 {
 	
 	if (p->literal) {
-		while (*pos < sz && ismspace(buf[*pos])) {
-			texiputchar(p, buf[*pos]);
-			advance(p, buf, pos);
+		while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) {
+			texiputchar(p, BUF(p)[*pos]);
+			advance(p, pos);
 		}
 		return(*pos);
 	} 
 
-	while (*pos < sz && ismspace(buf[*pos])) {
+	while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) {
 		p->seenws = 1;
 		/* 
 		 * If it looks like we've printed a double-line, then
 		 * output a paragraph.
 		 * FIXME: this is stupid.
 		 */
-		if (*pos && '\n' == buf[*pos] && '\n' == buf[*pos - 1])
+		if (*pos && '\n' == BUF(p)[*pos] && '\n' == BUF(p)[*pos - 1])
 			texivspace(p);
-		advance(p, buf, pos);
+		advance(p, pos);
 	}
 	return(*pos);
 }
@@ -399,14 +395,13 @@ advancenext(struct texi *p, const char *
  * the @\n.
  */
 size_t
-advanceeoln(struct texi *p, const char *buf, 
-	size_t sz, size_t *pos, int consumenl)
+advanceeoln(struct texi *p, size_t *pos, int consumenl)
 {
 
-	while (*pos < sz && '\n' != buf[*pos])
-		advance(p, buf, pos);
-	if (*pos < sz && consumenl)
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos])
+		advance(p, pos);
+	if (*pos < BUFSZ(p) && consumenl)
+		advance(p, pos);
 	return(*pos);
 }
 
@@ -415,17 +410,16 @@ advanceeoln(struct texi *p, const char *
  * current buffer greater than or equal to the current position.
  */
 void
-advanceto(struct texi *p, const char *buf, size_t *pos, size_t end)
+advanceto(struct texi *p, size_t *pos, size_t end)
 {
 
 	assert(*pos <= end);
 	while (*pos < end) 
-		advance(p, buf, pos);
+		advance(p, pos);
 }
 
 static void
-texiexecmacro(struct texi *p, struct teximacro *m,
-	const char *buf, size_t sz, size_t *pos)
+texiexecmacro(struct texi *p, struct teximacro *m, size_t *pos)
 {
 	size_t		  valsz, realsz, aasz, asz, 
 			   ssz, i, j, k, start, end;
@@ -433,13 +427,13 @@ texiexecmacro(struct texi *p, struct tex
 	char		**args;
 	const char	 *cp;
 
-	args = argparse(p, buf, sz, pos, &asz, m->argsz);
+	args = argparse(p, pos, &asz, m->argsz);
 	if (asz != m->argsz)
 		texiwarn(p, "invalid macro argument length");
 	aasz = asz < m->argsz ? asz : m->argsz;
 
 	if (0 == aasz) {
-		parsemembuf(p, m->value, strlen(m->value));
+		texisplice(p, m->value, strlen(m->value), pos);
 		return;
 	}
 
@@ -482,15 +476,10 @@ texiexecmacro(struct texi *p, struct tex
 
 		/* 
 		 * Argument didn't exist in argument table. 
-		 * No need to reallocate here: we just copy the text
-		 * directly from the macro value into the buffer.
+		 * Just ignore it.
 		 */
 		if (k == aasz) {
-			for ( ; i < end; i++)
-				val[j++] = m->value[i];
-			assert('\\' == m->value[i]);
-			val[j++] = m->value[i];
-			val[j] = '\0';
+			i = end;
 			continue;
 		}
 
@@ -508,7 +497,7 @@ texiexecmacro(struct texi *p, struct tex
 		i = end;
 	}
 
-	parsemembuf(p, val, strlen(val));
+	texisplice(p, val, strlen(val), pos);
 
 	for (i = 0; i < asz; i++)
 		free(args[i]);
@@ -522,8 +511,7 @@ texiexecmacro(struct texi *p, struct tex
  * This also will advance the input stream.
  */
 static void
-texiword(struct texi *p, const char *buf, 
-	size_t sz, size_t *pos, char extra)
+parseword(struct texi *p, size_t *pos, char extra)
 {
 
 	if (p->seenws && 0 == p->outmacro && 
@@ -535,28 +523,28 @@ texiword(struct texi *p, const char *buf
 
 	p->seenws = 0;
 
-	while (*pos < sz && ! ismspace(buf[*pos])) {
-		switch (buf[*pos]) {
+	while (*pos < BUFSZ(p) && ! ismspace(BUF(p)[*pos])) {
+		switch (BUF(p)[*pos]) {
 		case ('@'):
 		case ('}'):
 		case ('{'):
 			return;
 		}
-		if ('\0' != extra && buf[*pos] == extra)
+		if ('\0' != extra && BUF(p)[*pos] == extra)
 			return;
-		if (*pos < sz - 1 && 
-			 '`' == buf[*pos] && 
-			 '`' == buf[*pos + 1]) {
+		if (*pos < BUFSZ(p) - 1 && 
+			 '`' == BUF(p)[*pos] && 
+			 '`' == BUF(p)[*pos + 1]) {
 			texiputchars(p, "\\(lq");
-			advance(p, buf, pos);
-		} else if (*pos < sz - 1 && 
-			 '\'' == buf[*pos] && 
-			 '\'' == buf[*pos + 1]) {
+			advance(p, pos);
+		} else if (*pos < BUFSZ(p) - 1 && 
+			 '\'' == BUF(p)[*pos] && 
+			 '\'' == BUF(p)[*pos + 1]) {
 			texiputchars(p, "\\(rq");
-			advance(p, buf, pos);
+			advance(p, pos);
 		} else
-			texiputchar(p, buf[*pos]);
-		advance(p, buf, pos);
+			texiputchar(p, BUF(p)[*pos]);
+		advance(p, pos);
 	}
 }
 
@@ -566,39 +554,38 @@ texiword(struct texi *p, const char *buf
  * index after the command name.
  */
 enum texicmd
-texicmd(struct texi *p, const char *buf, size_t pos, 
-	size_t sz, size_t *end, struct teximacro **macro)
+texicmd(struct texi *p, size_t pos, size_t *end, struct teximacro **macro)
 {
 	size_t	 i, len, toksz;
 
-	assert('@' == buf[pos]);
+	assert('@' == BUF(p)[pos]);
 
 	if (NULL != macro)
 		*macro = NULL;
 
-	if ((*end = pos) == sz)
+	if ((*end = pos) == BUFSZ(p))
 		return(TEXICMD__MAX);
-	else if ((*end = ++pos) == sz)
+	else if ((*end = ++pos) == BUFSZ(p))
 		return(TEXICMD__MAX);
 
 	/* Alphabetic commands are special. */
-	if ( ! isalpha(buf[pos])) {
-		if ((*end = pos + 1) == sz)
+	if ( ! isalpha(BUF(p)[pos])) {
+		if ((*end = pos + 1) == BUFSZ(p))
 			return(TEXICMD__MAX);
 		for (i = 0; i < TEXICMD__MAX; i++) {
 			if (1 != texitoks[i].len)
 				continue;
-			if (0 == strncmp(texitoks[i].tok, &buf[pos], 1))
+			if (0 == strncmp(texitoks[i].tok, &BUF(p)[pos], 1))
 				return(i);
 		}
-		texiwarn(p, "bad command: @%c", buf[pos]);
+		texiwarn(p, "bad command: @%c", BUF(p)[pos]);
 		return(TEXICMD__MAX);
 	}
 
 	/* Scan to the end of the possible command name. */
-	for (*end = pos; *end < sz && ! ismspace(buf[*end]); (*end)++)
-		if ((*end > pos && ('@' == buf[*end] || 
-			  '{' == buf[*end] || '}' == buf[*end])))
+	for (*end = pos; *end < BUFSZ(p) && ! ismspace(BUF(p)[*end]); (*end)++)
+		if ((*end > pos && ('@' == BUF(p)[*end] || 
+			  '{' == BUF(p)[*end] || '}' == BUF(p)[*end])))
 			break;
 
 	/* Look for the command. */
@@ -606,7 +593,7 @@ texicmd(struct texi *p, const char *buf,
 	for (i = 0; i < TEXICMD__MAX; i++) {
 		if (len != texitoks[i].len)
 			continue;
-		if (0 == strncmp(texitoks[i].tok, &buf[pos], len))
+		if (0 == strncmp(texitoks[i].tok, &BUF(p)[pos], len))
 			return(i);
 	}
 
@@ -615,23 +602,23 @@ texicmd(struct texi *p, const char *buf,
 		toksz = strlen(p->indexs[i]);
 		if (len != 5 + toksz)
 			continue;
-		if (strncmp(&buf[pos], p->indexs[i], toksz))
+		if (strncmp(&BUF(p)[pos], p->indexs[i], toksz))
 			continue;
-		if (0 == strncmp(&buf[pos + toksz], "index", 5))
+		if (0 == strncmp(&BUF(p)[pos + toksz], "index", 5))
 			return(TEXICMD_USER_INDEX);
 	}
 
 	for (i = 0; i < p->macrosz; i++) {
 		if (len != strlen(p->macros[i].key))
 			continue;
-		if (strncmp(&buf[pos], p->macros[i].key, len))
+		if (strncmp(&BUF(p)[pos], p->macros[i].key, len))
 			continue;
 		if (NULL != macro)
 			*macro = &p->macros[i];
 		return(TEXICMD__MAX);
 	}
 
-	texiwarn(p, "bad command: @%.*s", (int)len, &buf[pos]);
+	texiwarn(p, "bad command: @%.*s", (int)len, &BUF(p)[pos]);
 	return(TEXICMD__MAX);
 }
 
@@ -644,48 +631,47 @@ texicmd(struct texi *p, const char *buf,
  * bracket for the zeroth parse.
  */
 int
-parsearg(struct texi *p, const char *buf, 
-	size_t sz, size_t *pos, size_t num)
+parsearg(struct texi *p, size_t *pos, size_t num)
 {
 	size_t		  end;
 	enum texicmd	  cmd;
 	struct teximacro *macro;
 
-	while (*pos < sz && ismspace(buf[*pos]))
-		advance(p, buf, pos);
-	if (*pos == sz || (0 == num && '{' != buf[*pos]))
+	while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos]))
+		advance(p, pos);
+	if (*pos == BUFSZ(p) || (0 == num && '{' != BUF(p)[*pos]))
 		return(0);
 	if (0 == num)
-		advance(p, buf, pos);
+		advance(p, pos);
 
-	while ((*pos = advancenext(p, buf, sz, pos)) < sz) {
-		switch (buf[*pos]) {
+	while ((*pos = advancenext(p, pos)) < BUFSZ(p)) {
+		switch (BUF(p)[*pos]) {
 		case (','):
-			advance(p, buf, pos);
+			advance(p, pos);
 			return(1);
 		case ('}'):
-			advance(p, buf, pos);
+			advance(p, pos);
 			return(0);
 		case ('{'):
 			if (0 == p->ign)
 				texiwarn(p, "unexpected \"{\"");
-			advance(p, buf, pos);
+			advance(p, pos);
 			continue;
 		case ('@'):
 			break;
 		default:
-			texiword(p, buf, sz, pos, ',');
+			parseword(p, pos, ',');
 			continue;
 		}
 
-		cmd = texicmd(p, buf, *pos, sz, &end, &macro);
-		advanceto(p, buf, pos, end);
+		cmd = texicmd(p, *pos, &end, &macro);
+		advanceto(p, pos, end);
 		if (NULL != macro)
-			texiexecmacro(p, macro, buf, sz, pos);
+			texiexecmacro(p, macro, pos);
 		if (TEXICMD__MAX == cmd) 
 			continue;
 		if (NULL != texitoks[cmd].fp)
-			(*texitoks[cmd].fp)(p, cmd, buf, sz, pos);
+			(*texitoks[cmd].fp)(p, cmd, pos);
 	}
 	return(0);
 }
@@ -695,44 +681,44 @@ parsearg(struct texi *p, const char *buf
  * This will stop in the event of EOF or if we're not at a bracket.
  */
 void
-parsebracket(struct texi *p, const char *buf, size_t sz, size_t *pos)
+parsebracket(struct texi *p, size_t *pos)
 {
 	size_t		  end;
 	enum texicmd	  cmd;
 	struct teximacro *macro;
 
-	while (*pos < sz && ismspace(buf[*pos]))
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos]))
+		advance(p, pos);
 
-	if (*pos == sz || '{' != buf[*pos])
+	if (*pos == BUFSZ(p) || '{' != BUF(p)[*pos])
 		return;
-	advance(p, buf, pos);
+	advance(p, pos);
 
-	while ((*pos = advancenext(p, buf, sz, pos)) < sz) {
-		switch (buf[*pos]) {
+	while ((*pos = advancenext(p, pos)) < BUFSZ(p)) {
+		switch (BUF(p)[*pos]) {
 		case ('}'):
-			advance(p, buf, pos);
+			advance(p, pos);
 			return;
 		case ('{'):
 			if (0 == p->ign)
 				texiwarn(p, "unexpected \"{\"");
-			advance(p, buf, pos);
+			advance(p, pos);
 			continue;
 		case ('@'):
 			break;
 		default:
-			texiword(p, buf, sz, pos, '\0');
+			parseword(p, pos, '\0');
 			continue;
 		}
 
-		cmd = texicmd(p, buf, *pos, sz, &end, &macro);
-		advanceto(p, buf, pos, end);
+		cmd = texicmd(p, *pos, &end, &macro);
+		advanceto(p, pos, end);
 		if (NULL != macro)
-			texiexecmacro(p, macro, buf, sz, pos);
+			texiexecmacro(p, macro, pos);
 		if (TEXICMD__MAX == cmd) 
 			continue;
 		if (NULL != texitoks[cmd].fp)
-			(*texitoks[cmd].fp)(p, cmd, buf, sz, pos);
+			(*texitoks[cmd].fp)(p, cmd, pos);
 	}
 }
 
@@ -742,88 +728,91 @@ parsebracket(struct texi *p, const char 
  * the way.
  */
 void
-parseeoln(struct texi *p, const char *buf, size_t sz, size_t *pos)
+parseeoln(struct texi *p, size_t *pos)
 {
 	size_t		  end;
 	enum texicmd	  cmd;
 	struct teximacro *macro;
 
-	while (*pos < sz && '\n' != buf[*pos]) {
-		while (*pos < sz && isws(buf[*pos])) {
+	while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) {
+		while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) {
 			p->seenws = 1;
 			if (p->literal)
-				texiputchar(p, buf[*pos]);
-			advance(p, buf, pos);
+				texiputchar(p, BUF(p)[*pos]);
+			advance(p, pos);
 		}
-		switch (buf[*pos]) {
+		switch (BUF(p)[*pos]) {
 		case ('}'):
 			if (0 == p->ign)
 				texiwarn(p, "unexpected \"}\"");
-			advance(p, buf, pos);
+			advance(p, pos);
 			continue;
 		case ('{'):
 			if (0 == p->ign)
 				texiwarn(p, "unexpected \"{\"");
-			advance(p, buf, pos);
+			advance(p, pos);
 			continue;
 		case ('@'):
 			break;
 		default:
-			texiword(p, buf, sz, pos, '\0');
+			parseword(p, pos, '\0');
 			continue;
 		}
 
-		cmd = texicmd(p, buf, *pos, sz, &end, &macro);
-		advanceto(p, buf, pos, end);
+		cmd = texicmd(p, *pos, &end, &macro);
+		advanceto(p, pos, end);
 		if (NULL != macro)
-			texiexecmacro(p, macro, buf, sz, pos);
+			texiexecmacro(p, macro, pos);
 		if (TEXICMD__MAX == cmd) 
 			continue;
 		if (NULL != texitoks[cmd].fp)
-			(*texitoks[cmd].fp)(p, cmd, buf, sz, pos);
+			(*texitoks[cmd].fp)(p, cmd, pos);
 	}
+
+	if (*pos < BUFSZ(p) && '\n' == BUF(p)[*pos])
+		advance(p, pos);
 }
 
 /*
  * Parse a single word or command.
  * This will return immediately at the EOF.
  */
-void
-parsesingle(struct texi *p, const char *buf, size_t sz, size_t *pos)
+static void
+parsesingle(struct texi *p, size_t *pos)
 {
 	size_t		  end;
 	enum texicmd	  cmd;
 	struct teximacro *macro;
 
-	if ((*pos = advancenext(p, buf, sz, pos)) >= sz)
+	if ((*pos = advancenext(p, pos)) >= BUFSZ(p))
 		return;
 
-	switch (buf[*pos]) {
+	switch (BUF(p)[*pos]) {
 	case ('}'):
 		if (0 == p->ign)
 			texiwarn(p, "unexpected \"}\"");
-		advance(p, buf, pos);
+		advance(p, pos);
 		return;
 	case ('{'):
 		if (0 == p->ign)
 			texiwarn(p, "unexpected \"{\"");
-		advance(p, buf, pos);
+		advance(p, pos);
 		return;
 	case ('@'):
 		break;
 	default:
-		texiword(p, buf, sz, pos, '\0');
+		parseword(p, pos, '\0');
 		return;
 	}
 
-	cmd = texicmd(p, buf, *pos, sz, &end, &macro);
-	advanceto(p, buf, pos, end);
+	cmd = texicmd(p, *pos, &end, &macro);
+	advanceto(p, pos, end);
 	if (NULL != macro)
-		texiexecmacro(p, macro, buf, sz, pos);
+		texiexecmacro(p, macro, pos);
 	if (TEXICMD__MAX == cmd) 
 		return;
 	if (NULL != texitoks[cmd].fp)
-		(*texitoks[cmd].fp)(p, cmd, buf, sz, pos);
+		(*texitoks[cmd].fp)(p, cmd, pos);
 }
 
 /*
@@ -835,18 +824,18 @@ parsesingle(struct texi *p, const char *
  * line or 1 otherwise.
  */
 int
-parselinearg(struct texi *p, const char *buf, size_t sz, size_t *pos)
+parselinearg(struct texi *p, size_t *pos)
 {
 
-	while (*pos < sz && isws(buf[*pos])) {
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) {
 		p->seenws = 1;
-		advance(p, buf, pos);
+		advance(p, pos);
 	}
 
-	if (*pos < sz && '{' == buf[*pos])
-		parsebracket(p, buf, sz, pos);
-	else if (*pos < sz && '\n' != buf[*pos])
-		parsesingle(p, buf, sz, pos);
+	if (*pos < BUFSZ(p) && '{' == BUF(p)[*pos])
+		parsebracket(p, pos);
+	else if (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos])
+		parsesingle(p, pos);
 	else
 		return(0);
 
@@ -856,41 +845,35 @@ parselinearg(struct texi *p, const char 
 /*
  * Parse til the end of the buffer.
  */
-void
-parseeof(struct texi *p, const char *buf, size_t sz)
+static void
+parseeof(struct texi *p)
 {
 	size_t	 pos;
 
-	for (pos = 0; pos < sz; ) 
-		parsesingle(p, buf, sz, &pos);
+	for (pos = 0; pos < BUFSZ(p); ) 
+		parsesingle(p, &pos);
 }
 
-/*
- * This is like parseeof() except that it's to be invoked on memory
- * buffers while parsing a larger scope.
- * This is useful for parsing macro sequences.
- * The line, column, and name of the calling file context are saved, the
- * column and line reset, then all of these restored after parse.
- */
 void
-parsemembuf(struct texi *p, const char *buf, size_t sz)
+texisplice(struct texi *p, const char *buf, size_t sz, size_t *pos)
 {
-	size_t	 	 svln, svcol;
-	const char	*svname;
-
-	svln = p->files[p->filepos - 1].line;
-	svcol = p->files[p->filepos - 1].col;
-	svname = p->files[p->filepos - 1].name;
+	char		*cp;
+	struct texifile	*f;
 
-	p->files[p->filepos - 1].line = 0;
-	p->files[p->filepos - 1].col = 0;
-	p->files[p->filepos - 1].name = "<macro buffer>";
+	assert(p->filepos > 0);
+	f = &p->files[p->filepos - 1];
 
-	parseeof(p, buf, sz);
+	if (f->mapsz + sz > f->mapmaxsz) {
+		f->mapmaxsz = f->mapsz + sz + 1024;
+		cp = realloc(f->map, f->mapmaxsz);
+		if (NULL == cp)
+			texiabort(p, NULL);
+		f->map = cp;
+	}
 
-	p->files[p->filepos - 1].line = svln;
-	p->files[p->filepos - 1].col = svcol;
-	p->files[p->filepos - 1].name = svname;
+	memmove(f->map + *pos + sz, f->map + *pos, f->mapsz - *pos);
+	memcpy(f->map + *pos, buf, sz);
+	f->mapsz += sz;
 }
 
 /*
@@ -899,8 +882,7 @@ parsemembuf(struct texi *p, const char *
  * This will return immediately at EOF.
  */
 void
-parseto(struct texi *p, const char *buf, 
-	size_t sz, size_t *pos, const char *endtoken)
+parseto(struct texi *p, size_t *pos, const char *endtoken)
 {
 	size_t		  end;
 	enum texicmd	  cmd;
@@ -910,50 +892,50 @@ parseto(struct texi *p, const char *buf,
 	endtoksz = strlen(endtoken);
 	assert(endtoksz > 0);
 	
-	while ((*pos = advancenext(p, buf, sz, pos)) < sz) {
-		switch (buf[*pos]) {
+	while ((*pos = advancenext(p, pos)) < BUFSZ(p)) {
+		switch (BUF(p)[*pos]) {
 		case ('}'):
 			if (0 == p->ign)
 				texiwarn(p, "unexpected \"}\"");
-			advance(p, buf, pos);
+			advance(p, pos);
 			continue;
 		case ('{'):
 			if (0 == p->ign)
 				texiwarn(p, "unexpected \"{\"");
-			advance(p, buf, pos);
+			advance(p, pos);
 			continue;
 		case ('@'):
 			break;
 		default:
-			texiword(p, buf, sz, pos, '\0');
+			parseword(p, pos, '\0');
 			continue;
 		}
 
-		cmd = texicmd(p, buf, *pos, sz, &end, &macro);
-		advanceto(p, buf, pos, end);
+		cmd = texicmd(p, *pos, &end, &macro);
+		advanceto(p, pos, end);
 		if (TEXICMD_END == cmd) {
-			while (*pos < sz && isws(buf[*pos]))
-				advance(p, buf, pos);
+			while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+				advance(p, pos);
 			/* 
 			 * FIXME: check the full word, not just its
 			 * initial substring!
 			 */
-			if (sz - *pos >= endtoksz && 0 == strncmp
-				 (&buf[*pos], endtoken, endtoksz)) {
-				advanceeoln(p, buf, sz, pos, 0);
+			if (BUFSZ(p) - *pos >= endtoksz && 0 == strncmp
+				 (&BUF(p)[*pos], endtoken, endtoksz)) {
+				advanceeoln(p, pos, 0);
 				break;
 			}
 			if (0 == p->ign)
 				texiwarn(p, "unexpected \"end\"");
-			advanceeoln(p, buf, sz, pos, 0);
+			advanceeoln(p, pos, 0);
 			continue;
 		} 
 		if (NULL != macro)
-			texiexecmacro(p, macro, buf, sz, pos);
+			texiexecmacro(p, macro, pos);
 		if (TEXICMD__MAX == cmd) 
 			continue;
 		if (NULL != texitoks[cmd].fp) 
-			(*texitoks[cmd].fp)(p, cmd, buf, sz, pos);
+			(*texitoks[cmd].fp)(p, cmd, pos);
 	}
 }
 
@@ -965,7 +947,6 @@ void
 parsestdin(struct texi *p)
 {
 	struct texifile	*f;
-	size_t		 off;
 	ssize_t		 ssz;
 
 	assert(0 == p->filepos);
@@ -975,18 +956,18 @@ parsestdin(struct texi *p)
 	f->type = TEXISRC_STDIN;
 	f->name = "<stdin>";
 
-	for (off = 0; ; off += (size_t)ssz) {
-		if (off == f->mapsz) {
-			if (f->mapsz == (1U << 31))
+	for (f->mapsz = 0; ; f->mapsz += (size_t)ssz) {
+		if (f->mapsz == f->mapmaxsz) {
+			if (f->mapmaxsz == (1U << 31))
 				texierr(p, "stdin buffer too long");
-			f->mapsz = f->mapsz > 65536 / 2 ? 
-				2 * f->mapsz : 65536;
-			f->map = realloc(f->map, f->mapsz);
+			f->mapmaxsz = f->mapmaxsz > 65536 / 2 ? 
+				2 * f->mapmaxsz : 65536;
+			f->map = realloc(f->map, f->mapmaxsz);
 			if (NULL == f->map) 
 				texiabort(p, NULL);
 		}
-		ssz = read(STDIN_FILENO, 
-			f->map + (int)off, f->mapsz - off);
+		ssz = read(STDIN_FILENO, f->map + 
+			(int)f->mapsz, f->mapmaxsz - f->mapsz);
 		if (0 == ssz)
 			break;
 		else if (-1 == ssz) 
@@ -994,7 +975,7 @@ parsestdin(struct texi *p)
 	}
 
 	p->filepos++;
-	parseeof(p, f->map, off);
+	parseeof(p);
 	texifilepop(p);
 }
 
@@ -1011,6 +992,7 @@ parsefile(struct texi *p, const char *fn
 	int		 fd;
 	struct stat	 st;
 	size_t		 i;
+	char		*map;
 
 	if (64 == p->filepos) 
 		texierr(p, "too many open files");
@@ -1026,22 +1008,28 @@ parsefile(struct texi *p, const char *fn
 		texiabort(p, fname);
 	} 
 
-	f->mapsz = st.st_size;
-	f->map = mmap(NULL, f->mapsz,
+	f->mapsz = f->mapmaxsz = st.st_size;
+	map = mmap(NULL, f->mapsz,
 		PROT_READ, MAP_SHARED, fd, 0);
 	close(fd);
 
-	if (MAP_FAILED == f->map)
+	if (MAP_FAILED == map)
 		texiabort(p, fname);
 
-	p->filepos++;
 	if ( ! parse) {
 		for (i = 0; i < f->mapsz; i++)
-			texiputchar(p, f->map[i]);
+			texiputchar(p, map[i]);
 		if (p->outcol)
 			texiputchar(p, '\n');
-	} else
-		parseeof(p, f->map, f->mapsz);
+		munmap(map, f->mapsz);
+		return;
+	}
+
+	p->filepos++;
+	f->map = malloc(f->mapsz);
+	memcpy(f->map, map, f->mapsz);
+	munmap(map, f->mapsz);
+	parseeof(p);
 	texifilepop(p);
 }
 
@@ -1053,8 +1041,7 @@ parsefile(struct texi *p, const char *fn
  * The pointer can point to NULL if the value has been unset.
  */
 static char **
-valuequery(const struct texi *p, 
-	const char *buf, size_t start, size_t end)
+valuequery(const struct texi *p, size_t start, size_t end)
 {
 	size_t	 i, sz, len;
 
@@ -1066,7 +1053,7 @@ valuequery(const struct texi *p, 
 		sz = strlen(p->vals[i].key);
 		if (sz != len)
 			continue;
-		if (0 == strncmp(p->vals[i].key, &buf[start], len))
+		if (0 == strncmp(p->vals[i].key, &BUF(p)[start], len))
 			return(&p->vals[i].value);
 	}
 	return(NULL);
@@ -1077,45 +1064,45 @@ valuequery(const struct texi *p, 
  * pointer to its value via valuequery().
  */
 static char **
-valuelquery(struct texi *p, const char *buf, size_t sz, size_t *pos)
+valuelquery(struct texi *p, size_t *pos)
 {
 	size_t	  start, end;
 	char	**ret;
 
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
-	if (*pos == sz)
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
+	if (*pos == BUFSZ(p))
 		return(NULL);
-	for (start = end = *pos; end < sz; end++)
-		if ('\n' == buf[end])
+	for (start = end = *pos; end < BUFSZ(p); end++)
+		if ('\n' == BUF(p)[end])
 			break;
-	advanceto(p, buf, pos, end);
-	if (*pos < sz) {
-		assert('\n' == buf[*pos]);
-		advance(p, buf, pos);
+	advanceto(p, pos, end);
+	if (*pos < BUFSZ(p)) {
+		assert('\n' == BUF(p)[*pos]);
+		advance(p, pos);
 	}
-	if (NULL == (ret = valuequery(p, buf, start, end)))
+	if (NULL == (ret = valuequery(p, start, end)))
 		return(NULL);
 	return(ret);
 }
 
 void
-valuelclear(struct texi *p, const char *buf, size_t sz, size_t *pos)
+valuelclear(struct texi *p, size_t *pos)
 {
 	char	**ret;
 
-	if (NULL == (ret = valuelquery(p, buf, sz, pos)))
+	if (NULL == (ret = valuelquery(p, pos)))
 		return;
 	free(*ret);
 	*ret = NULL;
 }
 
 const char *
-valuellookup(struct texi *p, const char *buf, size_t sz, size_t *pos)
+valuellookup(struct texi *p, size_t *pos)
 {
 	char	**ret;
 
-	if (NULL == (ret = valuelquery(p, buf, sz, pos)))
+	if (NULL == (ret = valuelquery(p, pos)))
 		return(NULL);
 	return(*ret);
 }
@@ -1128,25 +1115,25 @@ valuellookup(struct texi *p, const char 
  * value had previously been unset.
  */
 const char *
-valueblookup(struct texi *p, const char *buf, size_t sz, size_t *pos)
+valueblookup(struct texi *p, size_t *pos)
 {
 	size_t	  start, end;
 	char	**ret;
 
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
-	if (*pos == sz || '{' != buf[*pos])
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
+	if (*pos == BUFSZ(p) || '{' != BUF(p)[*pos])
 		return(NULL);
-	advance(p, buf, pos);
-	for (start = end = *pos; end < sz; end++)
-		if ('}' == buf[end])
+	advance(p, pos);
+	for (start = end = *pos; end < BUFSZ(p); end++)
+		if ('}' == BUF(p)[end])
 			break;
-	advanceto(p, buf, pos, end);
-	if (*pos < sz) {
-		assert('}' == buf[*pos]);
-		advance(p, buf, pos);
+	advanceto(p, pos, end);
+	if (*pos < BUFSZ(p)) {
+		assert('}' == BUF(p)[*pos]);
+		advance(p, pos);
 	}
-	if (NULL == (ret = valuequery(p, buf, start, end)))
+	if (NULL == (ret = valuequery(p, start, end)))
 		return(NULL);
 	return(*ret);
 }
@@ -1190,19 +1177,18 @@ valueadd(struct texi *p, char *key, char
  * Ergo, textual: this doesn't interpret the arguments in any way.
  */
 char **
-argparse(struct texi *p, const char *buf, 
-	size_t sz, size_t *pos, size_t *argsz, size_t hint)
+argparse(struct texi *p, size_t *pos, size_t *argsz, size_t hint)
 {
 	char	**args;
 	size_t	  start, end, stack;
 
-	while (*pos < sz && isws(buf[*pos]))
-		advance(p, buf, pos);
+	while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+		advance(p, pos);
 
 	args = NULL;
 	*argsz = 0;
 
-	if ('{' != buf[*pos] && hint) {
+	if ('{' != BUF(p)[*pos] && hint) {
 		/*
 		 * Special case: if we encounter an unbracketed argument
 		 * and we're being invoked with non-zero arguments
@@ -1214,51 +1200,51 @@ argparse(struct texi *p, const char *buf
 		if (NULL == args)
 			texiabort(p, NULL);
 		start = *pos;
-		while (*pos < sz) {
-			if ('\n' == buf[*pos])
+		while (*pos < BUFSZ(p)) {
+			if ('\n' == BUF(p)[*pos])
 				break;
-			advance(p, buf, pos);
+			advance(p, pos);
 		}
 		args[0] = malloc(*pos - start + 1);
-		memcpy(args[0], &buf[start], *pos - start);
+		memcpy(args[0], &BUF(p)[start], *pos - start);
 		args[0][*pos - start] = '\0';
-		if (*pos < sz && '\n' == buf[*pos])
-			advance(p, buf, pos);
+		if (*pos < BUFSZ(p) && '\n' == BUF(p)[*pos])
+			advance(p, pos);
 		return(args);
-	} else if ('{' != buf[*pos])
+	} else if ('{' != BUF(p)[*pos])
 		return(args);
 
 	/* Parse til the closing '}', putting into the array. */
-	advance(p, buf, pos);
-	while (*pos < sz) {
-		while (*pos < sz && isws(buf[*pos]))
-			advance(p, buf, pos);
+	advance(p, pos);
+	while (*pos < BUFSZ(p)) {
+		while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
+			advance(p, pos);
 		start = *pos;
 		stack = 0;
-		while (*pos < sz) {
+		while (*pos < BUFSZ(p)) {
 			/* 
 			 * According to the manual, commas within
 			 * embedded commands are escaped.
 			 * We keep track of embedded-ness in the "stack"
 			 * state anyway, so this is free.
 			 */
-			if (',' == buf[*pos] && 0 == stack && 1 != hint)
+			if (',' == BUF(p)[*pos] && 0 == stack && 1 != hint)
 				break;
-			else if (0 == stack && '}' == buf[*pos])
+			else if (0 == stack && '}' == BUF(p)[*pos])
 				break;
-			else if (0 != stack && '}' == buf[*pos])
+			else if (0 != stack && '}' == BUF(p)[*pos])
 				stack--;
-			else if ('{' == buf[*pos])
+			else if ('{' == BUF(p)[*pos])
 				stack++;
-			advance(p, buf, pos);
+			advance(p, pos);
 		}
 		if (stack)
 			texiwarn(p, "unterminated macro "
 				"in macro arguments");
-		if ((end = *pos) == sz)
+		if ((end = *pos) == BUFSZ(p))
 			break;
 		/* Test for zero-length '{  }'. */
-		if (start == end && '}' == buf[*pos] && 0 == *argsz)
+		if (start == end && '}' == BUF(p)[*pos] && 0 == *argsz)
 			break;
 		/* FIXME: use reallocarray. */
 		args = realloc
@@ -1270,17 +1256,17 @@ argparse(struct texi *p, const char *buf
 		if (NULL == args[*argsz])
 			texiabort(p, NULL);
 		memcpy(args[*argsz],
-			&buf[start], end - start);
+			&BUF(p)[start], end - start);
 		args[*argsz][end - start] = '\0';
 		(*argsz)++;
-		if ('}' == buf[*pos])
+		if ('}' == BUF(p)[*pos])
 			break;
-		advance(p, buf, pos);
+		advance(p, pos);
 	}
 
-	if (*pos == sz) 
+	if (*pos == BUFSZ(p)) 
 		texierr(p, "unterminated arguments");
-	assert('}' == buf[*pos]);
-	advance(p, buf, pos);
+	assert('}' == BUF(p)[*pos]);
+	advance(p, pos);
 	return(args);
 }
Index: version_0_1_2.xml
===================================================================
RCS file: /home/cvs/mdocml/texi2mdoc/version_0_1_2.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lversion_0_1_2.xml -Lversion_0_1_2.xml -u -p -r1.2 -r1.3
--- version_0_1_2.xml
+++ version_0_1_2.xml
@@ -9,5 +9,6 @@
 		Added a few macros for viewing <a href="https://gmplib.org/">GMP</a> manuals.
 		Also allow reading from standard input (instead of always from a file).
 		Consolidate mdoc(7)-escaping of opaque output.
+		Let conditionally-ignored text (e.g., <code>@ifset</code>) allow for nested conditionals as stipulate in the Texinfo manual.
 	</aside>
 </article>
--
 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:[~2015-02-25 14:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-25 14:37 texi2mdoc: Completely re-write @value and @macro handling to work kristaps

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).