shithub: neatroff

Download patch

ref: 4d4dea5a36a677716b56d800e86f4ba4df60327b
parent: 87294120003bbc48e7ffb50566c46c9b22285cf3
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sun Jun 9 16:37:37 EDT 2013

roff: rename xroff.{h,c} to roff.{h,c}

--- a/Makefile
+++ b/Makefile
@@ -2,10 +2,10 @@
 CFLAGS = -Wall -O2 -DTROFFROOT=\"/root/troff/home\"
 LDFLAGS =
 
-all: xroff
-%.o: %.c xroff.h
+all: roff
+%.o: %.c roff.h
 	$(CC) -c $(CFLAGS) $<
-xroff: xroff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o sbuf.o adj.o eval.o draw.o wb.o hyph.o
+roff: roff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o sbuf.o adj.o eval.o draw.o wb.o hyph.o
 	$(CC) -o $@ $^ $(LDFLAGS)
 clean:
-	rm -f *.o xroff
+	rm -f *.o roff
--- a/adj.c
+++ b/adj.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 #define ADJ_LLEN(a)	MAX(0, (a)->ll - ((a)->lt >= 0 ? (a)->lt : (a)->li))
 
--- a/cp.c
+++ b/cp.c
@@ -1,6 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include "xroff.h"
+#include "roff.h"
 
 #define CPBUF		4
 
--- a/dev.c
+++ b/dev.c
@@ -2,7 +2,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 char dev_dir[PATHLEN];	/* device directory */
 int dev_res;		/* device resolution */
--- a/draw.c
+++ b/draw.c
@@ -1,7 +1,7 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 static char *ln_s;
 
--- a/eval.c
+++ b/eval.c
@@ -1,7 +1,7 @@
 #include <ctype.h>
 #include <stdio.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 #define SCHAR	"icpPvmnu"	/* scale indicators */
 
