shithub: neatroff

Download patch

ref: a579ab3890031df70e0c05a9f301f6798991969e
parent: 74e88bbb0eb0e98021f64a16f04a316d9a9b5021
author: Ali Gholami Rudi <ali@rudi.ir>
date: Fri Nov 23 11:39:35 EST 2012

tr: defining macros with .de

--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
 all: xroff
 %.o: %.c xroff.h
 	$(CC) -c $(CFLAGS) $<
-xroff: xroff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o
+xroff: xroff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o sbuf.o
 	$(CC) -o $@ $^ $(LDFLAGS)
 clean:
 	rm -f *.o xroff
--- /dev/null
+++ b/sbuf.c
@@ -1,0 +1,47 @@
+#include <stdlib.h>
+#include <string.h>
+#include "xroff.h"
+
+#define SBUF_SZ		1024
+
+void sbuf_init(struct sbuf *sbuf)
+{
+	sbuf->s = malloc(SBUF_SZ);
+	sbuf->sz = SBUF_SZ;
+	sbuf->n = 0;
+}
+
+static void sbuf_extend(struct sbuf *sbuf, int amount)
+{
+	char *s = sbuf->s;
+	sbuf->s = malloc(amount);
+	sbuf->sz = amount;
+	memcpy(sbuf->s, s, sbuf->n);
+}
+
+void sbuf_add(struct sbuf *sbuf, int c)
+{
+	if (sbuf->n + 2 >= sbuf->sz)
+		sbuf_extend(sbuf, sbuf->sz * 2);
+	sbuf->s[sbuf->n++] = c;
+}
+
+void sbuf_append(struct sbuf *sbuf, char *s)
+{
+	int len = strlen(s);
+	if (sbuf->n + len + 1 >= sbuf->sz)
+		sbuf_extend(sbuf, sbuf->n + len + 1);
+	memcpy(sbuf->s + sbuf->n, s, len);
+	sbuf->n += len;
+}
+
+char *sbuf_buf(struct sbuf *sbuf)
+{
+	sbuf->s[sbuf->n] = '\0';
+	return sbuf->s;
+}
+
+void sbuf_done(struct sbuf *sbuf)
+{
+	free(sbuf->s);
+}
--- a/tr.c
+++ b/tr.c
@@ -95,6 +95,34 @@
 	str_set(N_ID(args[1][0], args[1][1]), args[2]);
 }
 
+static void tr_de(int argc, char **args)
+{
+	struct sbuf sbuf;
+	int c;
+	if (argc <= 1)
+		return;
+	sbuf_init(&sbuf);
+	while ((c = cp_next()) >= 0) {
+		sbuf_add(&sbuf, c);
+		if (c == '\n') {
+			c = cp_next();
+			if (c == '.') {
+				c = cp_next();
+				if (c == '.')
+					break;
+				sbuf_add(&sbuf, '.');
+				if (c >= 0)
+					sbuf_add(&sbuf, c);
+			} else {
+				if (c >= 0)
+					sbuf_add(&sbuf, c);
+			}
+		}
+	}
+	str_set(N_ID(args[1][0], args[1][1]), sbuf_buf(&sbuf));
+	sbuf_done(&sbuf);
+}
+
 static void tr_in(int argc, char **args)
 {
 	if (argc >= 2)
@@ -189,6 +217,7 @@
 	int (*args)(char **args, int maxargs, char *buf, int len);
 } cmds[] = {
 	{"br", tr_br},
+	{"de", tr_de},
 	{"ds", tr_ds, tr_args_ds},
 	{"fp", tr_fp},
 	{"ft", tr_ft},
--- a/xroff.h
+++ b/xroff.h
@@ -97,3 +97,16 @@
 void errmsg(char *msg, ...);
 int utf8len(int c);
 int charwid(int wid, int sz);
+
+/* 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);