ref: ec160f1296fa62bf0e739cd2d670854261bfafd2
parent: 9b90808b2c90134f7d96534908feea5a7769051c
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat May 25 17:34:06 EDT 2013
ren: add .em
--- a/in.c
+++ b/in.c
@@ -20,7 +20,7 @@
static char files[NFILES][PATHLEN];
static int nfiles;
static int cfile;
-static int in_last[2]; /* the last chars returned from in_next() */
+static int in_last[2] = {'\n'}; /* the last chars returned from in_next() */
static char **args_init(char **args);
static void args_free(char **args);
@@ -119,13 +119,18 @@
int in_next(void)
{
- in_last[1] = in_last[0];
- in_last[0] = in_read();
- return in_last[0];
+ int c = in_read();
+ if (c >= 0) {
+ in_last[1] = in_last[0];
+ in_last[0] = c;
+ }
+ return c;
}
void in_back(int c)
{
+ if (c < 0)
+ return;
in_last[0] = in_last[1];
if (buf)
buf->unbuf[buf->un++] = c;
--- a/ren.c
+++ b/ren.c
@@ -21,6 +21,7 @@
static struct div divs[NPREV]; /* diversion stack */
static struct div *cdiv; /* current diversion */
static int ren_div; /* rendering a diversion */
+static int trap_em = -1; /* end macro */
static struct wb ren_wb; /* the main ren.c word buffer */
static int ren_nl; /* just after newline */
@@ -30,7 +31,9 @@
static int bp_first = 1; /* prior to the first page */
static int bp_next = 1; /* next page number */
-static int bp_force; /* execute the traps until the next page */
+static int bp_count; /* number of pages so far */
+static int bp_ejected; /* current ejected page */
+static int bp_final; /* 1: the final page, 2: the 2nd final page */
static int c_fa; /* field delimiter */
static char c_fb[GNLEN]; /* field padding */
@@ -55,7 +58,7 @@
cdiv->treg = -1;
if (args[0][2] == 'a' && str_get(cdiv->reg)) /* .da */
sbuf_append(&cdiv->sbuf, str_get(cdiv->reg));
- sbuf_printf(&cdiv->sbuf, "%c%s\n", c_cc, DIV_BEG);
+ sbuf_printf(&cdiv->sbuf, "%c%s\n", c_cc, TR_DIVBEG);
cdiv->prev_d = n_d;
cdiv->prev_h = n_h;
cdiv->prev_mk = n_mk;
@@ -66,7 +69,7 @@
n_ns = 0;
} else if (cdiv) {
sbuf_putnl(&cdiv->sbuf);
- sbuf_printf(&cdiv->sbuf, "%c%s\n", c_cc, DIV_END);
+ sbuf_printf(&cdiv->sbuf, "%c%s\n", c_cc, TR_DIVEND);
str_set(cdiv->reg, sbuf_buf(&cdiv->sbuf));
sbuf_done(&cdiv->sbuf);
n_dl = cdiv->dl;
@@ -105,13 +108,16 @@
static int trap_pos(int pos);
static void trap_exec(int reg);
-static void ren_page(int pg)
+static void ren_page(int pg, int force)
{
+ if (!force && bp_final)
+ return;
n_nl = 0;
n_d = 0;
n_h = 0;
n_pg = pg;
bp_next = n_pg + 1;
+ bp_count++;
out("p%d\n", pg);
out("V%d\n", 0);
if (trap_pos(-1) == 0)
@@ -122,7 +128,7 @@
{
if (bp_first && !cdiv) {
bp_first = 0;
- ren_page(bp_next);
+ ren_page(bp_next, 1);
}
}
@@ -144,17 +150,8 @@
}
}
-static void push_ne(void)
-{
- char buf[32];
- sprintf(buf, "%cne %du\n", c_cc, n_p);
- in_pushnl(buf, NULL);
-}
-
static void trap_exec(int reg)
{
- if (bp_force)
- push_ne();
if (str_get(reg))
in_pushnl(str_get(reg), NULL);
}
@@ -187,8 +184,7 @@
static int ren_pagelimit(int ne)
{
if (detect_pagelimit(ne)) {
- bp_force = 0;
- ren_page(bp_next);
+ ren_page(bp_next, 0);
return 1;
}
return 0;
@@ -344,15 +340,45 @@
ren_pagelimit(n);
}
-void tr_bp(char **args)
+static void push_eject(void)
{
+ char buf[32];
+ bp_ejected = bp_count;
+ sprintf(buf, "%c%s %d\n", c_cc, TR_EJECT, bp_ejected);
+ in_pushnl(buf, NULL);
+}
+
+static void push_br(void)
+{
char br[8] = {c_cc, 'b', 'r', '\n'};
+ in_pushnl(br, NULL);
+}
+
+static void ren_eject(int id)
+{
+ if (id == bp_ejected && !cdiv) {
+ if (detect_traps(n_d, n_p)) {
+ push_eject();
+ ren_traps(n_d, n_p, 1);
+ } else {
+ bp_ejected = 0;
+ ren_page(bp_next, 0);
+ }
+ }
+}
+
+void tr_eject(char **args)
+{
+ ren_eject(atoi(args[1]));
+}
+
+void tr_bp(char **args)
+{
if (!cdiv && (args[1] || !n_ns)) {
- if (!bp_force)
- push_ne();
+ if (bp_ejected != bp_count)
+ push_eject();
if (args[0][0] == c_cc)
- in_pushnl(br, NULL);
- bp_force = 1;
+ push_br();
if (args[1])
bp_next = eval_re(args[1], n_pg, 0);
}
@@ -751,7 +777,18 @@
tr_first();
ren_first(); /* transition to the first page */
c = ren_next();
- while (c >= 0) {
+ while (1) {
+ if (c < 0) {
+ if (bp_final)
+ break;
+ bp_final = 1;
+ push_eject();
+ push_br();
+ if (trap_em >= 0)
+ trap_exec(trap_em);
+ c = ren_next();
+ continue;
+ }
ren_cnl = c == '\n';
if (c == ' ' || c == '\n') {
adj_swid(cadj, charwid(dev_spacewid(), n_s));
@@ -778,6 +815,9 @@
ren_nl = c == '\n';
c = ren_next();
}
+ bp_final = 2;
+ if (!adj_empty(cadj, 0))
+ ren_page(bp_next, 1);
ren_br(1);
wb_done(wb);
}
@@ -865,9 +905,16 @@
}
}
+void tr_em(char **args)
+{
+ trap_em = args[1] ? REG(args[1][0], args[1][1]) : -1;
+}
+
static int trap_pos(int pos)
{
int ret = trap_first(pos);
+ if (bp_final > 1)
+ return -1;
if (cdiv)
return cdiv->treg && cdiv->tpos > pos ? cdiv->tpos : -1;
return ret >= 0 ? tposval(ret) : -1;
--- a/tr.c
+++ b/tr.c
@@ -576,8 +576,9 @@
void (*f)(char **args);
int (*args)(char **args, char *buf, int len);
} cmds[] = {
- {DIV_BEG, tr_divbeg},
- {DIV_END, tr_divend},
+ {TR_DIVBEG, tr_divbeg},
+ {TR_DIVEND, tr_divend},
+ {TR_EJECT, tr_eject},
{"ad", tr_ad},
{"am", tr_de, mkargs_reg1},
{"as", tr_as, mkargs_ds},
@@ -594,6 +595,7 @@
{"dt", tr_dt},
{"ec", tr_ec},
{"el", tr_el, mkargs_null},
+ {"em", tr_em},
{"eo", tr_eo},
{"ev", tr_ev},
{"ex", tr_ex},
@@ -649,7 +651,7 @@
char cmd[RLEN];
char buf[LNLEN];
struct cmd *req;
- while (tr_nl && (c == c_cc || c == c_c2)) {
+ while (tr_nl && c >= 0 && (c == c_cc || c == c_c2)) {
nl = 1;
memset(args, 0, sizeof(args));
args[0] = cmd;
@@ -673,7 +675,7 @@
c = cp_next();
nl = c == '\n';
}
- tr_nl = nl;
+ tr_nl = c < 0 || nl;
return c;
}
--- a/xroff.h
+++ b/xroff.h
@@ -237,6 +237,7 @@
void tr_divbeg(char **args);
void tr_divend(char **args);
void tr_dt(char **args);
+void tr_em(char **args);
void tr_ev(char **args);
void tr_fc(char **args);
void tr_fi(char **args);
@@ -259,6 +260,7 @@
void tr_ta(char **args);
void tr_ti(char **args);
void tr_wh(char **args);
+void tr_eject(char **args);
void tr_init(void);
@@ -269,9 +271,10 @@
void schar_read(char *d, int (*next)(void));
int schar_jump(char *d, int (*next)(void), void (*back)(int));
-/* diversions */
-#define DIV_BEG "&<"
-#define DIV_END "&>"
+/* internal commands */
+#define TR_DIVBEG "\07<" /* diversion begins */
+#define TR_DIVEND "\07>" /* diversion ends */
+#define TR_EJECT "\07P" /* page eject */
/* builtin number registers; n_X for .X register */
#define REG(c1, c2) ((c1) * 256 + (c2))