--- a/font.c
+++ b/font.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 static void skipline(FILE* filp)
 {
--- a/hyph.c
+++ b/hyph.c
@@ -1,7 +1,7 @@
 #include <ctype.h>
 #include <string.h>
 #include <stdio.h>
-#include "xroff.h"
+#include "roff.h"
 
 #define HYEXLEN		(1 << 17)	/* hyphenation exception list length */
 #define HYEXWLEN	128		/* hyphenation exception word length */
--- a/in.c
+++ b/in.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 struct inbuf {
 	char path[64];		/* for file buffers */
--- a/out.c
+++ b/out.c
@@ -3,7 +3,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 static int out_nl = 1;
 
--- a/reg.c
+++ b/reg.c
@@ -3,7 +3,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include "xroff.h"
+#include "roff.h"
 
 #define NREGS		(1 << 16)
 #define NENVS		(1 << 5)
--- a/ren.c
+++ b/ren.c
@@ -2,7 +2,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 #define cadj		env_adj()		/* line buffer */
 
--- /dev/null
+++ b/roff.c
@@ -1,0 +1,60 @@
+/*
+ * neatroff troff clone
+ *
+ * Copyright (C) 2012-2013 Ali Gholami Rudi <ali at rudi dot ir>
+ *
+ * This program is released under the modified BSD license.
+ */
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "roff.h"
+
+static void g_init(void)
+{
+	n_o = SC_IN;
+	n_p = SC_IN * 11;
+}
+
+static void compile(void)
+{
+	out("s%d\n", n_s);
+	out("f%d\n", n_f);
+	render();
+	out("V%d\n", n_p);
+}
+
+void errmsg(char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+	char path[PATHLEN];
+	dev_open(TROFFROOT "/font/devutf");
+	env_init();
+	tr_init();
+	g_init();
+	for (i = 1; i < argc; i++) {
+		if (argv[i][0] != '-' || !argv[i][0])
+			break;
+		if (argv[i][1] == 'm') {
+			sprintf(path, TROFFROOT "/tmac/tmac.%s", argv[i] + 2);
+			in_queue(path);
+		}
+	}
+	if (i == argc)
+		in_queue(NULL);	/* reading from standard input */
+	for (; i < argc; i++)
+		in_queue(!strcmp("-", argv[i]) ? NULL : argv[i]);
+	str_set(REG('.', 'P'), TROFFROOT);
+	compile();
+	env_free();
+	dev_close();
+	return 0;
+}
--- /dev/null
+++ b/roff.h
@@ -1,0 +1,322 @@
+/* converting scales */
+#define SC_IN		(dev_res)	/* inch in units */
+#define SC_PT		(SC_IN / 72)	/* point in units */
+#define SC_EM		(n_s * SC_IN / 72)
+#define SC_DW		(SC_EM / 3)	/* default width */
+#define SC_HT		(n_s * SC_PT)	/* character height */
+
+/* predefined array limits */
+#define PATHLEN		1024	/* path length */
+#define NFILES		16	/* number of input files */
+#define NFONTS		32	/* number of fonts */
+#define FNLEN		32	/* font name length */
+#define NGLYPHS		512	/* glyphs in fonts */
+#define GNLEN		32	/* glyph name length */
+#define ILNLEN		256	/* line limit of input files */
+#define LNLEN		4000	/* line buffer length (ren.c/out.c) */
+#define NWORDS		256	/* number of words in line buffer */
+#define NARGS		9	/* number of macro arguments */
+#define RLEN		4	/* register/macro name */
+#define NPREV		16	/* environment stack depth */
+#define NTRAPS		1024	/* number of traps per page */
+#define NIES		128	/* number of nested .ie commands */
+#define NTABS		16	/* number of tab stops */
+#define NFIELDS		32	/* number of fields */
+#define MAXFRAC		100000	/* maximum value of the fractional part */
+
+/* escape sequences */
+#define ESC_Q	"bCDhHlLNoSvwxX"	/* quoted escape sequences */
+#define ESC_P	"*fgkns"		/* 1 or 2-char escape sequences */
+
+#define MIN(a, b)	((a) < (b) ? (a) : (b))
+#define MAX(a, b)	((a) < (b) ? (b) : (a))
+#define LEN(a)		(sizeof(a) / sizeof((a)[0]))
+
+/* special characters */
+extern int c_ec;	/* escape character (\) */
+extern int c_cc;	/* basic control character (.) */
+extern int c_c2;	/* no-break control character (') */
+#define c_ni	4	/* non-interpreted copy mode escape */
+#define c_hc	env_hc()/* hyphenation character */
+
+/* number registers */
+int num_get(int id, int inc);
+void num_set(int id, int val);
+void num_inc(int id, int val);
+void num_del(int id);
+char *num_str(int id);
+int *nreg(int id);
+int eval(char *s, int unit);
+int eval_up(char **s, int unit);
+int eval_re(char *s, int orig, int unit);
+
+/* string registers */
+void str_set(int id, char *s);
+void str_dset(int id, void *d);
+char *str_get(int id);
+void *str_dget(int id);
+void str_rm(int id);
+void str_rn(int src, int dst);
+
+/* saving and restoring registers before and after printing diverted lines */
+void odiv_beg(void);
+void odiv_end(void);
+
+/* enviroments */
+void env_init(void);
+void env_free(void);
+struct adj *env_adj(void);
+char *env_hc(void);
+int tab_next(int pos);
+
+/* device related variables */
+extern int dev_res;
+extern int dev_uwid;
+extern int dev_hor;
+extern int dev_ver;
+
+struct glyph {
+	char name[FNLEN];	/* name of the glyph */
+	char id[FNLEN];		/* device-dependent glyph identifier */
+	struct font *font;	/* glyph font */
+	int wid;		/* character width */
+	int type;		/* character type; ascender/descender */
+};
+
+struct font {
+	char name[FNLEN];
+	struct glyph glyphs[NGLYPHS];
+	int nglyphs;
+	int spacewid;
+	int special;
+	char c[NGLYPHS][FNLEN];		/* character names in charset */
+	struct glyph *g[NGLYPHS];	/* character glyphs in charset */
+	int n;				/* number of characters in charset */
+};
+
+/* output device functions */
+int dev_open(char *path);
+void dev_close(void);
+int dev_mnt(int pos, char *id, char *name);
+int dev_font(char *id);
+int charwid(int wid, int sz);
+
+/* font-related functions */
+struct font *font_open(char *path);
+void font_close(struct font *fn);
+struct glyph *font_glyph(struct font *fn, char *id);
+struct glyph *font_find(struct font *fn, char *name);
+
+/* glyph handling functions */
+struct glyph *dev_glyph(char *c, int fn);
+struct glyph *dev_glyph_byid(char *id, int fn);
+int dev_spacewid(void);
+
+/* different layers of neatroff */
+int in_next(void);		/* input layer */
+int cp_next(void);		/* copy-mode layer */
+int tr_next(void);		/* troff layer */
+
+void in_push(char *s, char **args);
+void in_pushnl(char *s, char **args);
+void in_so(char *path);		/* .so request */
+void in_nx(char *path);		/* .nx request */
+void in_ex(void);		/* .nx request */
+void in_queue(char *path);	/* .ex request */
+char *in_arg(int i);		/* look up argument */
+int in_nargs(void);		/* number of arguments */
+void in_back(int c);		/* push back input character */
+int in_top(void);		/* the first pushed-back character */
+char *in_filename(void);	/* current filename */
+
+void cp_blk(int skip);		/* skip or read the next line or block */
+void cp_wid(int enable);	/* control inlining \w requests */
+#define cp_back		in_back	/* cp.c is stateless */
+void tr_first(void);		/* read until the first non-command line */
+
+/* variable length string buffer */
+struct sbuf {
+	char *s;
+	int sz;
+	int n;
+};
+
+void sbuf_init(struct sbuf *sbuf);
+void sbuf_done(struct sbuf *sbuf);
+char *sbuf_buf(struct sbuf *sbuf);
+void sbuf_add(struct sbuf *sbuf, int c);
+void sbuf_append(struct sbuf *sbuf, char *s);
+void sbuf_printf(struct sbuf *sbuf, char *s, ...);
+void sbuf_putnl(struct sbuf *sbuf);
+int sbuf_empty(struct sbuf *sbuf);
+
+/* word buffer */
+struct wb {
+	struct sbuf sbuf;
+	int f, s;		/* the last output font and size */
+	int r_f, r_s;		/* current font and size; use n_f and n_s if -1 */
+	int part;		/* partial input (\c) */
+	int els_neg, els_pos;	/* extra line spacing */
+	int h, v;		/* buffer vertical and horizontal positions */
+	int ct, sb, st;		/* \w registers */
+};
+
+void wb_init(struct wb *wb);
+void wb_done(struct wb *wb);
+void wb_hmov(struct wb *wb, int n);
+void wb_vmov(struct wb *wb, int n);
+void wb_els(struct wb *wb, int els);
+void wb_etc(struct wb *wb, char *x);
+void wb_put(struct wb *wb, char *c);
+int wb_part(struct wb *wb);
+void wb_setpart(struct wb *wb);
+void wb_drawl(struct wb *wb, int h, int v);
+void wb_drawc(struct wb *wb, int r);
+void wb_drawe(struct wb *wb, int h, int v);
+void wb_drawa(struct wb *wb, int h1, int v1, int h2, int v2);
+void wb_drawxbeg(struct wb *wb, int c);
+void wb_drawxdot(struct wb *wb, int h, int v);
+void wb_drawxend(struct wb *wb);
+void wb_cat(struct wb *wb, struct wb *src);
+int wb_hyph(struct wb *wb, int w, struct wb *w1, struct wb *w2, int flg);
+int wb_wid(struct wb *wb);
+int wb_empty(struct wb *wb);
+void wb_wconf(struct wb *wb, int *ct, int *st, int *sb);
+
+/* hyphenation flags */
+#define HY_MASK		0x0f	/* enable hyphenation */
+#define HY_LAST		0x02	/* do not hyphenate last lines */
+#define HY_FINAL	0x04	/* do not hyphenate the final character */
+#define HY_FIRSTTWO	0x08	/* do not hyphenate the first two characters */
+#define HY_ANY		0x10	/* break at any possible position */
+
+void hyphenate(char *hyphs, char *word);
+
+/* adjustment */
+#define AD_L		0
+#define AD_B		1
+#define AD_C		3
+#define AD_R		5
+
+struct adj *adj_alloc(void);
+void adj_free(struct adj *adj);
+int adj_fill(struct adj *adj, int ad_b, int fill, int hyph, struct sbuf *dst,
+		int *ll, int *in, int *ti, int *els_neg, int *els_pos);
+int adj_full(struct adj *adj, int fill);
+int adj_empty(struct adj *adj, int fill);
+int adj_wid(struct adj *adj);
+void adj_swid(struct adj *adj, int swid);
+void adj_ll(struct adj *adj, int ll);
+void adj_in(struct adj *adj, int in);
+void adj_ti(struct adj *adj, int ti);
+void adj_wb(struct adj *adj, struct wb *wb);
+void adj_nl(struct adj *adj);
+void adj_sp(struct adj *adj);
+void adj_nonl(struct adj *adj);
+
+/* rendering */
+void render(void);				/* the main loop */
+void ren_char(struct wb *wb, int (*next)(void), void (*back)(int));
+int ren_wid(int (*next)(void), void (*back)(int));
+void ren_tl(int (*next)(void), void (*back)(int));
+void out_line(char *s);				/* output rendered line */
+int out_readc(char **s, char *d);		/* read request or glyph */
+void out(char *s, ...);				/* output troff cmd */
+void ren_hline(struct wb *wb, char *arg);	/* horizontal line */
+void ren_vline(struct wb *wb, char *arg);	/* vertical line */
+void ren_bracket(struct wb *wb, char *arg);	/* \b */
+void ren_over(struct wb *wb, char *arg);	/* \o */
+void ren_draw(struct wb *wb, char *arg);	/* \D */
+
+/* troff commands */
+void tr_bp(char **args);
+void tr_br(char **args);
+void tr_ce(char **args);
+void tr_ch(char **args);
+void tr_di(char **args);
+void tr_divbeg(char **args);
+void tr_divend(char **args);
+void tr_dt(char **args);
+void tr_em(char **args);
+void tr_ev(char **args);
+void tr_fc(char **args);
+void tr_fi(char **args);
+void tr_fp(char **args);
+void tr_ft(char **args);
+void tr_hw(char **args);
+void tr_in(char **args);
+void tr_ll(char **args);
+void tr_mk(char **args);
+void tr_ne(char **args);
+void tr_nf(char **args);
+void tr_ns(char **args);
+void tr_os(char **args);
+void tr_pn(char **args);
+void tr_ps(char **args);
+void tr_rs(char **args);
+void tr_rt(char **args);
+void tr_sp(char **args);
+void tr_sv(char **args);
+void tr_ta(char **args);
+void tr_ti(char **args);
+void tr_wh(char **args);
+void tr_eject(char **args);
+
+void tr_init(void);
+
+/* helpers */
+void errmsg(char *msg, ...);
+int utf8len(int c);
+int utf8read(char **s, char *d);
+void schar_read(char *d, int (*next)(void));
+int schar_jump(char *d, int (*next)(void), void (*back)(int));
+
+/* internal commands */
+#define TR_DIVBEG	"\07<"	/* diversion begins */
+#define TR_DIVEND	"\07>"	/* diversion ends */
+#define TR_EJECT	"\07P"	/* page eject */
+
+/* builtin number registers; n_X for .X register */
+#define REG(c1, c2)	((c1) * 256 + (c2))
+#define n_a		(*nreg(REG('.', 'a')))
+#define n_d		(*nreg(REG('.', 'd')))
+#define n_f		(*nreg(REG('.', 'f')))
+#define n_h		(*nreg(REG('.', 'h')))
+#define n_i		(*nreg(REG('.', 'i')))
+#define n_j		(*nreg(REG('.', 'j')))
+#define n_l		(*nreg(REG('.', 'l')))
+#define n_L		(*nreg(REG('.', 'L')))
+#define n_n		(*nreg(REG('.', 'n')))
+#define n_o		(*nreg(REG('.', 'o')))
+#define n_p		(*nreg(REG('.', 'p')))
+#define n_s		(*nreg(REG('.', 's')))
+#define n_u		(*nreg(REG('.', 'u')))
+#define n_v		(*nreg(REG('.', 'v')))
+#define n_ct		(*nreg(REG('c', 't')))
+#define n_dl		(*nreg(REG('d', 'l')))
+#define n_dn		(*nreg(REG('d', 'n')))
+#define n_nl		(*nreg(REG('n', 'l')))
+#define n_sb		(*nreg(REG('s', 'b')))
+#define n_st		(*nreg(REG('s', 't')))
+#define n_pg		(*nreg(REG('%', '\0')))	/* % */
+#define n_lb		(*nreg(REG(0, 'b')))	/* input line beg */
+#define n_ce		(*nreg(REG(0, 'c')))	/* .ce remaining */
+#define n_f0		(*nreg(REG(0, 'f')))	/* last .f */
+#define n_hy		(*nreg(REG(0, 'h')))	/* .hy mode */
+#define n_i0		(*nreg(REG(0, 'i')))	/* last .i */
+#define n_l0		(*nreg(REG(0, 'l')))	/* last .l */
+#define n_L0		(*nreg(REG(0, 'L')))	/* last .L */
+#define n_mk		(*nreg(REG(0, 'm')))	/* .mk internal register */
+#define n_na		(*nreg(REG(0, 'n')))	/* .na mode */
+#define n_ns		(*nreg(REG(0, 'N')))	/* .ns mode */
+#define n_o0		(*nreg(REG(0, 'o')))	/* last .o */
+#define n_s0		(*nreg(REG(0, 's')))	/* last .s */
+#define n_sv		(*nreg(REG(0, 'S')))	/* .sv value */
+#define n_lt		(*nreg(REG(0, 't')))	/* .lt value */
+#define n_t0		(*nreg(REG(0, 'T')))	/* previous .lt value */
+#define n_v0		(*nreg(REG(0, 'v')))	/* last .v */
+
+/* functions for implementing read-only registers */
+int f_nexttrap(void);	/* .t */
+int f_divreg(void);	/* .z */
+int f_hpos(void);	/* .k */
--- a/sbuf.c
+++ b/sbuf.c
@@ -2,7 +2,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 #define SBUF_SZ		512
 
--- a/tr.c
+++ b/tr.c
@@ -2,7 +2,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 static int tr_nl = 1;
 static int c_pc = '%';		/* page number character */
--- a/wb.c
+++ b/wb.c
@@ -1,7 +1,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include "xroff.h"
+#include "roff.h"
 
 #define R_F(wb)		((wb)->r_f >= 0 ? (wb)->r_f : n_f)	/* current font */
 #define R_S(wb)		((wb)->r_s >= 0 ? (wb)->r_s : n_s)	/* current size */
--- a/xroff.c
+++ /dev/null
@@ -1,60 +1,0 @@
-/*
- * neatroff troff clone
- *
- * Copyright (C) 2012-2013 Ali Gholami Rudi <ali at rudi dot ir>
- *
- * This program is released under the modified BSD license.
- */
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include "xroff.h"
-
-static void g_init(void)
-{
-	n_o = SC_IN;
-	n_p = SC_IN * 11;
-}
-
-static void compile(void)
-{
-	out("s%d\n", n_s);
-	out("f%d\n", n_f);
-	render();
-	out("V%d\n", n_p);
-}
-
-void errmsg(char *fmt, ...)
-{
-	va_list ap;
-	va_start(ap, fmt);
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
-}
-
-int main(int argc, char **argv)
-{
-	int i;
-	char path[PATHLEN];
-	dev_open(TROFFROOT "/font/devutf");
-	env_init();
-	tr_init();
-	g_init();
-	for (i = 1; i < argc; i++) {
-		if (argv[i][0] != '-' || !argv[i][0])
-			break;
-		if (argv[i][1] == 'm') {
-			sprintf(path, TROFFROOT "/tmac/tmac.%s", argv[i] + 2);
-			in_queue(path);
-		}
-	}
-	if (i == argc)
-		in_queue(NULL);	/* reading from standard input */
-	for (; i < argc; i++)
-		in_queue(!strcmp("-", argv[i]) ? NULL : argv[i]);
-	str_set(REG('.', 'P'), TROFFROOT);
-	compile();
-	env_free();
-	dev_close();
-	return 0;
-}
--- a/xroff.h
+++ /dev/null
@@ -1,322 +1,0 @@
-/* converting scales */
-#define SC_IN		(dev_res)	/* inch in units */
-#define SC_PT		(SC_IN / 72)	/* point in units */
-#define SC_EM		(n_s * SC_IN / 72)
-#define SC_DW		(SC_EM / 3)	/* default width */
-#define SC_HT		(n_s * SC_PT)	/* character height */
-
-/* predefined array limits */
-#define PATHLEN		1024	/* path length */
-#define NFILES		16	/* number of input files */
-#define NFONTS		32	/* number of fonts */
-#define FNLEN		32	/* font name length */
-#define NGLYPHS		512	/* glyphs in fonts */
-#define GNLEN		32	/* glyph name length */
-#define ILNLEN		256	/* line limit of input files */
-#define LNLEN		4000	/* line buffer length (ren.c/out.c) */
-#define NWORDS		256	/* number of words in line buffer */
-#define NARGS		9	/* number of macro arguments */
-#define RLEN		4	/* register/macro name */
-#define NPREV		16	/* environment stack depth */
-#define NTRAPS		1024	/* number of traps per page */
-#define NIES		128	/* number of nested .ie commands */
-#define NTABS		16	/* number of tab stops */
-#define NFIELDS		32	/* number of fields */
-#define MAXFRAC		100000	/* maximum value of the fractional part */
-
-/* escape sequences */
-#define ESC_Q	"bCDhHlLNoSvwxX"	/* quoted escape sequences */
-#define ESC_P	"*fgkns"		/* 1 or 2-char escape sequences */
-
-#define MIN(a, b)	((a) < (b) ? (a) : (b))
-#define MAX(a, b)	((a) < (b) ? (b) : (a))
-#define LEN(a)		(sizeof(a) / sizeof((a)[0]))
-
-/* special characters */
-extern int c_ec;	/* escape character (\) */
-extern int c_cc;	/* basic control character (.) */
-extern int c_c2;	/* no-break control character (') */
-#define c_ni	4	/* non-interpreted copy mode escape */
-#define c_hc	env_hc()/* hyphenation character */
-
-/* number registers */
-int num_get(int id, int inc);
-void num_set(int id, int val);
-void num_inc(int id, int val);
-void num_del(int id);
-char *num_str(int id);
-int *nreg(int id);
-int eval(char *s, int unit);
-int eval_up(char **s, int unit);
-int eval_re(char *s, int orig, int unit);
-
-/* string registers */
-void str_set(int id, char *s);
-void str_dset(int id, void *d);
-char *str_get(int id);
-void *str_dget(int id);
-void str_rm(int id);
-void str_rn(int src, int dst);
-
-/* saving and restoring registers before and after printing diverted lines */
-void odiv_beg(void);
-void odiv_end(void);
-
-/* enviroments */
-void env_init(void);
-void env_free(void);
-struct adj *env_adj(void);
-char *env_hc(void);
-int tab_next(int pos);
-
-/* device related variables */
-extern int dev_res;
-extern int dev_uwid;
-extern int dev_hor;
-extern int dev_ver;
-
-struct glyph {
-	char name[FNLEN];	/* name of the glyph */
-	char id[FNLEN];		/* device-dependent glyph identifier */
-	struct font *font;	/* glyph font */
-	int wid;		/* character width */
-	int type;		/* character type; ascender/descender */
-};
-
-struct font {
-	char name[FNLEN];
-	struct glyph glyphs[NGLYPHS];
-	int nglyphs;
-	int spacewid;
-	int special;
-	char c[NGLYPHS][FNLEN];		/* character names in charset */
-	struct glyph *g[NGLYPHS];	/* character glyphs in charset */
-	int n;				/* number of characters in charset */
-};
-
-/* output device functions */
-int dev_open(char *path);
-void dev_close(void);
-int dev_mnt(int pos, char *id, char *name);
-int dev_font(char *id);
-int charwid(int wid, int sz);
-
-/* font-related functions */
-struct font *font_open(char *path);
-void font_close(struct font *fn);
-struct glyph *font_glyph(struct font *fn, char *id);
-struct glyph *font_find(struct font *fn, char *name);
-
-/* glyph handling functions */
-struct glyph *dev_glyph(char *c, int fn);
-struct glyph *dev_glyph_byid(char *id, int fn);
-int dev_spacewid(void);
-
-/* different layers of neatroff */
-int in_next(void);		/* input layer */
-int cp_next(void);		/* copy-mode layer */
-int tr_next(void);		/* troff layer */
-
-void in_push(char *s, char **args);
-void in_pushnl(char *s, char **args);
-void in_so(char *path);		/* .so request */
-void in_nx(char *path);		/* .nx request */
-void in_ex(void);		/* .nx request */
-void in_queue(char *path);	/* .ex request */
-char *in_arg(int i);		/* look up argument */
-int in_nargs(void);		/* number of arguments */
-void in_back(int c);		/* push back input character */
-int in_top(void);		/* the first pushed-back character */
-char *in_filename(void);	/* current filename */
-
-void cp_blk(int skip);		/* skip or read the next line or block */
-void cp_wid(int enable);	/* control inlining \w requests */
-#define cp_back		in_back	/* cp.c is stateless */
-void tr_first(void);		/* read until the first non-command line */
-
-/* variable length string buffer */
-struct sbuf {
-	char *s;
-	int sz;
-	int n;
-};
-
-void sbuf_init(struct sbuf *sbuf);
-void sbuf_done(struct sbuf *sbuf);
-char *sbuf_buf(struct sbuf *sbuf);
-void sbuf_add(struct sbuf *sbuf, int c);
-void sbuf_append(struct sbuf *sbuf, char *s);
-void sbuf_printf(struct sbuf *sbuf, char *s, ...);
-void sbuf_putnl(struct sbuf *sbuf);
-int sbuf_empty(struct sbuf *sbuf);
-
-/* word buffer */
-struct wb {
-	struct sbuf sbuf;
-	int f, s;		/* the last output font and size */
-	int r_f, r_s;		/* current font and size; use n_f and n_s if -1 */
-	int part;		/* partial input (\c) */
-	int els_neg, els_pos;	/* extra line spacing */
-	int h, v;		/* buffer vertical and horizontal positions */
-	int ct, sb, st;		/* \w registers */
-};
-
-void wb_init(struct wb *wb);
-void wb_done(struct wb *wb);
-void wb_hmov(struct wb *wb, int n);
-void wb_vmov(struct wb *wb, int n);
-void wb_els(struct wb *wb, int els);
-void wb_etc(struct wb *wb, char *x);
-void wb_put(struct wb *wb, char *c);
-int wb_part(struct wb *wb);
-void wb_setpart(struct wb *wb);
-void wb_drawl(struct wb *wb, int h, int v);
-void wb_drawc(struct wb *wb, int r);
-void wb_drawe(struct wb *wb, int h, int v);
-void wb_drawa(struct wb *wb, int h1, int v1, int h2, int v2);
-void wb_drawxbeg(struct wb *wb, int c);
-void wb_drawxdot(struct wb *wb, int h, int v);
-void wb_drawxend(struct wb *wb);
-void wb_cat(struct wb *wb, struct wb *src);
-int wb_hyph(struct wb *wb, int w, struct wb *w1, struct wb *w2, int flg);
-int wb_wid(struct wb *wb);
-int wb_empty(struct wb *wb);
-void wb_wconf(struct wb *wb, int *ct, int *st, int *sb);
-
-/* hyphenation flags */
-#define HY_MASK		0x0f	/* enable hyphenation */
-#define HY_LAST		0x02	/* do not hyphenate last lines */
-#define HY_FINAL	0x04	/* do not hyphenate the final character */
-#define HY_FIRSTTWO	0x08	/* do not hyphenate the first two characters */
-#define HY_ANY		0x10	/* break at any possible position */
-
-void hyphenate(char *hyphs, char *word);
-
-/* adjustment */
-#define AD_L		0
-#define AD_B		1
-#define AD_C		3
-#define AD_R		5
-
-struct adj *adj_alloc(void);
-void adj_free(struct adj *adj);
-int adj_fill(struct adj *adj, int ad_b, int fill, int hyph, struct sbuf *dst,
-		int *ll, int *in, int *ti, int *els_neg, int *els_pos);
-int adj_full(struct adj *adj, int fill);
-int adj_empty(struct adj *adj, int fill);
-int adj_wid(struct adj *adj);
-void adj_swid(struct adj *adj, int swid);
-void adj_ll(struct adj *adj, int ll);
-void adj_in(struct adj *adj, int in);
-void adj_ti(struct adj *adj, int ti);
-void adj_wb(struct adj *adj, struct wb *wb);
-void adj_nl(struct adj *adj);
-void adj_sp(struct adj *adj);
-void adj_nonl(struct adj *adj);
-
-/* rendering */
-void render(void);				/* the main loop */
-void ren_char(struct wb *wb, int (*next)(void), void (*back)(int));
-int ren_wid(int (*next)(void), void (*back)(int));
-void ren_tl(int (*next)(void), void (*back)(int));
-void out_line(char *s);				/* output rendered line */
-int out_readc(char **s, char *d);		/* read request or glyph */
-void out(char *s, ...);				/* output troff cmd */
-void ren_hline(struct wb *wb, char *arg);	/* horizontal line */
-void ren_vline(struct wb *wb, char *arg);	/* vertical line */
-void ren_bracket(struct wb *wb, char *arg);	/* \b */
-void ren_over(struct wb *wb, char *arg);	/* \o */
-void ren_draw(struct wb *wb, char *arg);	/* \D */
-
-/* troff commands */
-void tr_bp(char **args);
-void tr_br(char **args);
-void tr_ce(char **args);
-void tr_ch(char **args);
-void tr_di(char **args);
-void tr_divbeg(char **args);
-void tr_divend(char **args);
-void tr_dt(char **args);
-void tr_em(char **args);
-void tr_ev(char **args);
-void tr_fc(char **args);
-void tr_fi(char **args);
-void tr_fp(char **args);
-void tr_ft(char **args);
-void tr_hw(char **args);
-void tr_in(char **args);
-void tr_ll(char **args);
-void tr_mk(char **args);
-void tr_ne(char **args);
-void tr_nf(char **args);
-void tr_ns(char **args);
-void tr_os(char **args);
-void tr_pn(char **args);
-void tr_ps(char **args);
-void tr_rs(char **args);
-void tr_rt(char **args);
-void tr_sp(char **args);
-void tr_sv(char **args);
-void tr_ta(char **args);
-void tr_ti(char **args);
-void tr_wh(char **args);
-void tr_eject(char **args);
-
-void tr_init(void);
-
-/* helpers */
-void errmsg(char *msg, ...);
-int utf8len(int c);
-int utf8read(char **s, char *d);
-void schar_read(char *d, int (*next)(void));
-int schar_jump(char *d, int (*next)(void), void (*back)(int));
-
-/* internal commands */
-#define TR_DIVBEG	"\07<"	/* diversion begins */
-#define TR_DIVEND	"\07>"	/* diversion ends */
-#define TR_EJECT	"\07P"	/* page eject */
-
-/* builtin number registers; n_X for .X register */
-#define REG(c1, c2)	((c1) * 256 + (c2))
-#define n_a		(*nreg(REG('.', 'a')))
-#define n_d		(*nreg(REG('.', 'd')))
-#define n_f		(*nreg(REG('.', 'f')))
-#define n_h		(*nreg(REG('.', 'h')))
-#define n_i		(*nreg(REG('.', 'i')))
-#define n_j		(*nreg(REG('.', 'j')))
-#define n_l		(*nreg(REG('.', 'l')))
-#define n_L		(*nreg(REG('.', 'L')))
-#define n_n		(*nreg(REG('.', 'n')))
-#define n_o		(*nreg(REG('.', 'o')))
-#define n_p		(*nreg(REG('.', 'p')))
-#define n_s		(*nreg(REG('.', 's')))
-#define n_u		(*nreg(REG('.', 'u')))
-#define n_v		(*nreg(REG('.', 'v')))
-#define n_ct		(*nreg(REG('c', 't')))
-#define n_dl		(*nreg(REG('d', 'l')))
-#define n_dn		(*nreg(REG('d', 'n')))
-#define n_nl		(*nreg(REG('n', 'l')))
-#define n_sb		(*nreg(REG('s', 'b')))
-#define n_st		(*nreg(REG('s', 't')))
-#define n_pg		(*nreg(REG('%', '\0')))	/* % */
-#define n_lb		(*nreg(REG(0, 'b')))	/* input line beg */
-#define n_ce		(*nreg(REG(0, 'c')))	/* .ce remaining */
-#define n_f0		(*nreg(REG(0, 'f')))	/* last .f */
-#define n_hy		(*nreg(REG(0, 'h')))	/* .hy mode */
-#define n_i0		(*nreg(REG(0, 'i')))	/* last .i */
-#define n_l0		(*nreg(REG(0, 'l')))	/* last .l */
-#define n_L0		(*nreg(REG(0, 'L')))	/* last .L */
-#define n_mk		(*nreg(REG(0, 'm')))	/* .mk internal register */
-#define n_na		(*nreg(REG(0, 'n')))	/* .na mode */
-#define n_ns		(*nreg(REG(0, 'N')))	/* .ns mode */
-#define n_o0		(*nreg(REG(0, 'o')))	/* last .o */
-#define n_s0		(*nreg(REG(0, 's')))	/* last .s */
-#define n_sv		(*nreg(REG(0, 'S')))	/* .sv value */
-#define n_lt		(*nreg(REG(0, 't')))	/* .lt value */
-#define n_t0		(*nreg(REG(0, 'T')))	/* previous .lt value */
-#define n_v0		(*nreg(REG(0, 'v')))	/* last .v */
-
-/* functions for implementing read-only registers */
-int f_nexttrap(void);	/* .t */
-int f_divreg(void);	/* .z */
-int f_hpos(void);	/* .k */