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 */