shithub: neatroff

Download patch

ref: 83e0919c862f62422e065f6ce1a684e202457c37
parent: f7fb552fa7ca7a294f5a0c02375c5824ff27d9a2
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sun Apr 14 08:24:27 EDT 2013

in: add .so

--- a/in.c
+++ b/in.c
@@ -4,7 +4,9 @@
 #include "xroff.h"
 
 struct inbuf {
-	char *buf;
+	char path[64];		/* for file buffers */
+	FILE *fin;
+	char *buf;		/* for string buffers */
 	char **args;
 	int pos;
 	int len;
@@ -12,26 +14,41 @@
 	struct inbuf *prev;
 };
 
-static struct inbuf in_main = {.backed = -1};
-static struct inbuf *buf = &in_main;
+static struct inbuf *buf;
 
 static char **args_init(char **args);
 static void args_free(char **args);
 
-void in_push(char *s, char **args)
+static void in_new(void)
 {
-	struct inbuf *next = malloc(sizeof(*buf));
-	int len = strlen(s);
-	next->buf = malloc(len + 1);
-	strcpy(next->buf, s);
-	next->pos = 0;
-	next->len = len;
+	struct inbuf *next = malloc(sizeof(*next));
+	memset(next, 0, sizeof(*next));
 	next->backed = -1;
 	next->prev = buf;
-	next->args = args ? args_init(args) : NULL;
 	buf = next;
 }
 
+void in_push(char *s, char **args)
+{
+	int len = strlen(s);
+	in_new();
+	buf->buf = malloc(len + 1);
+	buf->len = len;
+	strcpy(buf->buf, s);
+	buf->args = args ? args_init(args) : NULL;
+}
+
+void in_source(char *path)
+{
+	FILE *fin = path ? fopen(path, "r") : stdin;
+	if (fin) {
+		in_new();
+		buf->fin = fin;
+		if (path)
+			snprintf(buf->path, sizeof(buf->path) - 1, "%s", path);
+	}
+}
+
 static void in_pop(void)
 {
 	struct inbuf *old = buf;
@@ -38,6 +55,8 @@
 	buf = buf->prev;
 	if (old->args)
 		args_free(old->args);
+	if (old->fin && old->path[0])
+		fclose(old->fin);
 	free(old->buf);
 	free(old);
 }
@@ -44,15 +63,22 @@
 
 int in_next(void)
 {
-	int c = buf->backed;
-	buf->backed = -1;
-	if (c >= 0)
+	int c;
+	if (!buf)
+		return -1;
+	if (buf->backed >= 0) {
+		c = buf->backed;
+		buf->backed = -1;
 		return c;
-	while (buf->pos == buf->len && buf->prev)
+	}
+	while (buf) {
+		if (buf->buf && buf->pos < buf->len)
+			break;
+		if (!buf->buf && (c = getc(buf->fin)) >= 0)
+			return c;
 		in_pop();
-	if (!buf->buf)
-		return getchar();
-	if (buf->pos >= buf->len)
+	}
+	if (!buf)
 		return -1;
 	/* replacing \\ with \ only for buffers inserted via in_push() */
 	if (buf->buf[buf->pos] == '\\' && buf->buf[buf->pos + 1] == '\\')
@@ -62,15 +88,24 @@
 
 void in_back(int c)
 {
-	buf->backed = c;
+	if (buf)
+		buf->backed = c;
 }
 
 char *in_arg(int i)
 {
 	struct inbuf *cur = buf;
-	while (!cur->args && cur->prev)
+	while (cur && !cur->args)
 		cur = cur->prev;
-	return cur->args && cur->args[i - 1] ? cur->args[i - 1] : "";
+	return cur && cur->args && cur->args[i - 1] ? cur->args[i - 1] : "";
+}
+
+char *in_filename(void)
+{
+	struct inbuf *cur = buf;
+	while (cur && !cur->fin)
+		cur = cur->prev;
+	return cur && cur->path[0] ? cur->path : "-";
 }
 
 static char **args_init(char **args)
--- a/reg.c
+++ b/reg.c
@@ -64,6 +64,9 @@
 		if (f_divreg() >= 0)
 			reg_name(numbuf, f_divreg());
 		break;
+	case REG('.', 'F'):
+		sprintf(numbuf, "%s", in_filename());
+		break;
 	default:
 		sprintf(numbuf, "%d", *nreg(id));
 	}
--- a/tr.c
+++ b/tr.c
@@ -254,6 +254,12 @@
 	fprintf(stderr, "%s\n", args[1]);
 }
 
+static void tr_so(char **args)
+{
+	if (args[1])
+		in_source(args[1]);
+}
+
 static char *arg_regname(char *s, int len)
 {
 	char *e = s + 2;
@@ -420,6 +426,7 @@
 	{"ps", tr_ps},
 	{"rm", tr_rm},
 	{"rn", tr_rn},
+	{"so", tr_so},
 	{"sp", tr_sp},
 	{"ti", tr_ti},
 	{"tm", tr_tm, mkargs_eol},
--- a/xroff.c
+++ b/xroff.c
@@ -38,6 +38,7 @@
 	env_init();
 	tr_init();
 	g_init();
+	in_source(NULL);	/* reading from standard input */
 	compile();
 	env_free();
 	dev_close();
--- a/xroff.h
+++ b/xroff.h
@@ -96,8 +96,10 @@
 int cp_next(void);	/* copy-mode layer */
 int tr_next(void);	/* troff layer */
 void in_push(char *s, char **args);
+void in_source(char *path);
 char *in_arg(int i);
 void in_back(int c);
+char *in_filename(void);
 void cp_back(int c);
 void cp_skip(void);	/* skip current input line or block */