ref: d11408e98db95f4463e5c74cdab2ec1eeadaa0a9
parent: 78a59118aea99a388d678ba9bdd54b24322cc25c
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Nov 20 17:09:20 EST 2012
extract out.c for printing troff code for a line
--- 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 out.o reg.o
+xroff: xroff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f *.o xroff
--- a/dev.c
+++ b/dev.c
@@ -175,3 +175,9 @@
return i;
return dev_mnt(0, id, id);
}
+
+int charwid(int wid, int sz)
+{
+ /* the original troff rounds the widths up */
+ return (wid * sz + dev_uwid - 1) / dev_uwid;
+}
--- a/out.c
+++ b/out.c
@@ -4,22 +4,7 @@
#include <string.h>
#include "xroff.h"
-#define LINELEN 1024
-
-struct word {
- int beg; /* word beginning offset in buf */
- int end; /* word ending offset in buf */
- int wid; /* word width */
- int blanks; /* blanks before word */
-};
-
-static char buf[LINELEN]; /* output buffer */
-static int buflen;
-static struct word words[LINELEN]; /* words in the buffer */
-static int nwords;
-static int wid; /* total width of the buffer */
-
-static int utf8len(int c)
+int utf8len(int c)
{
if (c <= 0x7f)
return 1;
@@ -36,29 +21,6 @@
return 1;
}
-static int out_next(void)
-{
- int c = tr_next();
- if (c < 0)
- return -1;
- buf[buflen++] = c;
- return c;
-}
-
-static int nextchar(char *s)
-{
- int c = out_next();
- int l = utf8len(c);
- int i;
- if (c < 0)
- return 0;
- s[0] = c;
- for (i = 1; i < l; i++)
- s[i] = out_next();
- s[l] = '\0';
- return l;
-}
-
static char *utf8get(char *d, char *s)
{
int l = utf8len(*s);
@@ -69,15 +31,26 @@
return s + l;
}
-static int charwid(int wid, int sz)
+static int o_s = 10;
+static int o_f = 1;
+
+static void out_ps(int n)
{
- /* the original troff rounds the widths up */
- return (wid * sz + dev_uwid - 1) / dev_uwid;
+ if (o_s != n) {
+ o_s = n;
+ printf("s%d\n", o_s);
+ }
}
-static int o_s, o_f;
+static void out_ft(int n)
+{
+ if (n >= 0 && o_f != n) {
+ o_f = n;
+ printf("f%d\n", o_f);
+ }
+}
-static char *read_escarg(char *s, char *d)
+static char *escarg(char *s, char *d)
{
if (*s == '(') {
s++;
@@ -96,7 +69,7 @@
return s;
}
-static void flush(char *s)
+void out_put(char *s)
{
struct glyph *g;
char c[LLEN];
@@ -112,16 +85,13 @@
s = utf8get(c, s);
s = utf8get(c + strlen(c), s);
} else if (strchr("sf", c[0])) {
- s = read_escarg(s, arg);
+ s = escarg(s, arg);
if (c[0] == 's') {
- o_s = tr_int(arg, o_s, '\0');
- printf("s%d\n", o_s);
+ out_ps(tr_int(arg, o_s, '\0'));
continue;
}
if (c[0] == 'f') {
- o_f = dev_font(arg);
- if (o_f >= 0)
- printf("f%d\n", o_f);
+ out_ft(dev_font(arg));
continue;
}
}
@@ -141,175 +111,4 @@
o_blank = 1;
}
}
-}
-
-static void down(int n)
-{
- printf("v%d\n", n);
-}
-
-static void adjust(char *s)
-{
- struct word *last = words;
- int w = 0;
- int lendiff;
- int i;
- if (!nwords) {
- s[0] = '\0';
- return;
- }
- while (last < words + nwords && w + last->wid + last->blanks <= n_l) {
- w += last->wid + last->blanks;
- last++;
- }
- if (last > words)
- last--;
- memcpy(s, buf, last->end);
- s[last->end] = '\0';
- lendiff = last + 1 < words + nwords ? last[1].beg : buflen;
- memmove(buf, buf + lendiff, buflen - lendiff);
- buflen -= lendiff;
- nwords -= last - words + 1;
- memmove(words, last + 1, nwords * sizeof(words[0]));
- wid -= w;
- for (i = 0; i < nwords; i++) {
- words[i].beg -= lendiff;
- words[i].end -= lendiff;
- }
- if (nwords)
- wid -= words[0].blanks;
- words[0].blanks = 0;
-}
-
-void tr_br(int argc, char **args)
-{
- char out[LINELEN];
- buf[buflen] = '\0';
- if (buflen) {
- adjust(out);
- flush(out);
- }
- o_s = n_s;
- o_f = n_f;
-}
-
-void tr_sp(int argc, char **args)
-{
- tr_br(0, NULL);
- if (argc > 1)
- down(tr_int(args[1], 0, 'v'));
-}
-
-static void out_ps(char *s)
-{
- n_s = tr_int(s, n_s, '\0');
-}
-
-void tr_ps(int argc, char **args)
-{
- if (argc >= 2)
- out_ps(args[1]);
- buflen += sprintf(buf + buflen, "\\s(%2d", n_s);
-}
-
-static int out_ft(char *name)
-{
- int fn = dev_font(name);
- if (fn >= 0)
- n_f = fn;
- return fn;
-}
-
-void tr_ft(int argc, char **args)
-{
- int fn;
- if (argc < 2)
- return;
- fn = out_ft(args[1]);
- if (fn >= 0)
- buflen += sprintf(buf + buflen, "\\f%d", n_f);
-}
-
-void tr_fp(int argc, char **args)
-{
- if (argc < 3)
- return;
- if (dev_mnt(atoi(args[1]), args[2], argc > 3 ? args[3] : args[2]) < 0)
- fprintf(stderr, "troff: failed to mount %s\n", args[2]);
-}
-
-static void escarg(char *s)
-{
- int c;
- c = out_next();
- if (c == '(') {
- *s++ = out_next();
- *s++ = out_next();
- *s = '\0';
- return;
- }
- if (c == '\'') {
- while (1) {
- c = out_next();
- if (c == '\'' || c < 0)
- break;
- *s++ = c;
- }
- *s = '\0';
- return;
- }
- *s++ = c;
- *s = '\0';
-}
-
-void render(void)
-{
- char c[LLEN];
- char arg[LINELEN];
- struct glyph *g;
- struct word *word = NULL;
- int word_beg;
- int blanks = 0;
- tr_br(0, NULL);
- while (nextchar(c) > 0) {
- g = NULL;
- word_beg = buflen - strlen(c);
- if (c[0] == '\\') {
- nextchar(c);
- if (c[0] == '(') {
- int l = nextchar(c);
- l += nextchar(c + l);
- c[l] = '\0';
- } else if (strchr("sf", c[0])) {
- escarg(arg);
- if (c[0] == 'f')
- out_ft(arg);
- if (c[0] == 's')
- out_ps(arg);
- continue;
- }
- }
- g = dev_glyph(c, n_f);
- if (!g) {
- blanks += charwid(dev_spacewid(), n_s);
- word = NULL;
- continue;
- }
- if (!word) {
- word = &words[nwords++];
- word->beg = word_beg;
- word->wid = 0;
- word->blanks = blanks;
- wid += blanks;
- blanks = 0;
- }
- word->end = buflen;
- word->wid += charwid(g->wid, n_s);
- wid += charwid(g->wid, n_s);
- if (wid > n_l) {
- word = NULL;
- tr_br(0, NULL);
- }
- }
- tr_br(0, NULL);
}
--- /dev/null
+++ b/ren.c
@@ -1,0 +1,210 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "xroff.h"
+
+struct word {
+ int beg; /* word beginning offset in buf */
+ int end; /* word ending offset in buf */
+ int wid; /* word width */
+ int blanks; /* blanks before word */
+};
+
+static char buf[LINELEN]; /* output buffer */
+static int buflen;
+static struct word words[LINELEN]; /* words in the buffer */
+static int nwords;
+static int wid; /* total width of the buffer */
+
+static int ren_next(void)
+{
+ int c = tr_next();
+ if (c < 0)
+ return -1;
+ buf[buflen++] = c;
+ return c;
+}
+
+static int nextchar(char *s)
+{
+ int c = ren_next();
+ int l = utf8len(c);
+ int i;
+ if (c < 0)
+ return 0;
+ s[0] = c;
+ for (i = 1; i < l; i++)
+ s[i] = ren_next();
+ s[l] = '\0';
+ return l;
+}
+
+static void down(int n)
+{
+ printf("v%d\n", n);
+}
+
+static void adjust(char *s)
+{
+ struct word *last = words;
+ int w = 0;
+ int lendiff;
+ int i;
+ if (!nwords) {
+ s[0] = '\0';
+ return;
+ }
+ while (last < words + nwords && w + last->wid + last->blanks <= n_l) {
+ w += last->wid + last->blanks;
+ last++;
+ }
+ if (last > words)
+ last--;
+ memcpy(s, buf, last->end);
+ s[last->end] = '\0';
+ lendiff = last + 1 < words + nwords ? last[1].beg : buflen;
+ memmove(buf, buf + lendiff, buflen - lendiff);
+ buflen -= lendiff;
+ nwords -= last - words + 1;
+ memmove(words, last + 1, nwords * sizeof(words[0]));
+ wid -= w;
+ for (i = 0; i < nwords; i++) {
+ words[i].beg -= lendiff;
+ words[i].end -= lendiff;
+ }
+ if (nwords)
+ wid -= words[0].blanks;
+ words[0].blanks = 0;
+}
+
+void tr_br(int argc, char **args)
+{
+ char out[LINELEN];
+ buf[buflen] = '\0';
+ if (buflen) {
+ adjust(out);
+ out_put(out);
+ }
+}
+
+void tr_sp(int argc, char **args)
+{
+ tr_br(0, NULL);
+ if (argc > 1)
+ down(tr_int(args[1], 0, 'v'));
+}
+
+static void ren_ps(char *s)
+{
+ n_s = tr_int(s, n_s, '\0');
+}
+
+void tr_ps(int argc, char **args)
+{
+ if (argc >= 2)
+ ren_ps(args[1]);
+ buflen += sprintf(buf + buflen, "\\s(%2d", n_s);
+}
+
+static int ren_ft(char *name)
+{
+ int fn = dev_font(name);
+ if (fn >= 0)
+ n_f = fn;
+ return fn;
+}
+
+void tr_ft(int argc, char **args)
+{
+ int fn;
+ if (argc < 2)
+ return;
+ fn = ren_ft(args[1]);
+ if (fn >= 0)
+ buflen += sprintf(buf + buflen, "\\f%d", n_f);
+}
+
+void tr_fp(int argc, char **args)
+{
+ if (argc < 3)
+ return;
+ if (dev_mnt(atoi(args[1]), args[2], argc > 3 ? args[3] : args[2]) < 0)
+ errmsg("troff: failed to mount %s\n", args[2]);
+}
+
+static void escarg(char *s)
+{
+ int c;
+ c = ren_next();
+ if (c == '(') {
+ *s++ = ren_next();
+ *s++ = ren_next();
+ *s = '\0';
+ return;
+ }
+ if (c == '\'') {
+ while (1) {
+ c = ren_next();
+ if (c == '\'' || c < 0)
+ break;
+ *s++ = c;
+ }
+ *s = '\0';
+ return;
+ }
+ *s++ = c;
+ *s = '\0';
+}
+
+void render(void)
+{
+ char c[LLEN];
+ char arg[LINELEN];
+ struct glyph *g;
+ struct word *word = NULL;
+ int word_beg;
+ int blanks = 0;
+ tr_br(0, NULL);
+ while (nextchar(c) > 0) {
+ g = NULL;
+ word_beg = buflen - strlen(c);
+ if (c[0] == '\\') {
+ nextchar(c);
+ if (c[0] == '(') {
+ int l = nextchar(c);
+ l += nextchar(c + l);
+ c[l] = '\0';
+ } else if (strchr("sf", c[0])) {
+ escarg(arg);
+ if (c[0] == 'f')
+ ren_ft(arg);
+ if (c[0] == 's')
+ ren_ps(arg);
+ continue;
+ }
+ }
+ g = dev_glyph(c, n_f);
+ if (!g) {
+ blanks += charwid(dev_spacewid(), n_s);
+ word = NULL;
+ continue;
+ }
+ if (!word) {
+ word = &words[nwords++];
+ word->beg = word_beg;
+ word->wid = 0;
+ word->blanks = blanks;
+ wid += blanks;
+ blanks = 0;
+ }
+ word->end = buflen;
+ word->wid += charwid(g->wid, n_s);
+ wid += charwid(g->wid, n_s);
+ if (wid > n_l) {
+ word = NULL;
+ tr_br(0, NULL);
+ }
+ }
+ tr_br(0, NULL);
+}
--- a/xroff.c
+++ b/xroff.c
@@ -1,3 +1,4 @@
+#include <stdarg.h>
#include <stdio.h>
#include "xroff.h"
@@ -22,9 +23,12 @@
printf("V%d\n", n_p);
}
-void errmsg(char *msg)
+void errmsg(char *fmt, ...)
{
- fprintf(stderr, "%s", msg);
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
}
int main(void)
--- a/xroff.h
+++ b/xroff.h
@@ -76,10 +76,8 @@
/* rendering */
void render(void);
+void out_put(char *s);
-/* error messages */
-void errmsg(char *msg);
-
/* troff commands */
void tr_br(int argc, char **args);
void tr_sp(int argc, char **args);
@@ -87,3 +85,8 @@
void tr_ps(int argc, char **args);
void tr_ft(int argc, char **args);
void tr_fp(int argc, char **args);
+
+/* helpers */
+void errmsg(char *msg, ...);
+int utf8len(int c);
+int charwid(int wid, int sz);