ref: 9d68d6260e5b04097d8e1e6bca795da4a0192d78
parent: bf62c957f310d3d127093f472d98ed1e3bf94490
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Nov 24 14:59:54 EST 2012
expand macro arguments
--- a/cp.c
+++ b/cp.c
@@ -1,8 +1,12 @@
#include <stdio.h>
+#include <stdlib.h>
#include "xroff.h"
-static int cp_backed = -1;
+#define CPBUF 4
+static int cp_backed = 0;
+static int cp_buf[CPBUF];
+
static int regid(void)
{
int c1;
@@ -19,7 +23,7 @@
{
char buf[32];
sprintf(buf, "%d", num_get(regid()));
- in_push(buf);
+ in_push(buf, NULL);
}
static void cp_str(void)
@@ -26,13 +30,26 @@
{
char *buf = str_get(regid());
if (buf)
- in_push(buf);
+ in_push(buf, NULL);
}
+static void cp_arg(void)
+{
+ int c;
+ char *arg;
+ c = cp_next();
+ if (c >= '1' && c <= '9')
+ arg = in_arg(c - '0');
+ if (arg)
+ in_push(arg, NULL);
+}
+
int cp_next(void)
{
- int c = cp_backed >= 0 ? cp_backed : in_next();
- cp_backed = -1;
+ int c;
+ if (cp_backed)
+ return cp_buf[--cp_backed];
+ c = in_next();
if (c == '\\') {
c = in_next();
if (c == 'n') {
@@ -39,10 +56,13 @@
cp_num();
c = in_next();
} else if (c == '*') {
- cp_str();;
+ cp_str();
c = in_next();
+ } else if (c == '$') {
+ cp_arg();
+ c = in_next();
} else {
- in_back(c);
+ cp_back(c);
c = '\\';
}
}
@@ -51,5 +71,6 @@
void cp_back(int c)
{
- cp_backed = c;
+ if (cp_backed < CPBUF)
+ cp_buf[cp_backed++] = c;
}
--- a/in.c
+++ b/in.c
@@ -5,6 +5,7 @@
struct inbuf {
char *buf;
+ char **args;
int pos;
int len;
int backed;
@@ -14,7 +15,10 @@
static struct inbuf in_main = {.backed = -1};
static struct inbuf *buf = &in_main;
-void in_push(char *s)
+static char **args_init(char **args);
+static void args_free(char **args);
+
+void in_push(char *s, char **args)
{
struct inbuf *next = malloc(sizeof(*buf));
int len = strlen(s);
@@ -24,6 +28,7 @@
next->len = len;
next->backed = -1;
next->prev = buf;
+ next->args = args ? args_init(args) : NULL;
buf = next;
}
@@ -31,6 +36,8 @@
{
struct inbuf *old = buf;
buf = buf->prev;
+ if (old->args)
+ args_free(old->args);
free(old->buf);
free(old);
}
@@ -45,10 +52,47 @@
in_pop();
if (!buf->buf)
return getchar();
- return buf->pos < buf->len ? buf->buf[buf->pos++] : -1;
+ if (buf->pos >= buf->len)
+ return -1;
+ /* replacing \\ with \ only for buffers inserted via in_push() */
+ if (buf->buf[buf->pos] == '\\' && buf->buf[buf->pos + 1] == '\\')
+ buf->pos++;
+ return buf->buf[buf->pos++];
}
void in_back(int c)
{
buf->backed = c;
+}
+
+char *in_arg(int i)
+{
+ struct inbuf *cur = buf;
+ while (cur->prev && !cur->prev)
+ cur = cur->prev;
+ return cur->args && cur->args[i - 1] ? cur->args[i - 1] : "";
+}
+
+static char **args_init(char **args)
+{
+ char **out = malloc(NARGS * sizeof(*out));
+ int i;
+ for (i = 0; i < NARGS; i++) {
+ out[i] = NULL;
+ if (args[i]) {
+ int len = strlen(args[i]) + 1;
+ out[i] = malloc(len);
+ memcpy(out[i], args[i], len);
+ }
+ }
+ return out;
+}
+
+static void args_free(char **args)
+{
+ int i;
+ for (i = 0; i < NARGS; i++)
+ if (args[i])
+ free(args[i]);
+ free(args);
}
--- a/tr.c
+++ b/tr.c
@@ -4,7 +4,6 @@
#include <string.h>
#include "xroff.h"
-#define NARGS 10
#define LINEL 1024
#define LEN(a) (sizeof(a) / sizeof((a)[0]))
@@ -283,7 +282,7 @@
{
int c = cp_next();
int nl = c == '\n';
- char *args[NARGS];
+ char *args[NARGS + 1] = {NULL};
char buf[LINEL];
char cmd[LINEL];
struct cmd *req = NULL;
@@ -299,12 +298,14 @@
req = &cmds[i];
if (req) {
if (req->args)
- argc = req->args(args + 1, NARGS - 1, buf, LINEL);
+ argc = req->args(args + 1, NARGS, buf, LINEL);
else
- argc = mkargs(args + 1, NARGS - 1, buf, LINEL);
+ argc = mkargs(args + 1, NARGS, buf, LINEL);
req->f(argc + 1, args);
} else {
- jmp_eol();
+ argc = mkargs(args + 1, NARGS, buf, LINEL);
+ if (str_get(REG(cmd[1], cmd[2])))
+ in_push(str_get(REG(cmd[1], cmd[2])), args + 1);
}
c = cp_next();
}
--- a/xroff.h
+++ b/xroff.h
@@ -6,8 +6,8 @@
#define FNNAME 32
#define LLEN 128
#define LINELEN 1024
+#define NARGS 9
-
/* number registers */
extern int nreg[];
int num_get(int id);
@@ -77,7 +77,8 @@
int in_next(void);
int cp_next(void);
int tr_next(void);
-void in_push(char *s);
+void in_push(char *s, char **args);
+char *in_arg(int i);
void in_back(int c);
void cp_back(int c);