ref: 688bc8b668b371a8fa5d4b0415900f1607caccd3
parent: 57e2ed362dfe517efe02504426e9220892a159c3
author: Ali Gholami Rudi <ali@rudi.ir>
date: Thu Jun 27 15:47:12 EDT 2013
reg: add .af
--- a/cp.c
+++ b/cp.c
@@ -40,6 +40,11 @@
in_push(buf, NULL);
}
+static void cp_numfmt(void)
+{
+ in_push(num_getfmt(regid()), NULL);
+}
+
static void cp_arg(void)
{
int c;
@@ -116,6 +121,9 @@
c = cp_next();
} else if (c == '*') {
cp_str();
+ c = cp_next();
+ } else if (c == 'g') {
+ cp_numfmt();
c = cp_next();
} else if (c == '$') {
cp_arg();
--- a/reg.c
+++ b/reg.c
@@ -1,3 +1,4 @@
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
@@ -17,6 +18,7 @@
static int nregs[NREGS]; /* global number registers */
static int nregs_inc[NREGS]; /* number register auto-increment size */
+static int nregs_fmt[NREGS]; /* number register format */
static char *sregs[NREGS]; /* global string registers */
static void *sregs_dat[NREGS]; /* builtin function data */
static struct env envs[3]; /* environments */
@@ -60,6 +62,8 @@
s[3] = '\0';
}
+static int num_fmt(char *s, int n, int fmt);
+
/* the contents of a number register (returns a static buffer) */
char *num_str(int id)
{
@@ -86,7 +90,8 @@
sprintf(numbuf, "%02d", nregs[id]);
break;
default:
- sprintf(numbuf, "%d", *nreg(id));
+ if (!nregs_fmt[id] || num_fmt(numbuf, *nreg(id), nregs_fmt[id]))
+ sprintf(numbuf, "%d", *nreg(id));
}
return numbuf;
}
@@ -105,6 +110,7 @@
{
*nreg(id) = 0;
nregs_inc[id] = 0;
+ nregs_fmt[id] = 0;
}
int num_get(int id, int inc)
@@ -277,4 +283,108 @@
if (env->tabs[i] > pos)
return env->tabs[i];
return pos;
+}
+
+/* number register format (.af) */
+#define NF_LSH 8 /* number format length shifts */
+#define NF_FMT 0x00ff /* number format mask */
+
+/* the format of a number register (returns a static buffer) */
+char *num_getfmt(int id)
+{
+ static char fmtbuf[128];
+ char *s = fmtbuf;
+ int i;
+ if (!nregs_fmt[id] || (nregs_fmt[id] & NF_FMT) == '0') {
+ *s++ = '0';
+ i = nregs_fmt[id] >> NF_LSH;
+ while (i-- > 1)
+ *s++ = '0';
+ } else {
+ *s++ = nregs_fmt[id] & NF_FMT;
+ }
+ *s = '\0';
+ return fmtbuf;
+}
+
+void num_setfmt(int id, char *s)
+{
+ int i = 0;
+ if (strchr("iIaA", s[0])) {
+ nregs_fmt[id] = s[0];
+ } else {
+ while (isdigit(s[i]))
+ i++;
+ nregs_fmt[id] = '0' | (i << NF_LSH);
+ }
+}
+
+static void nf_reverse(char *s)
+{
+ char r[128];
+ int i, l;
+ strcpy(r, s);
+ l = strlen(r);
+ for (i = 0; i < l; i++)
+ s[i] = r[l - i - 1];
+}
+
+static void nf_roman(char *s, int n, char *I, char *V)
+{
+ int i;
+ if (!n)
+ return;
+ if (n % 5 == 4) {
+ *s++ = n % 10 == 9 ? I[1] : V[0];
+ *s++ = I[0];
+ } else {
+ for (i = 0; i < n % 5; i++)
+ *s++ = I[0];
+ if (n % 10 >= 5)
+ *s++ = V[0];
+ }
+ *s = '\0';
+ nf_roman(s, n / 10, I + 1, V + 1);
+}
+
+static void nf_alpha(char *s, int n, int a)
+{
+ while (n) {
+ *s++ = a + ((n - 1) % 26);
+ n /= 26;
+ }
+ *s = '\0';
+}
+
+/* returns nonzero on failure */
+static int num_fmt(char *s, int n, int fmt)
+{
+ int type = fmt & NF_FMT;
+ int len;
+ if (n < 0) {
+ n = -n;
+ *s++ = '-';
+ }
+ if ((type == 'i' || type == 'I') && n > 0 && n < 40000) {
+ if (type == 'i')
+ nf_roman(s, n, "ixcmz", "vldw");
+ else
+ nf_roman(s, n, "IXCMZ", "VLDW");
+ nf_reverse(s);
+ return 0;
+ }
+ if ((type == 'a' || type == 'A') && n > 0) {
+ nf_alpha(s, n, type);
+ nf_reverse(s);
+ return 0;
+ }
+ if (type == '0') {
+ sprintf(s, "%d", n);
+ len = strlen(s);
+ while (len++ < fmt >> NF_LSH)
+ *s++ = '0';
+ sprintf(s, "%d", n);
+ return 0;
+ }
+ return 1;
}
--- a/roff.h
+++ b/roff.h
@@ -47,6 +47,8 @@
void num_inc(int id, int val);
void num_del(int id);
char *num_str(int id);
+char *num_getfmt(int id);
+void num_setfmt(int id, char *fmt);
int *nreg(int id);
int eval(char *s, int unit);
int eval_up(char **s, int unit);
--- a/tr.c
+++ b/tr.c
@@ -57,11 +57,16 @@
num_del(REG(args[i][0], args[i][1]));
}
+static void tr_af(char **args)
+{
+ if (args[2])
+ num_setfmt(REG(args[1][0], args[1][1]), args[2]);
+}
+
static void tr_ds(char **args)
{
- if (!args[2])
- return;
- str_set(REG(args[1][0], args[1][1]), args[2]);
+ if (args[2])
+ str_set(REG(args[1][0], args[1][1]), args[2]);
}
static void tr_as(char **args)
@@ -594,6 +599,7 @@
{TR_DIVEND, tr_divend},
{TR_EJECT, tr_eject},
{"ad", tr_ad},
+ {"af", tr_af},
{"am", tr_de, mkargs_reg1},
{"as", tr_as, mkargs_ds},
{"bp", tr_bp},