aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/tbl
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-05-15 23:24:00 +0000
committerrsc <devnull@localhost>2004-05-15 23:24:00 +0000
commit5cedca1b69d020c32466f70843a11767773d7e3b (patch)
treea15a3d84e92aa262543b0010763a5e6920c9ba24 /src/cmd/tbl
parent76e6aca867e3e48ea04fbcf7284c45369a69829e (diff)
downloadplan9port-5cedca1b69d020c32466f70843a11767773d7e3b.tar.gz
plan9port-5cedca1b69d020c32466f70843a11767773d7e3b.tar.bz2
plan9port-5cedca1b69d020c32466f70843a11767773d7e3b.zip
Let's try this. It's BUGGERED.
Diffstat (limited to 'src/cmd/tbl')
-rw-r--r--src/cmd/tbl/mkfile32
-rw-r--r--src/cmd/tbl/t.h192
-rw-r--r--src/cmd/tbl/t0.c49
-rw-r--r--src/cmd/tbl/t1.c95
-rw-r--r--src/cmd/tbl/t2.c25
-rw-r--r--src/cmd/tbl/t3.c104
-rw-r--r--src/cmd/tbl/t4.c405
-rw-r--r--src/cmd/tbl/t5.c198
-rw-r--r--src/cmd/tbl/t6.c223
-rw-r--r--src/cmd/tbl/t7.c150
-rw-r--r--src/cmd/tbl/t8.c367
-rw-r--r--src/cmd/tbl/t9.c76
-rw-r--r--src/cmd/tbl/tb.c101
-rw-r--r--src/cmd/tbl/tc.c65
-rw-r--r--src/cmd/tbl/te.c75
-rw-r--r--src/cmd/tbl/tf.c74
-rw-r--r--src/cmd/tbl/tg.c81
-rw-r--r--src/cmd/tbl/ti.c75
-rw-r--r--src/cmd/tbl/tm.c65
-rw-r--r--src/cmd/tbl/tr.c28
-rw-r--r--src/cmd/tbl/ts.c71
-rw-r--r--src/cmd/tbl/tt.c127
-rw-r--r--src/cmd/tbl/tu.c257
-rw-r--r--src/cmd/tbl/tv.c183
24 files changed, 3118 insertions, 0 deletions
diff --git a/src/cmd/tbl/mkfile b/src/cmd/tbl/mkfile
new file mode 100644
index 00000000..cdaf4a7e
--- /dev/null
+++ b/src/cmd/tbl/mkfile
@@ -0,0 +1,32 @@
+<$PLAN9/src/mkhdr
+
+TARG=tbl
+OFILES=\
+ t8.$O\
+ t4.$O\
+ t6.$O\
+ tu.$O\
+ t5.$O\
+ t7.$O\
+ tv.$O\
+ tg.$O\
+ t3.$O\
+ tb.$O\
+ tt.$O\
+ t9.$O\
+ t1.$O\
+ tf.$O\
+ tc.$O\
+ ti.$O\
+ tm.$O\
+ t0.$O\
+ tr.$O\
+ te.$O\
+ ts.$O\
+ t2.$O\
+
+HFILES=\
+ t.h\
+
+SHORTLIB=bio 9
+<$PLAN9/src/mkone
diff --git a/src/cmd/tbl/t.h b/src/cmd/tbl/t.h
new file mode 100644
index 00000000..efcab373
--- /dev/null
+++ b/src/cmd/tbl/t.h
@@ -0,0 +1,192 @@
+/* t..c : external declarations */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+# include <ctype.h>
+
+# define MAXLIN 250
+# define MAXHEAD 44
+# define MAXCOL 30
+ /* Do NOT make MAXCOL bigger with adjusting nregs[] in tr.c */
+# define MAXCHS 2000
+#define MAXLINLEN 300
+# define MAXRPT 100
+# define CLLEN 10
+# define SHORTLINE 4
+extern int nlin, ncol, iline, nclin, nslin;
+
+extern int (*style)[MAXHEAD];
+extern char (*font)[MAXHEAD][2];
+extern char (*csize)[MAXHEAD][4];
+extern char (*vsize)[MAXHEAD][4];
+extern char (*cll)[CLLEN];
+extern int (*flags)[MAXHEAD];
+# define ZEROW 001
+# define HALFUP 002
+# define CTOP 004
+# define CDOWN 010
+extern int stynum[];
+extern int qcol;
+extern int *doubled, *acase, *topat;
+extern int F1, F2;
+extern int (*lefline)[MAXHEAD];
+extern int fullbot[];
+extern char *instead[];
+extern int expflg;
+extern int ctrflg;
+extern int evenflg;
+extern int *evenup;
+extern int boxflg;
+extern int dboxflg;
+extern int linsize;
+extern int tab;
+extern int pr1403;
+extern int linsize, delim1, delim2;
+extern int allflg;
+extern int textflg;
+extern int left1flg;
+extern int rightl;
+struct colstr {char *col, *rcol;};
+extern struct colstr *table[];
+extern char *cspace, *cstore;
+extern char *exstore, *exlim, *exspace;
+extern int *sep;
+extern int *used, *lused, *rused;
+extern int linestop[];
+extern char *leftover;
+extern char *last, *ifile;
+extern int texname;
+extern int texct, texmax;
+extern char texstr[];
+extern int linstart;
+
+
+extern Biobuf *tabin, tabout;
+# define CRIGHT 2
+# define CLEFT 0
+# define CMID 1
+# define S1 31
+# define S2 32
+# define S3 33
+# define TMP 38
+#define S9 39
+# define SF 35
+# define SL 34
+# define LSIZE 33
+# define SIND 37
+# define SVS 36
+/* this refers to the relative position of lines */
+# define LEFT 1
+# define RIGHT 2
+# define THRU 3
+# define TOP 1
+# define BOT 2
+
+int tbl(int argc,char *argv[]); /*t1.c*/
+void setinp(int, char **);
+int swapin(void);
+
+void tableput(void); /*t2.c*/
+
+void getcomm(void); /*t3.c*/
+void backrest(char *);
+
+void getspec(void); /*t4.c*/
+void readspec(void);
+int findcol(void);
+void garray(int);
+char *getcore(int, int);
+void freearr(void);
+
+void gettbl(void); /*t5.c*/
+int nodata(int);
+int oneh(int);
+int vspand(int, int, int);
+int vspen(char *);
+void permute(void);
+
+void maktab(void); /*t6.c*/
+void wide(char *, char *, char *);
+int filler(char *);
+
+void runout(void); /*t7.c*/
+void runtabs(int, int);
+int ifline(char *);
+void need(void);
+void deftail(void);
+
+void putline(int, int); /*t8.c*/
+void puttext(char *, char *, char *);
+void funnies(int, int);
+void putfont(char *);
+void putsize(char *);
+
+void yetmore(void); /*t9.c*/
+int domore(char *);
+
+void checkuse(void); /*tb.c*/
+int real(char *);
+char *chspace(void);
+int *alocv(int);
+void release(void);
+
+void choochar(void); /*tc.c*/
+int point(char *);
+
+void error(char *); /*te.c*/
+char *gets1(char *, int);
+void un1getc(int);
+int get1char(void);
+
+void savefill(void); /*tf.c*/
+void rstofill(void);
+void endoff(void);
+void freearr(void);
+void saveline(void);
+void ifdivert(void);
+void restline(void);
+void cleanfc(void);
+
+int gettext(char *, int, int, char *, char *); /*tg.c*/
+void untext(void);
+
+int interv(int, int); /*ti.c*/
+int interh(int, int);
+int up1(int);
+
+char *maknew(char *); /*tm.c*/
+int ineqn (char *, char *);
+
+char *reg(int, int); /*tr.c*/
+
+int match (char *, char *); /*ts.c*/
+int prefix(char *, char *);
+int letter (int);
+int numb(char *);
+int digit(int);
+int max(int, int);
+void tcopy (char *, char *);
+
+int ctype(int, int); /*tt.c*/
+int min(int, int);
+int fspan(int, int);
+int lspan(int, int);
+int ctspan(int, int);
+void tohcol(int);
+int allh(int);
+int thish(int, int);
+
+void makeline(int, int, int); /*tu.c*/
+void fullwide(int, int);
+void drawline(int, int, int, int, int, int);
+void getstop(void);
+int left(int, int, int *);
+int lefdata(int, int);
+int next(int);
+int prev(int);
+
+void drawvert(int, int, int, int); /*tv.c*/
+int midbar(int, int);
+int midbcol(int, int);
+int barent(char *);
diff --git a/src/cmd/tbl/t0.c b/src/cmd/tbl/t0.c
new file mode 100644
index 00000000..0c0895bd
--- /dev/null
+++ b/src/cmd/tbl/t0.c
@@ -0,0 +1,49 @@
+ /* t0.c: storage allocation */
+#
+# include "t.h"
+int expflg = 0;
+int ctrflg = 0;
+int boxflg = 0;
+int dboxflg = 0;
+int tab = '\t';
+int linsize;
+int pr1403;
+int delim1, delim2;
+int evenflg;
+int *evenup;
+int F1 = 0;
+int F2 = 0;
+int allflg = 0;
+char *leftover = 0;
+int textflg = 0;
+int left1flg = 0;
+int rightl = 0;
+char *cstore, *cspace;
+char *last;
+struct colstr *table[MAXLIN];
+int stynum[MAXLIN+1];
+int fullbot[MAXLIN];
+char *instead[MAXLIN];
+int linestop[MAXLIN];
+int (*style)[MAXHEAD];
+char (*font)[MAXHEAD][2];
+char (*csize)[MAXHEAD][4];
+char (*vsize)[MAXHEAD][4];
+int (*lefline)[MAXHEAD];
+char (*cll)[CLLEN];
+int (*flags)[MAXHEAD];
+int qcol;
+int *doubled, *acase, *topat;
+int nslin, nclin;
+int *sep;
+int *used, *lused, *rused;
+int nlin, ncol;
+int iline = 1;
+char *ifile = "Input";
+int texname = 'a';
+int texct = 0;
+char texstr[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYXZ0123456789";
+int linstart;
+char *exstore, *exlim, *exspace;
+Biobuf *tabin /*= stdin */;
+Biobuf tabout /* = stdout */;
diff --git a/src/cmd/tbl/t1.c b/src/cmd/tbl/t1.c
new file mode 100644
index 00000000..1e6cbf11
--- /dev/null
+++ b/src/cmd/tbl/t1.c
@@ -0,0 +1,95 @@
+/* t1.c: main control and input switching */
+#
+# include "t.h"
+
+# define MACROS "/usr/lib/tmac.s"
+# define PYMACS "/usr/lib/tmac.m"
+
+
+# define ever (;;)
+
+void
+main(int argc, char *argv[])
+{
+ exits(tbl(argc, argv)? "error" : 0);
+}
+
+
+int
+tbl(int argc, char *argv[])
+{
+ char line[5120];
+ /*int x;*/
+ /*x=malloc((char *)0); uncomment when allocation breaks*/
+ Binit(&tabout, 1, OWRITE);
+ setinp(argc, argv);
+ while (gets1(line, sizeof(line))) {
+ Bprint(&tabout, "%s\n", line);
+ if (prefix(".TS", line))
+ tableput();
+ }
+ Bterm(tabin);
+ return(0);
+}
+
+
+int sargc;
+char **sargv;
+
+void
+setinp(int argc, char **argv)
+{
+ sargc = argc;
+ sargv = argv;
+ sargc--;
+ sargv++;
+ if (sargc > 0)
+ swapin();
+ else {
+ tabin = (Biobuf*)getcore(sizeof(Biobuf), 1);
+ Binit(tabin, 0, OREAD);
+ }
+}
+
+
+int
+swapin(void)
+{
+ char *name;
+ while (sargc > 0 && **sargv == '-') {
+ if (match("-ms", *sargv)) {
+ *sargv = MACROS;
+ break;
+ }
+ if (match("-mm", *sargv)) {
+ *sargv = PYMACS;
+ break;
+ }
+ if (match("-TX", *sargv))
+ pr1403 = 1;
+ if (match("-", *sargv))
+ break;
+ sargc--;
+ sargv++;
+ }
+ if (sargc <= 0)
+ return(0);
+ /* file closing is done by GCOS troff preprocessor */
+ if(tabin)
+ Bterm(tabin);
+ ifile = *sargv;
+ name = ifile;
+ if (match(ifile, "-")) {
+ tabin = (Biobuf*)getcore(sizeof(Biobuf), 1);
+ Binit(tabin, 0, OREAD);
+ } else
+ tabin = Bopen(ifile, OREAD);
+ iline = 1;
+ Bprint(&tabout, ".ds f. %s\n", ifile);
+ Bprint(&tabout, ".lf %d %s\n", iline, name);
+ if (tabin == 0)
+ error("Can't open file");
+ sargc--;
+ sargv++;
+ return(1);
+}
diff --git a/src/cmd/tbl/t2.c b/src/cmd/tbl/t2.c
new file mode 100644
index 00000000..6d2d7414
--- /dev/null
+++ b/src/cmd/tbl/t2.c
@@ -0,0 +1,25 @@
+/* t2.c: subroutine sequencing for one table */
+# include "t.h"
+void
+tableput(void)
+{
+ saveline();
+ savefill();
+ ifdivert();
+ cleanfc();
+ getcomm();
+ getspec();
+ gettbl();
+ getstop();
+ checkuse();
+ choochar();
+ maktab();
+ runout();
+ release();
+ rstofill();
+ endoff();
+ freearr();
+ restline();
+}
+
+
diff --git a/src/cmd/tbl/t3.c b/src/cmd/tbl/t3.c
new file mode 100644
index 00000000..a4dc9f9f
--- /dev/null
+++ b/src/cmd/tbl/t3.c
@@ -0,0 +1,104 @@
+/* t3.c: interpret commands affecting whole table */
+# include "t.h"
+struct optstr {
+ char *optnam;
+ int *optadd;
+} options [] = {
+ "expand", &expflg,
+ "EXPAND", &expflg,
+ "center", &ctrflg,
+ "CENTER", &ctrflg,
+ "box", &boxflg,
+ "BOX", &boxflg,
+ "allbox", &allflg,
+ "ALLBOX", &allflg,
+ "doublebox", &dboxflg,
+ "DOUBLEBOX", &dboxflg,
+ "frame", &boxflg,
+ "FRAME", &boxflg,
+ "doubleframe", &dboxflg,
+ "DOUBLEFRAME", &dboxflg,
+ "tab", &tab,
+ "TAB", &tab,
+ "linesize", &linsize,
+ "LINESIZE", &linsize,
+ "delim", &delim1,
+ "DELIM", &delim1,
+ 0, 0};
+
+
+void
+getcomm(void)
+{
+ char line[200], *cp, nb[25], *t;
+ struct optstr *lp;
+ int c, ci, found;
+
+ for (lp = options; lp->optnam; lp++)
+ *(lp->optadd) = 0;
+ texname = texstr[texct=0];
+ tab = '\t';
+ Bprint(&tabout, ".nr %d \\n(.s\n", LSIZE);
+ gets1(line, sizeof(line));
+ /* see if this is a command line */
+ if (strchr(line, ';') == 0) {
+ backrest(line);
+ return;
+ }
+ for (cp = line; (c = *cp) != ';'; cp++) {
+ if (!letter(c))
+ continue;
+ found = 0;
+ for (lp = options; lp->optadd; lp++) {
+ if (prefix(lp->optnam, cp)) {
+ *(lp->optadd) = 1;
+ cp += strlen(lp->optnam);
+ if (letter(*cp))
+ error("Misspelled global option");
+ while (*cp == ' ')
+ cp++;
+ t = nb;
+ if ( *cp == '(')
+ while ((ci = *++cp) != ')')
+ *t++ = ci;
+ else
+ cp--;
+ *t++ = 0;
+ *t = 0;
+ if (lp->optadd == &tab) {
+ if (nb[0])
+ *(lp->optadd) = nb[0];
+ }
+ if (lp->optadd == &linsize)
+ Bprint(&tabout, ".nr %d %s\n", LSIZE, nb);
+ if (lp->optadd == &delim1) {
+ delim1 = nb[0];
+ delim2 = nb[1];
+ }
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ error("Illegal option");
+ }
+ cp++;
+ backrest(cp);
+ return;
+}
+
+
+void
+backrest(char *cp)
+{
+ char *s;
+
+ for (s = cp; *s; s++)
+ ;
+ un1getc('\n');
+ while (s > cp)
+ un1getc(*--s);
+ return;
+}
+
+
diff --git a/src/cmd/tbl/t4.c b/src/cmd/tbl/t4.c
new file mode 100644
index 00000000..558d3ba3
--- /dev/null
+++ b/src/cmd/tbl/t4.c
@@ -0,0 +1,405 @@
+/* t4.c: read table specification */
+# include "t.h"
+int oncol;
+
+void
+getspec(void)
+{
+ int icol, i;
+
+ qcol = findcol() + 1;/* must allow one extra for line at right */
+ garray(qcol);
+ sep[-1] = -1;
+ for (icol = 0; icol < qcol; icol++) {
+ sep[icol] = -1;
+ evenup[icol] = 0;
+ cll[icol][0] = 0;
+ for (i = 0; i < MAXHEAD; i++) {
+ csize[icol][i][0] = 0;
+ vsize[icol][i][0] = 0;
+ font[icol][i][0] = lefline[icol][i] = 0;
+ flags[icol][i] = 0;
+ style[icol][i] = 'l';
+ }
+ }
+ for (i = 0; i < MAXHEAD; i++)
+ lefline[qcol][i] = 0; /* fixes sample55 looping */
+ nclin = ncol = 0;
+ oncol = 0;
+ left1flg = rightl = 0;
+ readspec();
+ Bprint(&tabout, ".rm");
+ for (i = 0; i < ncol; i++)
+ Bprint(&tabout, " %2s", reg(i, CRIGHT));
+ Bprint(&tabout, "\n");
+}
+
+
+void
+readspec(void)
+{
+ int icol, c, sawchar, stopc, i;
+ char sn[10], *snp, *temp;
+
+ sawchar = icol = 0;
+ while (c = get1char()) {
+ switch (c) {
+ default:
+ if (c != tab) {
+ char buf[64];
+ sprint(buf, "bad table specification character %c", c);
+ error(buf);
+ }
+ case ' ': /* note this is also case tab */
+ continue;
+ case '\n':
+ if (sawchar == 0)
+ continue;
+ case ',':
+ case '.': /* end of table specification */
+ ncol = max(ncol, icol);
+ if (lefline[ncol][nclin] > 0) {
+ ncol++;
+ rightl++;
+ };
+ if (sawchar)
+ nclin++;
+ if (nclin >= MAXHEAD)
+ error("too many lines in specification");
+ icol = 0;
+ if (ncol == 0 || nclin == 0)
+ error("no specification");
+ if (c == '.') {
+ while ((c = get1char()) && c != '\n')
+ if (c != ' ' && c != '\t')
+ error("dot not last character on format line");
+ /* fix up sep - default is 3 except at edge */
+ for (icol = 0; icol < ncol; icol++)
+ if (sep[icol] < 0)
+ sep[icol] = icol + 1 < ncol ? 3 : 2;
+ if (oncol == 0)
+ oncol = ncol;
+ else if (oncol + 2 < ncol)
+ error("tried to widen table in T&, not allowed");
+ return;
+ }
+ sawchar = 0;
+ continue;
+ case 'C':
+ case 'S':
+ case 'R':
+ case 'N':
+ case 'L':
+ case 'A':
+ c += ('a' - 'A');
+ case '_':
+ if (c == '_')
+ c = '-';
+ case '=':
+ case '-':
+ case '^':
+ case 'c':
+ case 's':
+ case 'n':
+ case 'r':
+ case 'l':
+ case 'a':
+ style[icol][nclin] = c;
+ if (c == 's' && icol <= 0)
+ error("first column can not be S-type");
+ if (c == 's' && style[icol-1][nclin] == 'a') {
+ Bprint(&tabout, ".tm warning: can't span a-type cols, changed to l\n");
+ style[icol-1][nclin] = 'l';
+ }
+ if (c == 's' && style[icol-1][nclin] == 'n') {
+ Bprint(&tabout, ".tm warning: can't span n-type cols, changed to c\n");
+ style[icol-1][nclin] = 'c';
+ }
+ icol++;
+ if (c == '^' && nclin <= 0)
+ error("first row can not contain vertical span");
+ if (icol > qcol)
+ error("too many columns in table");
+ sawchar = 1;
+ continue;
+ case 'b':
+ case 'i':
+ c += 'A' - 'a';
+ case 'B':
+ case 'I':
+ if (icol == 0)
+ continue;
+ snp = font[icol-1][nclin];
+ snp[0] = (c == 'I' ? '2' : '3');
+ snp[1] = 0;
+ continue;
+ case 't':
+ case 'T':
+ if (icol > 0)
+ flags[icol-1][nclin] |= CTOP;
+ continue;
+ case 'd':
+ case 'D':
+ if (icol > 0)
+ flags[icol-1][nclin] |= CDOWN;
+ continue;
+ case 'f':
+ case 'F':
+ if (icol == 0)
+ continue;
+ snp = font[icol-1][nclin];
+ snp[0] = snp[1] = stopc = 0;
+ for (i = 0; i < 2; i++) {
+ c = get1char();
+ if (i == 0 && c == '(') {
+ stopc = ')';
+ c = get1char();
+ }
+ if (c == 0)
+ break;
+ if (c == stopc) {
+ stopc = 0;
+ break;
+ }
+ if (stopc == 0)
+ if (c == ' ' || c == tab )
+ break;
+ if (c == '\n' || c == '|') {
+ un1getc(c);
+ break;
+ }
+ snp[i] = c;
+ if (c >= '0' && c <= '9')
+ break;
+ }
+ if (stopc)
+ if (get1char() != stopc)
+ error("Nonterminated font name");
+ continue;
+ case 'P':
+ case 'p':
+ if (icol <= 0)
+ continue;
+ temp = snp = csize[icol-1][nclin];
+ while (c = get1char()) {
+ if (c == ' ' || c == tab || c == '\n')
+ break;
+ if (c == '-' || c == '+')
+ if (snp > temp)
+ break;
+ else
+ *snp++ = c;
+ else if (digit(c))
+ *snp++ = c;
+ else
+ break;
+ if (snp - temp > 4)
+ error("point size too large");
+ }
+ *snp = 0;
+ if (atoi(temp) > 36)
+ error("point size unreasonable");
+ un1getc (c);
+ continue;
+ case 'V':
+ case 'v':
+ if (icol <= 0)
+ continue;
+ temp = snp = vsize[icol-1][nclin];
+ while (c = get1char()) {
+ if (c == ' ' || c == tab || c == '\n')
+ break;
+ if (c == '-' || c == '+')
+ if (snp > temp)
+ break;
+ else
+ *snp++ = c;
+ else if (digit(c))
+ *snp++ = c;
+ else
+ break;
+ if (snp - temp > 4)
+ error("vertical spacing value too large");
+ }
+ *snp = 0;
+ un1getc(c);
+ continue;
+ case 'w':
+ case 'W':
+ snp = cll [icol-1];
+ /* Dale Smith didn't like this check - possible to have two text blocks
+ of different widths now ....
+ if (*snp)
+ {
+ Bprint(&tabout, "Ignored second width specification");
+ continue;
+ }
+ /* end commented out code ... */
+ stopc = 0;
+ while (c = get1char()) {
+ if (snp == cll[icol-1] && c == '(') {
+ stopc = ')';
+ continue;
+ }
+ if ( !stopc && (c > '9' || c < '0'))
+ break;
+ if (stopc && c == stopc)
+ break;
+ *snp++ = c;
+ }
+ *snp = 0;
+ if (snp - cll[icol-1] > CLLEN)
+ error ("column width too long");
+ if (!stopc)
+ un1getc(c);
+ continue;
+ case 'e':
+ case 'E':
+ if (icol < 1)
+ continue;
+ evenup[icol-1] = 1;
+ evenflg = 1;
+ continue;
+ case 'z':
+ case 'Z': /* zero width-ignre width this item */
+ if (icol < 1)
+ continue;
+ flags[icol-1][nclin] |= ZEROW;
+ continue;
+ case 'u':
+ case 'U': /* half line up */
+ if (icol < 1)
+ continue;
+ flags[icol-1][nclin] |= HALFUP;
+ continue;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ sn[0] = c;
+ snp = sn + 1;
+ while (digit(*snp++ = c = get1char()))
+ ;
+ un1getc(c);
+ sep[icol-1] = max(sep[icol-1], numb(sn));
+ continue;
+ case '|':
+ lefline[icol][nclin]++;
+ if (icol == 0)
+ left1flg = 1;
+ continue;
+ }
+ }
+ error("EOF reading table specification");
+}
+
+
+int
+findcol(void)
+{
+# define FLNLIM 200
+ /* this counts the number of columns and then puts the line back*/
+ char *s, line[FLNLIM+2], *p;
+ int c, n = 0, inpar = 0;
+
+ while ((c = get1char()) != 0 && c == ' ')
+ ;
+ if (c != '\n')
+ un1getc(c);
+ for (s = line; *s = c = get1char(); s++) {
+ if (c == ')')
+ inpar = 0;
+ if (inpar)
+ continue;
+ if (c == '\n' || c == 0 || c == '.' || c == ',')
+ break;
+ else if (c == '(')
+ inpar = 1;
+ else if (s >= line + FLNLIM)
+ error("too long spec line");
+ }
+ for (p = line; p < s; p++)
+ switch (*p) {
+ case 'l':
+ case 'r':
+ case 'c':
+ case 'n':
+ case 'a':
+ case 's':
+ case 'L':
+ case 'R':
+ case 'C':
+ case 'N':
+ case 'A':
+ case 'S':
+ case '-':
+ case '=':
+ case '_':
+ n++;
+ }
+ while (p >= line)
+ un1getc(*p--);
+ return(n);
+}
+
+
+void
+garray(int qcol)
+{
+ style = (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int));
+ evenup = (int *) getcore(qcol, sizeof(int));
+ lefline = (int (*)[]) getcore(MAXHEAD * (qcol + 1), sizeof (int)); /*+1 for sample55 loop - others may need it too*/
+ font = (char (*)[][2]) getcore(MAXHEAD * qcol, 2);
+ csize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4);
+ vsize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4);
+ flags = (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int));
+ cll = (char (*)[])getcore(qcol, CLLEN);
+ sep = (int *) getcore(qcol + 1, sizeof(int));
+ sep++; /* sep[-1] must be legal */
+ used = (int *) getcore(qcol + 1, sizeof(int));
+ lused = (int *) getcore(qcol + 1, sizeof(int));
+ rused = (int *) getcore(qcol + 1, sizeof(int));
+ doubled = (int *) getcore(qcol + 1, sizeof(int));
+ acase = (int *) getcore(qcol + 1, sizeof(int));
+ topat = (int *) getcore(qcol + 1, sizeof(int));
+}
+
+
+char *
+getcore(int a, int b)
+{
+ char *x;
+ x = calloc(a, b);
+ if (x == 0)
+ error("Couldn't get memory");
+ return(x);
+}
+
+
+void
+freearr(void)
+{
+ free(style);
+ free(evenup);
+ free(lefline);
+ free(flags);
+ free(font);
+ free(csize);
+ free(vsize);
+ free(cll);
+ free(--sep); /* netnews says this should be --sep because incremented earlier! */
+ free(used);
+ free(lused);
+ free(rused);
+ free(doubled);
+ free(acase);
+ free(topat);
+}
+
+
diff --git a/src/cmd/tbl/t5.c b/src/cmd/tbl/t5.c
new file mode 100644
index 00000000..8b7a65d8
--- /dev/null
+++ b/src/cmd/tbl/t5.c
@@ -0,0 +1,198 @@
+/* t5.c: read data for table */
+# include "t.h"
+
+void
+gettbl(void)
+{
+ int icol, ch;
+
+ cstore = cspace = chspace();
+ textflg = 0;
+ for (nlin = nslin = 0; gets1(cstore, MAXCHS - (cstore - cspace)); nlin++) {
+ stynum[nlin] = nslin;
+ if (prefix(".TE", cstore)) {
+ leftover = 0;
+ break;
+ }
+ if (prefix(".TC", cstore) || prefix(".T&", cstore)) {
+ readspec();
+ nslin++;
+ }
+ if (nlin >= MAXLIN) {
+ leftover = cstore;
+ break;
+ }
+ fullbot[nlin] = 0;
+ if (cstore[0] == '.' && !isdigit(cstore[1])) {
+ instead[nlin] = cstore;
+ while (*cstore++)
+ ;
+ continue;
+ } else
+ instead[nlin] = 0;
+ if (nodata(nlin)) {
+ if (ch = oneh(nlin))
+ fullbot[nlin] = ch;
+ table[nlin] = (struct colstr *) alocv((ncol + 2) * sizeof(table[0][0]));
+ for (icol = 0; icol < ncol; icol++) {
+ table[nlin][icol].rcol = "";
+ table[nlin][icol].col = "";
+ }
+ nlin++;
+ nslin++;
+ fullbot[nlin] = 0;
+ instead[nlin] = (char *) 0;
+ }
+ table[nlin] = (struct colstr *) alocv((ncol + 2) * sizeof(table[0][0]));
+ if (cstore[1] == 0)
+ switch (cstore[0]) {
+ case '_':
+ fullbot[nlin] = '-';
+ continue;
+ case '=':
+ fullbot[nlin] = '=';
+ continue;
+ }
+ stynum[nlin] = nslin;
+ nslin = min(nslin + 1, nclin - 1);
+ for (icol = 0; icol < ncol; icol++) {
+ table[nlin][icol].col = cstore;
+ table[nlin][icol].rcol = 0;
+ ch = 1;
+ if (match(cstore, "T{")) { /* text follows */
+ table[nlin][icol].col =
+ (char *)gettext(cstore, nlin, icol,
+ font[icol][stynum[nlin]],
+ csize[icol][stynum[nlin]]);
+ } else
+ {
+ for (; (ch = *cstore) != '\0' && ch != tab; cstore++)
+ ;
+ *cstore++ = '\0';
+ switch (ctype(nlin, icol)) /* numerical or alpha, subcol */ {
+ case 'n':
+ table[nlin][icol].rcol = maknew(table[nlin][icol].col);
+ break;
+ case 'a':
+ table[nlin][icol].rcol = table[nlin][icol].col;
+ table[nlin][icol].col = "";
+ break;
+ }
+ }
+ while (ctype(nlin, icol + 1) == 's') /* spanning */
+ table[nlin][++icol].col = "";
+ if (ch == '\0')
+ break;
+ }
+ while (++icol < ncol + 2) {
+ table[nlin][icol].col = "";
+ table [nlin][icol].rcol = 0;
+ }
+ while (*cstore != '\0')
+ cstore++;
+ if (cstore - cspace + MAXLINLEN > MAXCHS)
+ cstore = cspace = chspace();
+ }
+ last = cstore;
+ permute();
+ if (textflg)
+ untext();
+ return;
+}
+
+
+int
+nodata(int il)
+{
+ int c;
+
+ for (c = 0; c < ncol; c++) {
+ switch (ctype(il, c)) {
+ case 'c':
+ case 'n':
+ case 'r':
+ case 'l':
+ case 's':
+ case 'a':
+ return(0);
+ }
+ }
+ return(1);
+}
+
+
+int
+oneh(int lin)
+{
+ int k, icol;
+
+ k = ctype(lin, 0);
+ for (icol = 1; icol < ncol; icol++) {
+ if (k != ctype(lin, icol))
+ return(0);
+ }
+ return(k);
+}
+
+
+# define SPAN "\\^"
+
+void
+permute(void)
+{
+ int irow, jcol, is;
+ char *start, *strig;
+
+ for (jcol = 0; jcol < ncol; jcol++) {
+ for (irow = 1; irow < nlin; irow++) {
+ if (vspand(irow, jcol, 0)) {
+ is = prev(irow);
+ if (is < 0)
+ error("Vertical spanning in first row not allowed");
+ start = table[is][jcol].col;
+ strig = table[is][jcol].rcol;
+ while (irow < nlin && vspand(irow, jcol, 0))
+ irow++;
+ table[--irow][jcol].col = start;
+ table[irow][jcol].rcol = strig;
+ while (is < irow) {
+ table[is][jcol].rcol = 0;
+ table[is][jcol].col = SPAN;
+ is = next(is);
+ }
+ }
+ }
+ }
+}
+
+
+int
+vspand(int ir, int ij, int ifform)
+{
+ if (ir < 0)
+ return(0);
+ if (ir >= nlin)
+ return(0);
+ if (instead[ir])
+ return(0);
+ if (ifform == 0 && ctype(ir, ij) == '^')
+ return(1);
+ if (table[ir][ij].rcol != 0)
+ return(0);
+ if (fullbot[ir])
+ return(0);
+ return(vspen(table[ir][ij].col));
+}
+
+
+int
+vspen(char *s)
+{
+ if (s == 0)
+ return(0);
+ if (!point(s))
+ return(0);
+ return(match(s, SPAN));
+}
+
+
diff --git a/src/cmd/tbl/t6.c b/src/cmd/tbl/t6.c
new file mode 100644
index 00000000..a78368fc
--- /dev/null
+++ b/src/cmd/tbl/t6.c
@@ -0,0 +1,223 @@
+/* t6.c: compute tab stops */
+# define tx(a) (a>0 && a<128)
+# include "t.h"
+# define FN(i,c) font[c][stynum[i]]
+# define SZ(i,c) csize[c][stynum[i]]
+# define TMP1 S1
+# define TMP2 S2
+
+void
+maktab(void) /* define the tab stops of the table */
+{
+ int icol, ilin, tsep, k, ik, vforml, il, text;
+ char *s;
+
+ for (icol = 0; icol < ncol; icol++) {
+ doubled[icol] = acase[icol] = 0;
+ Bprint(&tabout, ".nr %2s 0\n", reg(icol, CRIGHT));
+ for (text = 0; text < 2; text++) {
+ if (text)
+ Bprint(&tabout, ".%2s\n.rm %2s\n", reg(icol, CRIGHT),
+ reg(icol, CRIGHT));
+ for (ilin = 0; ilin < nlin; ilin++) {
+ if (instead[ilin] || fullbot[ilin])
+ continue;
+ vforml = ilin;
+ for (il = prev(ilin); il >= 0 && vspen(table[il][icol].col); il = prev(il))
+ vforml = il;
+ if (fspan(vforml, icol))
+ continue;
+ if (filler(table[ilin][icol].col))
+ continue;
+ if ((flags[icol][stynum[ilin]] & ZEROW) != 0)
+ continue;
+ switch (ctype(vforml, icol)) {
+ case 'a':
+ acase[icol] = 1;
+ s = table[ilin][icol].col;
+ if ((int)s > 0 && (int)s < 128 && text) {
+ if (doubled[icol] == 0)
+ Bprint(&tabout, ".nr %d 0\n.nr %d 0\n",
+ S1, S2);
+ doubled[icol] = 1;
+ Bprint(&tabout, ".if \\n(%c->\\n(%d .nr %d \\n(%c-\n",
+ (int)s, S2, S2, (int)s);
+ }
+ case 'n':
+ if (table[ilin][icol].rcol != 0) {
+ if (doubled[icol] == 0 && text == 0)
+ Bprint(&tabout, ".nr %d 0\n.nr %d 0\n",
+ S1, S2);
+ doubled[icol] = 1;
+ if (real(s = table[ilin][icol].col) && !vspen(s)) {
+ if (tx((int)s) != text)
+ continue;
+ Bprint(&tabout, ".nr %d ", TMP);
+ wide(s, FN(vforml, icol), SZ(vforml, icol));
+ Bprint(&tabout, "\n");
+ Bprint(&tabout, ".if \\n(%d<\\n(%d .nr %d \\n(%d\n",
+ S1, TMP, S1, TMP);
+ }
+ if (text == 0 && real(s = table[ilin][icol].rcol) && !vspen(s) && !barent(s)) {
+ Bprint(&tabout, ".nr %d \\w%c%s%c\n",
+ TMP, F1, s, F1);
+ Bprint(&tabout, ".if \\n(%d<\\n(%d .nr %d \\n(%d\n", S2, TMP, S2,
+ TMP);
+ }
+ continue;
+ }
+ case 'r':
+ case 'c':
+ case 'l':
+ if (real(s = table[ilin][icol].col) && !vspen(s)) {
+ if (tx((int)s) != text)
+ continue;
+ Bprint(&tabout, ".nr %d ", TMP);
+ wide(s, FN(vforml, icol), SZ(vforml, icol));
+ Bprint(&tabout, "\n");
+ Bprint(&tabout, ".if \\n(%2s<\\n(%d .nr %2s \\n(%d\n",
+ reg(icol, CRIGHT), TMP, reg(icol, CRIGHT), TMP);
+ }
+ }
+ }
+ }
+ if (acase[icol]) {
+ Bprint(&tabout, ".if \\n(%d>=\\n(%2s .nr %2s \\n(%du+2n\n",
+ S2, reg(icol, CRIGHT), reg(icol, CRIGHT), S2);
+ }
+ if (doubled[icol]) {
+ Bprint(&tabout, ".nr %2s \\n(%d\n", reg(icol, CMID), S1);
+ Bprint(&tabout, ".nr %d \\n(%2s+\\n(%d\n", TMP, reg(icol, CMID), S2);
+ Bprint(&tabout, ".if \\n(%d>\\n(%2s .nr %2s \\n(%d\n", TMP,
+ reg(icol, CRIGHT), reg(icol, CRIGHT), TMP);
+ Bprint(&tabout, ".if \\n(%d<\\n(%2s .nr %2s +(\\n(%2s-\\n(%d)/2\n",
+ TMP, reg(icol, CRIGHT), reg(icol, CMID), reg(icol, CRIGHT), TMP);
+ }
+ if (cll[icol][0]) {
+ Bprint(&tabout, ".nr %d %sn\n", TMP, cll[icol]);
+ Bprint(&tabout, ".if \\n(%2s<\\n(%d .nr %2s \\n(%d\n",
+ reg(icol, CRIGHT), TMP, reg(icol, CRIGHT), TMP);
+ }
+ for (ilin = 0; ilin < nlin; ilin++)
+ if (k = lspan(ilin, icol)) {
+ s = table[ilin][icol-k].col;
+ if (!real(s) || barent(s) || vspen(s) )
+ continue;
+ Bprint(&tabout, ".nr %d ", TMP);
+ wide(table[ilin][icol-k].col, FN(ilin, icol - k), SZ(ilin, icol - k));
+ for (ik = k; ik >= 0; ik--) {
+ Bprint(&tabout, "-\\n(%2s", reg(icol - ik, CRIGHT));
+ if (!expflg && ik > 0)
+ Bprint(&tabout, "-%dn", sep[icol-ik]);
+ }
+ Bprint(&tabout, "\n");
+ Bprint(&tabout, ".if \\n(%d>0 .nr %d \\n(%d/%d\n", TMP,
+ TMP, TMP, k);
+ Bprint(&tabout, ".if \\n(%d<0 .nr %d 0\n", TMP, TMP);
+ for (ik = 1; ik <= k; ik++) {
+ if (doubled[icol-k+ik])
+ Bprint(&tabout, ".nr %2s +\\n(%d/2\n",
+ reg(icol - k + ik, CMID), TMP);
+ Bprint(&tabout, ".nr %2s +\\n(%d\n",
+ reg(icol - k + ik, CRIGHT), TMP);
+ }
+ }
+ }
+ if (textflg)
+ untext();
+ /* if even requested, make all columns widest width */
+ if (evenflg) {
+ Bprint(&tabout, ".nr %d 0\n", TMP);
+ for (icol = 0; icol < ncol; icol++) {
+ if (evenup[icol] == 0)
+ continue;
+ Bprint(&tabout, ".if \\n(%2s>\\n(%d .nr %d \\n(%2s\n",
+ reg(icol, CRIGHT), TMP, TMP, reg(icol, CRIGHT));
+ }
+ for (icol = 0; icol < ncol; icol++) {
+ if (evenup[icol] == 0)
+ /* if column not evened just retain old interval */
+ continue;
+ if (doubled[icol])
+ Bprint(&tabout, ".nr %2s (100*\\n(%2s/\\n(%2s)*\\n(%d/100\n",
+ reg(icol, CMID), reg(icol, CMID), reg(icol, CRIGHT), TMP);
+ /* that nonsense with the 100's and parens tries
+ to avoid overflow while proportionally shifting
+ the middle of the number */
+ Bprint(&tabout, ".nr %2s \\n(%d\n", reg(icol, CRIGHT), TMP);
+ }
+ }
+ /* now adjust for total table width */
+ for (tsep = icol = 0; icol < ncol; icol++)
+ tsep += sep[icol];
+ if (expflg) {
+ Bprint(&tabout, ".nr %d 0", TMP);
+ for (icol = 0; icol < ncol; icol++)
+ Bprint(&tabout, "+\\n(%2s", reg(icol, CRIGHT));
+ Bprint(&tabout, "\n");
+ Bprint(&tabout, ".nr %d \\n(.l-\\n(%d\n", TMP, TMP);
+ if (boxflg || dboxflg || allflg)
+ /* tsep += 1; */ {}
+ else
+ tsep -= sep[ncol-1];
+ Bprint(&tabout, ".nr %d \\n(%d/%d\n", TMP, TMP, tsep);
+ Bprint(&tabout, ".if \\n(%d<0 .nr %d 0\n", TMP, TMP);
+ } else
+ Bprint(&tabout, ".nr %d 1n\n", TMP);
+ Bprint(&tabout, ".nr %2s 0\n", reg(-1, CRIGHT));
+ tsep = (boxflg || allflg || dboxflg || left1flg) ? 2 : 0;
+ if (sep[-1] >= 0)
+ tsep = sep[-1];
+ for (icol = 0; icol < ncol; icol++) {
+ Bprint(&tabout, ".nr %2s \\n(%2s+((%d*\\n(%d)/2)\n", reg(icol, CLEFT),
+ reg(icol - 1, CRIGHT), tsep, TMP);
+ Bprint(&tabout, ".nr %2s +\\n(%2s\n", reg(icol, CRIGHT), reg(icol, CLEFT));
+ if (doubled[icol]) {
+ /* the next line is last-ditch effort to avoid zero field width */
+ /*Bprint(&tabout, ".if \\n(%2s=0 .nr %2s 1\n",reg(icol,CMID), reg(icol,CMID));*/
+ Bprint(&tabout, ".nr %2s +\\n(%2s\n", reg(icol, CMID),
+ reg(icol, CLEFT));
+ /* Bprint(&tabout, ".if n .if \\n(%s%%24>0 .nr %s +12u\n",reg(icol,CMID), reg(icol,CMID)); */
+ }
+ tsep = sep[icol] * 2;
+ }
+ if (rightl)
+ Bprint(&tabout, ".nr %s (\\n(%s+\\n(%s)/2\n", reg(ncol - 1, CRIGHT),
+ reg(ncol - 1, CLEFT), reg(ncol - 2, CRIGHT));
+ Bprint(&tabout, ".nr TW \\n(%2s\n", reg(ncol - 1, CRIGHT));
+ tsep = sep[ncol-1];
+ if (boxflg || allflg || dboxflg)
+ Bprint(&tabout, ".nr TW +((%d*\\n(%d)/2)\n", tsep, TMP);
+ Bprint(&tabout,
+ ".if t .if (\\n(TW+\\n(.o)>7.65i .tm Table at line %d file %s is too wide - \\n(TW units\n", iline - 1, ifile);
+ return;
+}
+
+
+void
+wide(char *s, char *fn, char *size)
+{
+ if (point(s)) {
+ Bprint(&tabout, "\\w%c", F1);
+ if (*fn > 0)
+ putfont(fn);
+ if (*size)
+ putsize(size);
+ Bprint(&tabout, "%s", s);
+ if (*fn > 0)
+ putfont("P");
+ if (*size)
+ putsize("0");
+ Bprint(&tabout, "%c", F1);
+ } else
+ Bprint(&tabout, "\\n(%c-", (int)s);
+}
+
+
+int
+filler(char *s)
+{
+ return (point(s) && s[0] == '\\' && s[1] == 'R');
+}
+
+
diff --git a/src/cmd/tbl/t7.c b/src/cmd/tbl/t7.c
new file mode 100644
index 00000000..2fa9de53
--- /dev/null
+++ b/src/cmd/tbl/t7.c
@@ -0,0 +1,150 @@
+/* t7.c: control to write table entries */
+# include "t.h"
+# define realsplit ((ct=='a'||ct=='n') && table[ldata][c].rcol)
+
+void
+runout(void)
+{
+ int i;
+
+ if (boxflg || allflg || dboxflg)
+ need();
+ if (ctrflg) {
+ Bprint(&tabout, ".nr #I \\n(.i\n");
+ Bprint(&tabout, ".in +(\\n(.lu-\\n(TWu-\\n(.iu)/2u\n");
+ }
+ Bprint(&tabout, ".fc %c %c\n", F1, F2);
+ Bprint(&tabout, ".nr #T 0-1\n");
+ deftail();
+ for (i = 0; i < nlin; i++)
+ putline(i, i);
+ if (leftover)
+ yetmore();
+ Bprint(&tabout, ".fc\n");
+ Bprint(&tabout, ".nr T. 1\n");
+ Bprint(&tabout, ".T# 1\n");
+ if (ctrflg)
+ Bprint(&tabout, ".in \\n(#Iu\n");
+}
+
+
+void
+runtabs(int lform, int ldata)
+{
+ int c, ct, vforml, lf;
+
+ Bprint(&tabout, ".ta ");
+ for (c = 0; c < ncol; c++) {
+ vforml = lform;
+ for (lf = prev(lform); lf >= 0 && vspen(table[lf][c].col); lf = prev(lf))
+ vforml = lf;
+ if (fspan(vforml, c))
+ continue;
+ switch (ct = ctype(vforml, c)) {
+ case 'n':
+ case 'a':
+ if (table[ldata][c].rcol)
+ if (lused[c]) /*Zero field width*/
+ Bprint(&tabout, "\\n(%2su ", reg(c, CMID));
+ case 'c':
+ case 'l':
+ case 'r':
+ if (realsplit ? rused[c] : (used[c] + lused[c]))
+ Bprint(&tabout, "\\n(%2su ", reg(c, CRIGHT));
+ continue;
+ case 's':
+ if (lspan(lform, c))
+ Bprint(&tabout, "\\n(%2su ", reg(c, CRIGHT));
+ continue;
+ }
+ }
+ Bprint(&tabout, "\n");
+}
+
+
+int
+ifline(char *s)
+{
+ if (!point(s))
+ return(0);
+ if (s[0] == '\\')
+ s++;
+ if (s[1] )
+ return(0);
+ if (s[0] == '_')
+ return('-');
+ if (s[0] == '=')
+ return('=');
+ return(0);
+}
+
+
+void
+need(void)
+{
+ int texlin, horlin, i;
+
+ for (texlin = horlin = i = 0; i < nlin; i++) {
+ if (fullbot[i] != 0)
+ horlin++;
+ else if (instead[i] != 0)
+ continue;
+ else
+ texlin++;
+ }
+ Bprint(&tabout, ".ne %dv+%dp\n", texlin, 2 * horlin);
+}
+
+
+void
+deftail(void)
+{
+ int i, c, lf, lwid;
+
+ for (i = 0; i < MAXHEAD; i++)
+ if (linestop[i])
+ Bprint(&tabout, ".nr #%c 0-1\n", linestop[i] + 'a' - 1);
+ Bprint(&tabout, ".nr #a 0-1\n");
+ Bprint(&tabout, ".eo\n");
+ Bprint(&tabout, ".de T#\n");
+ Bprint(&tabout, ".nr 35 1m\n");
+ Bprint(&tabout, ".ds #d .d\n");
+ Bprint(&tabout, ".if \\(ts\\n(.z\\(ts\\(ts .ds #d nl\n");
+ Bprint(&tabout, ".mk ##\n");
+ Bprint(&tabout, ".nr ## -1v\n");
+ Bprint(&tabout, ".ls 1\n");
+ for (i = 0; i < MAXHEAD; i++)
+ if (linestop[i])
+ Bprint(&tabout, ".if \\n(#T>=0 .nr #%c \\n(#T\n",
+ linestop[i] + 'a' - 1);
+ if (boxflg || allflg || dboxflg) /* bottom of table line */
+ if (fullbot[nlin-1] == 0) {
+ if (!pr1403)
+ Bprint(&tabout, ".if \\n(T. .vs \\n(.vu-\\n(.sp\n");
+ Bprint(&tabout, ".if \\n(T. ");
+ drawline(nlin, 0, ncol, dboxflg ? '=' : '-', 1, 0);
+ Bprint(&tabout, "\n.if \\n(T. .vs\n");
+ /* T. is really an argument to a macro but because of
+ eqn we don't dare pass it as an argument and reference by $1 */
+ }
+ for (c = 0; c < ncol; c++) {
+ if ((lf = left(nlin - 1, c, &lwid)) >= 0) {
+ Bprint(&tabout, ".if \\n(#%c>=0 .sp -1\n", linestop[lf] + 'a' - 1);
+ Bprint(&tabout, ".if \\n(#%c>=0 ", linestop[lf] + 'a' - 1);
+ tohcol(c);
+ drawvert(lf, nlin - 1, c, lwid);
+ Bprint(&tabout, "\\h'|\\n(TWu'\n");
+ }
+ }
+ if (boxflg || allflg || dboxflg) /* right hand line */ {
+ Bprint(&tabout, ".if \\n(#a>=0 .sp -1\n");
+ Bprint(&tabout, ".if \\n(#a>=0 \\h'|\\n(TWu'");
+ drawvert (0, nlin - 1, ncol, dboxflg ? 2 : 1);
+ Bprint(&tabout, "\n");
+ }
+ Bprint(&tabout, ".ls\n");
+ Bprint(&tabout, "..\n");
+ Bprint(&tabout, ".ec\n");
+}
+
+
diff --git a/src/cmd/tbl/t8.c b/src/cmd/tbl/t8.c
new file mode 100644
index 00000000..92277e2a
--- /dev/null
+++ b/src/cmd/tbl/t8.c
@@ -0,0 +1,367 @@
+/* t8.c: write out one line of output table */
+# include "t.h"
+# define realsplit ((ct=='a'||ct=='n') && table[nl][c].rcol)
+int watchout;
+int once;
+
+void
+putline(int i, int nl)
+ /* i is line number for deciding format */
+ /* nl is line number for finding data usually identical */
+{
+ int c, lf, ct, form, lwid, vspf, ip, cmidx, exvspen, vforml;
+ int vct, chfont, uphalf;
+ char *s, *size, *fn, *rct;
+
+ cmidx = watchout = vspf = exvspen = 0;
+ if (i == 0)
+ once = 0;
+ if (i == 0 && ( allflg || boxflg || dboxflg))
+ fullwide(0, dboxflg ? '=' : '-');
+ if (instead[nl] == 0 && fullbot[nl] == 0)
+ for (c = 0; c < ncol; c++) {
+ s = table[nl][c].col;
+ if (s == 0)
+ continue;
+ if (vspen(s)) {
+ for (ip = nl; ip < nlin; ip = next(ip))
+ if (!vspen(s = table[ip][c].col))
+ break;
+ if ((int)s > 0 && (int)s < 128)
+ Bprint(&tabout, ".ne \\n(%c|u+\\n(.Vu\n", (int)s);
+ continue;
+ }
+ if (point(s))
+ continue;
+ Bprint(&tabout, ".ne \\n(%c|u+\\n(.Vu\n", (int)s);
+ watchout = 1;
+ }
+ if (linestop[nl])
+ Bprint(&tabout, ".mk #%c\n", linestop[nl] + 'a' - 1);
+ lf = prev(nl);
+ if (instead[nl]) {
+ Bprint(&tabout, "%s\n", instead[nl]);
+ return;
+ }
+ if (fullbot[nl]) {
+ switch (ct = fullbot[nl]) {
+ case '=':
+ case '-':
+ fullwide(nl, ct);
+ }
+ return;
+ }
+ for (c = 0; c < ncol; c++) {
+ if (instead[nl] == 0 && fullbot[nl] == 0)
+ if (vspen(table[nl][c].col))
+ vspf = 1;
+ if (lf >= 0)
+ if (vspen(table[lf][c].col))
+ vspf = 1;
+ }
+ if (vspf) {
+ Bprint(&tabout, ".nr #^ \\n(\\*(#du\n");
+ Bprint(&tabout, ".nr #- \\n(#^\n"); /* current line position relative to bottom */
+ }
+ vspf = 0;
+ chfont = 0;
+ for (c = 0; c < ncol; c++) {
+ s = table[nl][c].col;
+ if (s == 0)
+ continue;
+ chfont |= (int)(font[c][stynum[nl]]);
+ if (point(s) )
+ continue;
+ lf = prev(nl);
+ if (lf >= 0 && vspen(table[lf][c].col))
+ Bprint(&tabout,
+ ".if (\\n(%c|+\\n(^%c-1v)>\\n(#- .nr #- +(\\n(%c|+\\n(^%c-\\n(#--1v)\n",
+ (int)s, 'a' + c, (int)s, 'a' + c);
+ else
+ Bprint(&tabout,
+ ".if (\\n(%c|+\\n(#^-1v)>\\n(#- .nr #- +(\\n(%c|+\\n(#^-\\n(#--1v)\n",
+ (int)s, (int)s);
+ }
+ if (allflg && once > 0 )
+ fullwide(i, '-');
+ once = 1;
+ runtabs(i, nl);
+ if (allh(i) && !pr1403) {
+ Bprint(&tabout, ".nr %d \\n(.v\n", SVS);
+ Bprint(&tabout, ".vs \\n(.vu-\\n(.sp\n");
+ Bprint(&tabout, ".nr 35 \\n(.vu\n");
+ } else
+ Bprint(&tabout, ".nr 35 1m\n");
+ if (chfont)
+ Bprint(&tabout, ".nr %2d \\n(.f\n", S1);
+ Bprint(&tabout, "\\&");
+ vct = 0;
+ for (c = 0; c < ncol; c++) {
+ uphalf = 0;
+ if (watchout == 0 && i + 1 < nlin && (lf = left(i, c, &lwid)) >= 0) {
+ tohcol(c);
+ drawvert(lf, i, c, lwid);
+ vct += 2;
+ }
+ if (rightl && c + 1 == ncol)
+ continue;
+ vforml = i;
+ for (lf = prev(nl); lf >= 0 && vspen(table[lf][c].col); lf = prev(lf))
+ vforml = lf;
+ form = ctype(vforml, c);
+ if (form != 's') {
+ rct = reg(c, CLEFT);
+ if (form == 'a')
+ rct = reg(c, CMID);
+ if (form == 'n' && table[nl][c].rcol && lused[c] == 0)
+ rct = reg(c, CMID);
+ Bprint(&tabout, "\\h'|\\n(%2su'", rct);
+ }
+ s = table[nl][c].col;
+ fn = font[c][stynum[vforml]];
+ size = csize[c][stynum[vforml]];
+ if (*size == 0)
+ size = 0;
+ if ((flags[c][stynum[nl]] & HALFUP) != 0 && pr1403 == 0)
+ uphalf = 1;
+ switch (ct = ctype(vforml, c)) {
+ case 'n':
+ case 'a':
+ if (table[nl][c].rcol) {
+ if (lused[c]) /*Zero field width*/ {
+ ip = prev(nl);
+ if (ip >= 0)
+ if (vspen(table[ip][c].col)) {
+ if (exvspen == 0) {
+ Bprint(&tabout, "\\v'-(\\n(\\*(#du-\\n(^%cu", c + 'a');
+ if (cmidx)
+/* code folded from here */
+ Bprint(&tabout, "-((\\n(#-u-\\n(^%cu)/2u)", c + 'a');
+/* unfolding */
+ vct++;
+ if (pr1403) /* must round to whole lines */
+/* code folded from here */
+ Bprint(&tabout, "/1v*1v");
+/* unfolding */
+ Bprint(&tabout, "'");
+ exvspen = 1;
+ }
+ }
+ Bprint(&tabout, "%c%c", F1, F2);
+ if (uphalf)
+ Bprint(&tabout, "\\u");
+ puttext(s, fn, size);
+ if (uphalf)
+ Bprint(&tabout, "\\d");
+ Bprint(&tabout, "%c", F1);
+ }
+ s = table[nl][c].rcol;
+ form = 1;
+ break;
+ }
+ case 'c':
+ form = 3;
+ break;
+ case 'r':
+ form = 2;
+ break;
+ case 'l':
+ form = 1;
+ break;
+ case '-':
+ case '=':
+ if (real(table[nl][c].col))
+ fprint(2, "%s: line %d: Data ignored on table line %d\n", ifile, iline - 1, i + 1);
+ makeline(i, c, ct);
+ continue;
+ default:
+ continue;
+ }
+ if (realsplit ? rused[c] : used[c]) /*Zero field width*/ {
+ /* form: 1 left, 2 right, 3 center adjust */
+ if (ifline(s)) {
+ makeline(i, c, ifline(s));
+ continue;
+ }
+ if (filler(s)) {
+ Bprint(&tabout, "\\l'|\\n(%2su\\&%s'", reg(c, CRIGHT), s + 2);
+ continue;
+ }
+ ip = prev(nl);
+ cmidx = (flags[c][stynum[nl]] & (CTOP | CDOWN)) == 0;
+ if (ip >= 0)
+ if (vspen(table[ip][c].col)) {
+ if (exvspen == 0) {
+ Bprint(&tabout, "\\v'-(\\n(\\*(#du-\\n(^%cu", c + 'a');
+ if (cmidx)
+ Bprint(&tabout, "-((\\n(#-u-\\n(^%cu)/2u)", c + 'a');
+ vct++;
+ if (pr1403) /* round to whole lines */
+ Bprint(&tabout, "/1v*1v");
+ Bprint(&tabout, "'");
+ }
+ }
+ Bprint(&tabout, "%c", F1);
+ if (form != 1)
+ Bprint(&tabout, "%c", F2);
+ if (vspen(s))
+ vspf = 1;
+ else
+ {
+ if (uphalf)
+ Bprint(&tabout, "\\u");
+ puttext(s, fn, size);
+ if (uphalf)
+ Bprint(&tabout, "\\d");
+ }
+ if (form != 2)
+ Bprint(&tabout, "%c", F2);
+ Bprint(&tabout, "%c", F1);
+ }
+ ip = prev(nl);
+ if (ip >= 0)
+ if (vspen(table[ip][c].col)) {
+ exvspen = (c + 1 < ncol) && vspen(table[ip][c+1].col) &&
+ (topat[c] == topat[c+1]) &&
+ (cmidx == (flags[c+1] [stynum[nl]] & (CTOP | CDOWN) == 0))
+ && (left(i, c + 1, &lwid) < 0);
+ if (exvspen == 0) {
+ Bprint(&tabout, "\\v'(\\n(\\*(#du-\\n(^%cu", c + 'a');
+ if (cmidx)
+ Bprint(&tabout, "-((\\n(#-u-\\n(^%cu)/2u)", c + 'a');
+ vct++;
+ if (pr1403) /* round to whole lines */
+ Bprint(&tabout, "/1v*1v");
+ Bprint(&tabout, "'");
+ }
+ }
+ else
+ exvspen = 0;
+ /* if lines need to be split for gcos here is the place for a backslash */
+ if (vct > 7 && c < ncol) {
+ Bprint(&tabout, "\n.sp-1\n\\&");
+ vct = 0;
+ }
+ }
+ Bprint(&tabout, "\n");
+ if (allh(i) && !pr1403)
+ Bprint(&tabout, ".vs \\n(%du\n", SVS);
+ if (watchout)
+ funnies(i, nl);
+ if (vspf) {
+ for (c = 0; c < ncol; c++)
+ if (vspen(table[nl][c].col) && (nl == 0 || (lf = prev(nl)) < 0 ||
+ !vspen(table[lf][c].col))) {
+ Bprint(&tabout, ".nr ^%c \\n(#^u\n", 'a' + c);
+ topat[c] = nl;
+ }
+ }
+}
+
+
+void
+puttext(char *s, char *fn, char *size)
+{
+ if (point(s)) {
+ putfont(fn);
+ putsize(size);
+ Bprint(&tabout, "%s", s);
+ if (*fn > 0)
+ Bprint(&tabout, "\\f\\n(%2d", S1);
+ if (size != 0)
+ putsize("0");
+ }
+}
+
+
+void
+funnies(int stl, int lin)
+{
+ /* write out funny diverted things */
+ int c, s, pl, lwid, dv, lf, ct;
+ char *fn, *ss;
+
+ Bprint(&tabout, ".mk ##\n"); /* rmember current vertical position */
+ Bprint(&tabout, ".nr %d \\n(##\n", S1); /* bottom position */
+ for (c = 0; c < ncol; c++) {
+ ss = table[lin][c].col;
+ if (point(ss))
+ continue;
+ if (ss == 0)
+ continue;
+ s = (int)ss;
+ Bprint(&tabout, ".sp |\\n(##u-1v\n");
+ Bprint(&tabout, ".nr %d ", SIND);
+ ct = 0;
+ for (pl = stl; pl >= 0 && !isalpha(ct = ctype(pl, c)); pl = prev(pl))
+ ;
+ switch (ct) {
+ case 'n':
+ case 'c':
+ Bprint(&tabout, "(\\n(%2su+\\n(%2su-\\n(%c-u)/2u\n", reg(c, CLEFT),
+ reg(c - 1 + ctspan(lin, c), CRIGHT),
+ s);
+ break;
+ case 'l':
+ Bprint(&tabout, "\\n(%2su\n", reg(c, CLEFT));
+ break;
+ case 'a':
+ Bprint(&tabout, "\\n(%2su\n", reg(c, CMID));
+ break;
+ case 'r':
+ Bprint(&tabout, "\\n(%2su-\\n(%c-u\n", reg(c, CRIGHT), s);
+ break;
+ }
+ Bprint(&tabout, ".in +\\n(%du\n", SIND);
+ fn = font[c][stynum[stl]];
+ putfont(fn);
+ pl = prev(stl);
+ if (stl > 0 && pl >= 0 && vspen(table[pl][c].col)) {
+ Bprint(&tabout, ".sp |\\n(^%cu\n", 'a' + c);
+ if ((flags[c][stynum[stl]] & (CTOP | CDOWN)) == 0) {
+ Bprint(&tabout, ".nr %d \\n(#-u-\\n(^%c-\\n(%c|+1v\n",
+ TMP, 'a' + c, s);
+ Bprint(&tabout, ".if \\n(%d>0 .sp \\n(%du/2u", TMP, TMP);
+ if (pr1403) /* round */
+ Bprint(&tabout, "/1v*1v");
+ Bprint(&tabout, "\n");
+ }
+ }
+ Bprint(&tabout, ".%c+\n", s);
+ Bprint(&tabout, ".in -\\n(%du\n", SIND);
+ if (*fn > 0)
+ putfont("P");
+ Bprint(&tabout, ".mk %d\n", S2);
+ Bprint(&tabout, ".if \\n(%d>\\n(%d .nr %d \\n(%d\n", S2, S1, S1, S2);
+ }
+ Bprint(&tabout, ".sp |\\n(%du\n", S1);
+ for (c = dv = 0; c < ncol; c++) {
+ if (stl + 1 < nlin && (lf = left(stl, c, &lwid)) >= 0) {
+ if (dv++ == 0)
+ Bprint(&tabout, ".sp -1\n");
+ tohcol(c);
+ dv++;
+ drawvert(lf, stl, c, lwid);
+ }
+ }
+ if (dv)
+ Bprint(&tabout, "\n");
+}
+
+
+void
+putfont(char *fn)
+{
+ if (fn && *fn)
+ Bprint(&tabout, fn[1] ? "\\f(%.2s" : "\\f%.2s", fn);
+}
+
+
+void
+putsize(char *s)
+{
+ if (s && *s)
+ Bprint(&tabout, "\\s%s", s);
+}
+
+
diff --git a/src/cmd/tbl/t9.c b/src/cmd/tbl/t9.c
new file mode 100644
index 00000000..bf1978a9
--- /dev/null
+++ b/src/cmd/tbl/t9.c
@@ -0,0 +1,76 @@
+/* t9.c: write lines for tables over 200 lines */
+# include "t.h"
+static useln;
+
+void
+yetmore(void)
+{
+ for (useln = 0; useln < MAXLIN && table[useln] == 0; useln++)
+ ;
+ if (useln >= MAXLIN)
+ error("Wierd. No data in table.");
+ table[0] = table[useln];
+ for (useln = nlin - 1; useln >= 0 && (fullbot[useln] || instead[useln]); useln--)
+ ;
+ if (useln < 0)
+ error("Wierd. No real lines in table.");
+ domore(leftover);
+ while (gets1(cstore = cspace, MAXCHS) && domore(cstore))
+ ;
+ last = cstore;
+ return;
+}
+
+
+int
+domore(char *dataln)
+{
+ int icol, ch;
+
+ if (prefix(".TE", dataln))
+ return(0);
+ if (dataln[0] == '.' && !isdigit(dataln[1])) {
+ Bprint(&tabout, "%s\n", dataln);
+ return(1);
+ }
+ fullbot[0] = 0;
+ instead[0] = (char *)0;
+ if (dataln[1] == 0)
+ switch (dataln[0]) {
+ case '_':
+ fullbot[0] = '-';
+ putline(useln, 0);
+ return(1);
+ case '=':
+ fullbot[0] = '=';
+ putline(useln, 0);
+ return(1);
+ }
+ for (icol = 0; icol < ncol; icol++) {
+ table[0][icol].col = dataln;
+ table[0][icol].rcol = 0;
+ for (; (ch = *dataln) != '\0' && ch != tab; dataln++)
+ ;
+ *dataln++ = '\0';
+ switch (ctype(useln, icol)) {
+ case 'n':
+ table[0][icol].rcol = maknew(table[0][icol].col);
+ break;
+ case 'a':
+ table[0][icol].rcol = table[0][icol].col;
+ table[0][icol].col = "";
+ break;
+ }
+ while (ctype(useln, icol + 1) == 's') /* spanning */
+ table[0][++icol].col = "";
+ if (ch == '\0')
+ break;
+ }
+ while (++icol < ncol)
+ table[0][icol].col = "";
+ putline(useln, 0);
+ exstore = exspace; /* reuse space for numerical items */
+ return(1);
+}
+
+
diff --git a/src/cmd/tbl/tb.c b/src/cmd/tbl/tb.c
new file mode 100644
index 00000000..5cc59880
--- /dev/null
+++ b/src/cmd/tbl/tb.c
@@ -0,0 +1,101 @@
+/* tb.c: check which entries exist, also storage allocation */
+# include "t.h"
+
+void
+checkuse(void)
+{
+ int i, c, k;
+
+ for (c = 0; c < ncol; c++) {
+ used[c] = lused[c] = rused[c] = 0;
+ for (i = 0; i < nlin; i++) {
+ if (instead[i] || fullbot[i])
+ continue;
+ k = ctype(i, c);
+ if (k == '-' || k == '=')
+ continue;
+ if ((k == 'n' || k == 'a')) {
+ rused[c] |= real(table[i][c].rcol);
+ if ( !real(table[i][c].rcol))
+ used[c] |= real(table[i][c].col);
+ if (table[i][c].rcol)
+ lused[c] |= real(table[i][c].col);
+ } else
+ used[c] |= real(table[i][c].col);
+ }
+ }
+}
+
+
+int
+real(char *s)
+{
+ if (s == 0)
+ return(0);
+ if (!point(s))
+ return(1);
+ if (*s == 0)
+ return(0);
+ return(1);
+}
+
+
+int spcount = 0;
+# define MAXVEC 20
+char *spvecs[MAXVEC];
+
+char *
+chspace(void)
+{
+ char *pp;
+
+ if (spvecs[spcount])
+ return(spvecs[spcount++]);
+ if (spcount >= MAXVEC)
+ error("Too many characters in table");
+ spvecs[spcount++] = pp = calloc(MAXCHS + MAXLINLEN, 1);
+ if (pp == (char *) - 1 || pp == (char *)0)
+ error("no space for characters");
+ return(pp);
+}
+
+
+# define MAXPC 50
+char *thisvec;
+int tpcount = -1;
+char *tpvecs[MAXPC];
+
+int *
+alocv(int n)
+{
+ int *tp, *q;
+
+ if (tpcount < 0 || thisvec + n > tpvecs[tpcount] + MAXCHS) {
+ tpcount++;
+ if (tpvecs[tpcount] == 0) {
+ tpvecs[tpcount] = calloc(MAXCHS, 1);
+ }
+ thisvec = tpvecs[tpcount];
+ if (thisvec == (char *)0)
+ error("no space for vectors");
+ }
+ tp = (int *)thisvec;
+ thisvec += n;
+ for (q = tp; q < (int *)thisvec; q++)
+ *q = 0;
+ return(tp);
+}
+
+
+void
+release(void)
+{
+ /* give back unwanted space in some vectors */
+ /* this should call free; it does not because
+ alloc() is so buggy */
+ spcount = 0;
+ tpcount = -1;
+ exstore = 0;
+}
+
+
diff --git a/src/cmd/tbl/tc.c b/src/cmd/tbl/tc.c
new file mode 100644
index 00000000..635dbf8a
--- /dev/null
+++ b/src/cmd/tbl/tc.c
@@ -0,0 +1,65 @@
+/* tc.c: find character not in table to delimit fields */
+# include "t.h"
+
+void
+choochar(void)
+{
+ /* choose funny characters to delimit fields */
+ int had[128], ilin, icol, k;
+ char *s;
+
+ for (icol = 0; icol < 128; icol++)
+ had[icol] = 0;
+ F1 = F2 = 0;
+ for (ilin = 0; ilin < nlin; ilin++) {
+ if (instead[ilin])
+ continue;
+ if (fullbot[ilin])
+ continue;
+ for (icol = 0; icol < ncol; icol++) {
+ k = ctype(ilin, icol);
+ if (k == 0 || k == '-' || k == '=')
+ continue;
+ s = table[ilin][icol].col;
+ if (point(s))
+ while (*s)
+ had[*s++] = 1;
+ s = table[ilin][icol].rcol;
+ if (point(s))
+ while (*s)
+ had[*s++] = 1;
+ }
+ }
+ /* choose first funny character */
+ for (
+ s = "\002\003\005\006\007!%&#/?,:;<=>@`^~_{}+-*ABCDEFGHIJKMNOPQRSTUVWXYZabcdefgjkoqrstwxyz";
+ *s; s++) {
+ if (had[*s] == 0) {
+ F1 = *s;
+ had[F1] = 1;
+ break;
+ }
+ }
+ /* choose second funny character */
+ for (
+ s = "\002\003\005\006\007:_~^`@;,<=>#%&!/?{}+-*ABCDEFGHIJKMNOPQRSTUVWXZabcdefgjkoqrstuwxyz";
+ *s; s++) {
+ if (had[*s] == 0) {
+ F2 = *s;
+ break;
+ }
+ }
+ if (F1 == 0 || F2 == 0)
+ error("couldn't find characters to use for delimiters");
+ return;
+}
+
+
+int
+point(char *s)
+{
+ int ss = (int)s;
+ return(ss >= 128 || ss < 0);
+}
+
+
diff --git a/src/cmd/tbl/te.c b/src/cmd/tbl/te.c
new file mode 100644
index 00000000..3df8d445
--- /dev/null
+++ b/src/cmd/tbl/te.c
@@ -0,0 +1,75 @@
+/* te.c: error message control, input line count */
+# include "t.h"
+
+void
+error(char *s)
+{
+ fprint(2, "\n%s:%d: %s\n", ifile, iline, s);
+ fprint(2, "tbl quits\n");
+ exits(s);
+}
+
+
+char *
+gets1(char *s, int size)
+{
+ char *p, *ns;
+ int nbl;
+
+ iline++;
+ ns = s;
+ p = Brdline(tabin, '\n');
+ while (p == 0) {
+ if (swapin() == 0)
+ return(0);
+ p = Brdline(tabin, '\n');
+ }
+ nbl = Blinelen(tabin)-1;
+ if(nbl >= size)
+ error("input buffer too small");
+ p[nbl] = 0;
+ strcpy(s, p);
+ s += nbl;
+ for (nbl = 0; *s == '\\' && s > ns; s--)
+ nbl++;
+ if (linstart && nbl % 2) /* fold escaped nl if in table */
+ gets1(s + 1, size - (s-ns));
+
+ return(p);
+}
+
+
+# define BACKMAX 500
+char backup[BACKMAX];
+char *backp = backup;
+
+void
+un1getc(int c)
+{
+ if (c == '\n')
+ iline--;
+ *backp++ = c;
+ if (backp >= backup + BACKMAX)
+ error("too much backup");
+}
+
+
+int
+get1char(void)
+{
+ int c;
+ if (backp > backup)
+ c = *--backp;
+ else
+ c = Bgetc(tabin);
+ if (c == 0) /* EOF */ {
+ if (swapin() == 0)
+ error("unexpected EOF");
+ c = Bgetc(tabin);
+ }
+ if (c == '\n')
+ iline++;
+ return(c);
+}
+
+
diff --git a/src/cmd/tbl/tf.c b/src/cmd/tbl/tf.c
new file mode 100644
index 00000000..3791c32f
--- /dev/null
+++ b/src/cmd/tbl/tf.c
@@ -0,0 +1,74 @@
+/* tf.c: save and restore fill mode around table */
+# include "t.h"
+
+void
+savefill(void)
+{
+ /* remembers various things: fill mode, vs, ps in mac 35 (SF) */
+ Bprint(&tabout, ".de %d\n", SF);
+ Bprint(&tabout, ".ps \\n(.s\n");
+ Bprint(&tabout, ".vs \\n(.vu\n");
+ Bprint(&tabout, ".in \\n(.iu\n");
+ Bprint(&tabout, ".if \\n(.u .fi\n");
+ Bprint(&tabout, ".if \\n(.j .ad\n");
+ Bprint(&tabout, ".if \\n(.j=0 .na\n");
+ Bprint(&tabout, "..\n");
+ Bprint(&tabout, ".nf\n");
+ /* set obx offset if useful */
+ Bprint(&tabout, ".nr #~ 0\n");
+ Bprint(&tabout, ".if \\n(.T .if n .nr #~ 0.6n\n");
+}
+
+
+void
+rstofill(void)
+{
+ Bprint(&tabout, ".%d\n", SF);
+}
+
+
+void
+endoff(void)
+{
+ int i;
+
+ for (i = 0; i < MAXHEAD; i++)
+ if (linestop[i])
+ Bprint(&tabout, ".nr #%c 0\n", linestop[i] + 'a' - 1);
+ for (i = 0; i < texct; i++)
+ Bprint(&tabout, ".rm %c+\n", texstr[i]);
+ Bprint(&tabout, "%s\n", last);
+}
+
+
+void
+ifdivert(void)
+{
+ Bprint(&tabout, ".ds #d .d\n");
+ Bprint(&tabout, ".if \\(ts\\n(.z\\(ts\\(ts .ds #d nl\n");
+}
+
+
+void
+saveline(void)
+{
+ Bprint(&tabout, ".if \\n+(b.=1 .nr d. \\n(.c-\\n(c.-1\n");
+ linstart = iline;
+}
+
+
+void
+restline(void)
+{
+ Bprint(&tabout, ".if \\n-(b.=0 .nr c. \\n(.c-\\n(d.-%d\n", iline - linstart);
+ linstart = 0;
+}
+
+
+void
+cleanfc(void)
+{
+ Bprint(&tabout, ".fc\n");
+}
+
+
diff --git a/src/cmd/tbl/tg.c b/src/cmd/tbl/tg.c
new file mode 100644
index 00000000..6abb1490
--- /dev/null
+++ b/src/cmd/tbl/tg.c
@@ -0,0 +1,81 @@
+/* tg.c: process included text blocks */
+# include "t.h"
+
+int
+gettext(char *sp, int ilin, int icol, char *fn, char *sz)
+{
+ /* get a section of text */
+ char line[4096];
+ int oname;
+ char *vs;
+
+ if (texname == 0)
+ error("Too many text block diversions");
+ if (textflg == 0) {
+ Bprint(&tabout, ".nr %d \\n(.lu\n", SL); /* remember old line length */
+ textflg = 1;
+ }
+ Bprint(&tabout, ".eo\n");
+ Bprint(&tabout, ".am %s\n", reg(icol, CRIGHT));
+ Bprint(&tabout, ".br\n");
+ Bprint(&tabout, ".di %c+\n", texname);
+ rstofill();
+ if (fn && *fn)
+ Bprint(&tabout, ".nr %d \\n(.f\n.ft %s\n", S1, fn);
+ Bprint(&tabout, ".ft \\n(.f\n"); /* protect font */
+ vs = vsize[icol][stynum[ilin]];
+ if ((sz && *sz) || (vs && *vs)) {
+ Bprint(&tabout, ".nr %d \\n(.v\n", S9);
+ if (vs == 0 || *vs == 0)
+ vs = "\\n(.s+2";
+ if (sz && *sz)
+ Bprint(&tabout, ".ps %s\n", sz);
+ Bprint(&tabout, ".vs %s\n", vs);
+ Bprint(&tabout, ".if \\n(%du>\\n(.vu .sp \\n(%du-\\n(.vu\n", S9, S9);
+ }
+ if (cll[icol][0])
+ Bprint(&tabout, ".ll %sn\n", cll[icol]);
+ else
+ Bprint(&tabout, ".ll \\n(%du*%du/%du\n", SL, ctspan(ilin, icol), ncol + 1);
+ Bprint(&tabout, ".if \\n(.l<\\n(%2s .ll \\n(%2su\n", reg(icol, CRIGHT),
+ reg(icol, CRIGHT));
+ if (ctype(ilin, icol) == 'a')
+ Bprint(&tabout, ".ll -2n\n");
+ Bprint(&tabout, ".in 0\n");
+ while (gets1(line, sizeof(line))) {
+ if (line[0] == 'T' && line[1] == '}' && line[2] == tab)
+ break;
+ if (match("T}", line))
+ break;
+ Bprint(&tabout, "%s\n", line);
+ }
+ if (fn && *fn)
+ Bprint(&tabout, ".ft \\n(%d\n", S1);
+ if (sz && *sz)
+ Bprint(&tabout, ".br\n.ps\n.vs\n");
+ Bprint(&tabout, ".br\n");
+ Bprint(&tabout, ".di\n");
+ Bprint(&tabout, ".nr %c| \\n(dn\n", texname);
+ Bprint(&tabout, ".nr %c- \\n(dl\n", texname);
+ Bprint(&tabout, "..\n");
+ Bprint(&tabout, ".ec \\\n");
+ /* copy remainder of line */
+ if (line[2])
+ tcopy (sp, line + 3);
+ else
+ *sp = 0;
+ oname = texname;
+ texname = texstr[++texct];
+ return(oname);
+}
+
+
+void
+untext(void)
+{
+ rstofill();
+ Bprint(&tabout, ".nf\n");
+ Bprint(&tabout, ".ll \\n(%du\n", SL);
+}
+
+
diff --git a/src/cmd/tbl/ti.c b/src/cmd/tbl/ti.c
new file mode 100644
index 00000000..ef995bbb
--- /dev/null
+++ b/src/cmd/tbl/ti.c
@@ -0,0 +1,75 @@
+/* ti.c: classify line intersections */
+# include "t.h"
+/* determine local environment for intersections */
+
+int
+interv(int i, int c)
+{
+ int ku, kl;
+
+ if (c >= ncol || c == 0) {
+ if (dboxflg) {
+ if (i == 0)
+ return(BOT);
+ if (i >= nlin)
+ return(TOP);
+ return(THRU);
+ }
+ if (c >= ncol)
+ return(0);
+ }
+ ku = i > 0 ? lefdata(i - 1, c) : 0;
+ if (i + 1 >= nlin && allh(i))
+ kl = 0;
+ else
+ kl = lefdata(allh(i) ? i + 1 : i, c);
+ if (ku == 2 && kl == 2)
+ return(THRU);
+ if (ku == 2)
+ return(TOP);
+ if (kl == BOT)
+ return(2);
+ return(0);
+}
+
+
+int
+interh(int i, int c)
+{
+ int kl, kr;
+
+ if (fullbot[i] == '=' || (dboxflg && (i == 0 || i >= nlin - 1))) {
+ if (c == ncol)
+ return(LEFT);
+ if (c == 0)
+ return(RIGHT);
+ return(THRU);
+ }
+ if (i >= nlin)
+ return(0);
+ kl = c > 0 ? thish (i, c - 1) : 0;
+ if (kl <= 1 && i > 0 && allh(up1(i)))
+ kl = c > 0 ? thish(up1(i), c - 1) : 0;
+ kr = thish(i, c);
+ if (kr <= 1 && i > 0 && allh(up1(i)))
+ kr = c > 0 ? thish(up1(i), c) : 0;
+ if (kl == '=' && kr == '=')
+ return(THRU);
+ if (kl == '=')
+ return(LEFT);
+ if (kr == '=')
+ return(RIGHT);
+ return(0);
+}
+
+
+int
+up1(int i)
+{
+ i--;
+ while (instead[i] && i > 0)
+ i--;
+ return(i);
+}
+
+
diff --git a/src/cmd/tbl/tm.c b/src/cmd/tbl/tm.c
new file mode 100644
index 00000000..8fa4e497
--- /dev/null
+++ b/src/cmd/tbl/tm.c
@@ -0,0 +1,65 @@
+/* tm.c: split numerical fields */
+# include "t.h"
+
+char *
+maknew(char *str)
+{
+ /* make two numerical fields */
+ int dpoint, c;
+ char *p, *q, *ba;
+
+ p = str;
+ for (ba = 0; c = *str; str++)
+ if (c == '\\' && *(str + 1) == '&')
+ ba = str;
+ str = p;
+ if (ba == 0) {
+ for (dpoint = 0; *str; str++) {
+ if (*str == '.' && !ineqn(str, p) &&
+ (str > p && digit(*(str - 1)) ||
+ digit(*(str + 1))))
+ dpoint = (int)str;
+ }
+ if (dpoint == 0)
+ for (; str > p; str--) {
+ if (digit( *(str - 1) ) && !ineqn(str, p))
+ break;
+ }
+ if (!dpoint && p == str) /* not numerical, don't split */
+ return(0);
+ if (dpoint)
+ str = (char *)dpoint;
+ } else
+ str = ba;
+ p = str;
+ if (exstore == 0 || exstore > exlim) {
+ exstore = exspace = chspace();
+ exlim = exstore + MAXCHS;
+ }
+ q = exstore;
+ while (*exstore++ = *str++)
+ ;
+ *p = 0;
+ return(q);
+}
+
+
+int
+ineqn (char *s, char *p)
+{
+ /* true if s is in a eqn within p */
+ int ineq = 0, c;
+
+ while (c = *p) {
+ if (s == p)
+ return(ineq);
+ p++;
+ if ((ineq == 0) && (c == delim1))
+ ineq = 1;
+ else if ((ineq == 1) && (c == delim2))
+ ineq = 0;
+ }
+ return(0);
+}
+
+
diff --git a/src/cmd/tbl/tr.c b/src/cmd/tbl/tr.c
new file mode 100644
index 00000000..7d586e8b
--- /dev/null
+++ b/src/cmd/tbl/tr.c
@@ -0,0 +1,28 @@
+# include "t.h"
+/* tr.c: number register allocation */
+char *nregs[] = {
+ /* this array must have at least 3*qcol entries
+ or illegal register names will result */
+ "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
+ "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
+ "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
+ "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
+ "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
+ "90", "91", "92", "93", "94", "95", "96", "97", "4q", "4r",
+ "4s", "4t", "4u", "4v", "4w", "4x", "4y", "4z", "4;", "4.",
+ "4a", "4b", "4c", "4d", "4e", "4f", "4g", "4h", "4i", "4j",
+ "4k", "4l", "4m", "4n", "4o", "4p", "5a", "5b", "5c", "5d",
+ "5e", "5f", "5g", "5h", "5i", "5j", "5k", "5l", "5m", "5n",
+ "5o", "5p", "5q", "5r", "5s", "5t", "5u", "5v", "5w", "5x",
+ 0};
+
+
+char *
+reg(int col, int place)
+{
+ if (sizeof(nregs) < 2 * 3 * qcol)
+ error("Too many columns for registers");
+ return (nregs[qcol*place+col]);
+}
+
+
diff --git a/src/cmd/tbl/ts.c b/src/cmd/tbl/ts.c
new file mode 100644
index 00000000..43cc84ec
--- /dev/null
+++ b/src/cmd/tbl/ts.c
@@ -0,0 +1,71 @@
+/* ts.c: minor string processing subroutines */
+#include "t.h"
+
+int
+match (char *s1, char *s2)
+{
+ while (*s1 == *s2)
+ if (*s1++ == '\0')
+ return(1);
+ else
+ s2++;
+ return(0);
+}
+
+
+int
+prefix(char *small, char *big)
+{
+ int c;
+
+ while ((c = *small++) == *big++)
+ if (c == 0)
+ return(1);
+ return(c == 0);
+}
+
+
+int
+letter (int ch)
+{
+ if (ch >= 'a' && ch <= 'z')
+ return(1);
+ if (ch >= 'A' && ch <= 'Z')
+ return(1);
+ return(0);
+}
+
+
+int
+numb(char *str)
+{
+ /* convert to integer */
+ int k;
+ for (k = 0; *str >= '0' && *str <= '9'; str++)
+ k = k * 10 + *str - '0';
+ return(k);
+}
+
+
+int
+digit(int x)
+{
+ return(x >= '0' && x <= '9');
+}
+
+
+int
+max(int a, int b)
+{
+ return( a > b ? a : b);
+}
+
+
+void
+tcopy (char *s, char *t)
+{
+ while (*s++ = *t++)
+ ;
+}
+
+
diff --git a/src/cmd/tbl/tt.c b/src/cmd/tbl/tt.c
new file mode 100644
index 00000000..96270b75
--- /dev/null
+++ b/src/cmd/tbl/tt.c
@@ -0,0 +1,127 @@
+/* tt.c: subroutines for drawing horizontal lines */
+# include "t.h"
+
+int
+ctype(int il, int ic)
+{
+ if (instead[il])
+ return(0);
+ if (fullbot[il])
+ return(0);
+ il = stynum[il];
+ return(style[ic][il]);
+}
+
+
+int
+min(int a, int b)
+{
+ return(a < b ? a : b);
+}
+
+
+int
+fspan(int i, int c)
+{
+ c++;
+ return(c < ncol && ctype(i, c) == 's');
+}
+
+
+int
+lspan(int i, int c)
+{
+ int k;
+
+ if (ctype(i, c) != 's')
+ return(0);
+ c++;
+ if (c < ncol && ctype(i, c) == 's')
+ return(0);
+ for (k = 0; ctype(i, --c) == 's'; k++)
+ ;
+ return(k);
+}
+
+
+int
+ctspan(int i, int c)
+{
+ int k;
+ c++;
+ for (k = 1; c < ncol && ctype(i, c) == 's'; k++)
+ c++;
+ return(k);
+}
+
+
+void
+tohcol(int ic)
+{
+ if (ic == 0)
+ Bprint(&tabout, "\\h'|0'");
+ else
+ Bprint(&tabout, "\\h'(|\\n(%2su+|\\n(%2su)/2u'", reg(ic, CLEFT),
+ reg(ic - 1, CRIGHT));
+}
+
+
+int
+allh(int i)
+{
+ /* return true if every element in line i is horizontal */
+ /* also at least one must be horizontl */
+ int c, one, k;
+
+ if (fullbot[i])
+ return(1);
+ if (i >= nlin)
+ return(dboxflg || boxflg);
+ for (one = c = 0; c < ncol; c++) {
+ k = thish(i, c);
+ if (k == 0)
+ return(0);
+ if (k == 1)
+ continue;
+ one = 1;
+ }
+ return(one);
+}
+
+
+int
+thish(int i, int c)
+{
+ int t;
+ char *s;
+ struct colstr *pc;
+
+ if (c < 0)
+ return(0);
+ if (i < 0)
+ return(0);
+ t = ctype(i, c);
+ if (t == '_' || t == '-')
+ return('-');
+ if (t == '=')
+ return('=');
+ if (t == '^')
+ return(1);
+ if (fullbot[i] )
+ return(fullbot[i]);
+ if (t == 's')
+ return(thish(i, c - 1));
+ if (t == 0)
+ return(1);
+ pc = &table[i][c];
+ s = (t == 'a' ? pc->rcol : pc->col);
+ if (s == 0 || (point(s) && *s == 0))
+ return(1);
+ if (vspen(s))
+ return(1);
+ if (t = barent( s))
+ return(t);
+ return(0);
+}
+
+
diff --git a/src/cmd/tbl/tu.c b/src/cmd/tbl/tu.c
new file mode 100644
index 00000000..217869e1
--- /dev/null
+++ b/src/cmd/tbl/tu.c
@@ -0,0 +1,257 @@
+/* tu.c: draws horizontal lines */
+# include "t.h"
+
+void
+makeline(int i, int c, int lintype)
+{
+ int cr, type, shortl;
+
+ type = thish(i, c);
+ if (type == 0)
+ return;
+ shortl = (table[i][c].col[0] == '\\');
+ if (c > 0 && !shortl && thish(i, c - 1) == type)
+ return;
+ if (shortl == 0)
+ for (cr = c; cr < ncol && (ctype(i, cr) == 's' || type == thish(i, cr)); cr++)
+ ;
+ else
+ for (cr = c + 1; cr < ncol && ctype(i, cr) == 's'; cr++)
+ ;
+ drawline(i, c, cr - 1, lintype, 0, shortl);
+}
+
+
+void
+fullwide(int i, int lintype)
+{
+ int cr, cl;
+
+ if (!pr1403)
+ Bprint(&tabout, ".nr %d \\n(.v\n.vs \\n(.vu-\\n(.sp\n", SVS);
+ cr = 0;
+ while (cr < ncol) {
+ cl = cr;
+ while (i > 0 && vspand(prev(i), cl, 1))
+ cl++;
+ for (cr = cl; cr < ncol; cr++)
+ if (i > 0 && vspand(prev(i), cr, 1))
+ break;
+ if (cl < ncol)
+ drawline(i, cl, (cr < ncol ? cr - 1 : cr), lintype, 1, 0);
+ }
+ Bprint(&tabout, "\n");
+ if (!pr1403)
+ Bprint(&tabout, ".vs \\n(%du\n", SVS);
+}
+
+
+void
+drawline(int i, int cl, int cr, int lintype, int noheight, int shortl)
+{
+ char *exhr, *exhl, *lnch;
+ int lcount, ln, linpos, oldpos, nodata;
+
+ lcount = 0;
+ exhr = exhl = "";
+ switch (lintype) {
+ case '-':
+ lcount = 1;
+ break;
+ case '=':
+ lcount = pr1403 ? 1 : 2;
+ break;
+ case SHORTLINE:
+ lcount = 1;
+ break;
+ }
+ if (lcount <= 0)
+ return;
+ nodata = cr - cl >= ncol || noheight || allh(i);
+ if (!nodata)
+ Bprint(&tabout, "\\v'-.5m'");
+ for (ln = oldpos = 0; ln < lcount; ln++) {
+ linpos = 2 * ln - lcount + 1;
+ if (linpos != oldpos)
+ Bprint(&tabout, "\\v'%dp'", linpos - oldpos);
+ oldpos = linpos;
+ if (shortl == 0) {
+ tohcol(cl);
+ if (lcount > 1) {
+ switch (interv(i, cl)) {
+ case TOP:
+ exhl = ln == 0 ? "1p" : "-1p";
+ break;
+ case BOT:
+ exhl = ln == 1 ? "1p" : "-1p";
+ break;
+ case THRU:
+ exhl = "1p";
+ break;
+ }
+ if (exhl[0])
+ Bprint(&tabout, "\\h'%s'", exhl);
+ } else if (lcount == 1) {
+ switch (interv(i, cl)) {
+ case TOP:
+ case BOT:
+ exhl = "-1p";
+ break;
+ case THRU:
+ exhl = "1p";
+ break;
+ }
+ if (exhl[0])
+ Bprint(&tabout, "\\h'%s'", exhl);
+ }
+ if (lcount > 1) {
+ switch (interv(i, cr + 1)) {
+ case TOP:
+ exhr = ln == 0 ? "-1p" : "+1p";
+ break;
+ case BOT:
+ exhr = ln == 1 ? "-1p" : "+1p";
+ break;
+ case THRU:
+ exhr = "-1p";
+ break;
+ }
+ } else if (lcount == 1) {
+ switch (interv(i, cr + 1)) {
+ case TOP:
+ case BOT:
+ exhr = "+1p";
+ break;
+ case THRU:
+ exhr = "-1p";
+ break;
+ }
+ }
+ } else
+ Bprint(&tabout, "\\h'|\\n(%2su'", reg(cl, CLEFT));
+ Bprint(&tabout, "\\s\\n(%d", LSIZE);
+ if (linsize)
+ Bprint(&tabout, "\\v'-\\n(%dp/6u'", LSIZE);
+ if (shortl)
+ Bprint(&tabout, "\\l'|\\n(%2su'", reg(cr, CRIGHT));
+ else
+ {
+ lnch = "\\(ul";
+ if (pr1403)
+ lnch = lintype == 2 ? "=" : "\\(ru";
+ if (cr + 1 >= ncol)
+ Bprint(&tabout, "\\l'|\\n(TWu%s%s'", exhr, lnch);
+ else
+ Bprint(&tabout, "\\l'(|\\n(%2su+|\\n(%2su)/2u%s%s'", reg(cr, CRIGHT),
+ reg(cr + 1, CLEFT), exhr, lnch);
+ }
+ if (linsize)
+ Bprint(&tabout, "\\v'\\n(%dp/6u'", LSIZE);
+ Bprint(&tabout, "\\s0");
+ }
+ if (oldpos != 0)
+ Bprint(&tabout, "\\v'%dp'", -oldpos);
+ if (!nodata)
+ Bprint(&tabout, "\\v'+.5m'");
+}
+
+
+void
+getstop(void)
+{
+ int i, c, k, junk, stopp;
+
+ stopp = 1;
+ for (i = 0; i < MAXLIN; i++)
+ linestop[i] = 0;
+ for (i = 0; i < nlin; i++)
+ for (c = 0; c < ncol; c++) {
+ k = left(i, c, &junk);
+ if (k >= 0 && linestop[k] == 0)
+ linestop[k] = ++stopp;
+ }
+ if (boxflg || allflg || dboxflg)
+ linestop[0] = 1;
+}
+
+
+int
+left(int i, int c, int *lwidp)
+{
+ int kind, li, lj;
+ /* returns -1 if no line to left */
+ /* returns number of line where it starts */
+ /* stores into lwid the kind of line */
+ *lwidp = 0;
+ if (i < 0)
+ return(-1);
+ kind = lefdata(i, c);
+ if (kind == 0)
+ return(-1);
+ if (i + 1 < nlin)
+ if (lefdata(next(i), c) == kind)
+ return(-1);
+ li = i;
+ while (i >= 0 && lefdata(i, c) == kind)
+ i = prev(li = i);
+ if (prev(li) == -1)
+ li = 0;
+ *lwidp = kind;
+ for (lj = i + 1; lj < li; lj++)
+ if (instead[lj] && strcmp(instead[lj], ".TH") == 0)
+ return(li);
+ for (i = i + 1; i < li; i++)
+ if (fullbot[i])
+ li = i;
+ return(li);
+}
+
+
+int
+lefdata(int i, int c)
+{
+ int ck;
+
+ if (i >= nlin)
+ i = nlin - 1;
+ if (ctype(i, c) == 's') {
+ for (ck = c; ctype(i, ck) == 's'; ck--)
+ ;
+ if (thish(i, ck) == 0)
+ return(0);
+ }
+ i = stynum[i];
+ i = lefline[c][i];
+ if (i > 0)
+ return(i);
+ if (dboxflg && c == 0)
+ return(2);
+ if (allflg)
+ return(1);
+ if (boxflg && c == 0)
+ return(1);
+ return(0);
+}
+
+
+int
+next(int i)
+{
+ while (i + 1 < nlin) {
+ i++;
+ if (!fullbot[i] && !instead[i])
+ break;
+ }
+ return(i);
+}
+
+
+int
+prev(int i)
+{
+ while (--i >= 0 && (fullbot[i] || instead[i]))
+ ;
+ return(i);
+}
+
+
diff --git a/src/cmd/tbl/tv.c b/src/cmd/tbl/tv.c
new file mode 100644
index 00000000..19a4b03f
--- /dev/null
+++ b/src/cmd/tbl/tv.c
@@ -0,0 +1,183 @@
+/* tv.c: draw vertical lines */
+# include "t.h"
+
+void
+drawvert(int start, int end, int c, int lwid)
+{
+ char *exb = 0, *ext = 0;
+ int tp = 0, sl, ln, pos, epb, ept, vm;
+
+ end++;
+ vm = 'v';
+ /* note: nr 35 has value of 1m outside of linesize */
+ while (instead[end])
+ end++;
+ for (ln = 0; ln < lwid; ln++) {
+ epb = ept = 0;
+ pos = 2 * ln - lwid + 1;
+ if (pos != tp)
+ Bprint(&tabout, "\\h'%dp'", pos - tp);
+ tp = pos;
+ if (end < nlin) {
+ if (fullbot[end] || (!instead[end] && allh(end)))
+ epb = 2;
+ else
+ switch (midbar(end, c)) {
+ case '-':
+ exb = "1v-.5m";
+ break;
+ case '=':
+ exb = "1v-.5m";
+ epb = 1;
+ break;
+ }
+ }
+ if (lwid > 1)
+ switch (interh(end, c)) {
+ case THRU:
+ epb -= 1;
+ break;
+ case RIGHT:
+ epb += (ln == 0 ? 1 : -1);
+ break;
+ case LEFT:
+ epb += (ln == 1 ? 1 : -1);
+ break;
+ }
+ if (lwid == 1)
+ switch (interh(end, c)) {
+ case THRU:
+ epb -= 1;
+ break;
+ case RIGHT:
+ case LEFT:
+ epb += 1;
+ break;
+ }
+ if (start > 0) {
+ sl = start - 1;
+ while (sl >= 0 && instead[sl])
+ sl--;
+ if (sl >= 0 && (fullbot[sl] || allh(sl)))
+ ept = 0;
+ else if (sl >= 0)
+ switch (midbar(sl, c)) {
+ case '-':
+ ext = ".5m";
+ break;
+ case '=':
+ ext = ".5m";
+ ept = -1;
+ break;
+ default:
+ vm = 'm';
+ break;
+ }
+ else
+ ept = -4;
+ } else if (start == 0 && allh(0)) {
+ ept = 0;
+ vm = 'm';
+ }
+ if (lwid > 1)
+ switch (interh(start, c)) {
+ case THRU:
+ ept += 1;
+ break;
+ case LEFT:
+ ept += (ln == 0 ? 1 : -1);
+ break;
+ case RIGHT:
+ ept += (ln == 1 ? 1 : -1);
+ break;
+ }
+ else if (lwid == 1)
+ switch (interh(start, c)) {
+ case THRU:
+ ept += 1;
+ break;
+ case LEFT:
+ case RIGHT:
+ ept -= 1;
+ break;
+ }
+ if (exb)
+ Bprint(&tabout, "\\v'%s'", exb);
+ if (epb)
+ Bprint(&tabout, "\\v'%dp'", epb);
+ Bprint(&tabout, "\\s\\n(%d", LSIZE);
+ if (linsize)
+ Bprint(&tabout, "\\v'-\\n(%dp/6u'", LSIZE);
+ Bprint(&tabout, "\\h'-\\n(#~u'"); /* adjustment for T450 nroff boxes */
+ Bprint(&tabout, "\\L'|\\n(#%cu-%s", linestop[start] + 'a' - 1,
+ vm == 'v' ? "1v" : "\\n(35u");
+ if (ext)
+ Bprint(&tabout, "-(%s)", ext);
+ if (exb)
+ Bprint(&tabout, "-(%s)", exb);
+ pos = ept - epb;
+ if (pos)
+ Bprint(&tabout, "%s%dp", pos >= 0 ? "+" : "", pos);
+ /* the string #d is either "nl" or ".d" depending
+ on diversions; on GCOS not the same */
+ Bprint(&tabout, "'\\s0\\v'\\n(\\*(#du-\\n(#%cu+%s",
+ linestop[start] + 'a' - 1, vm == 'v' ? "1v" : "\\n(35u");
+ if (ext)
+ Bprint(&tabout, "+%s", ext);
+ if (ept)
+ Bprint(&tabout, "%s%dp", (-ept) > 0 ? "+" : "", (-ept));
+ Bprint(&tabout, "'");
+ if (linsize)
+ Bprint(&tabout, "\\v'\\n(%dp/6u'", LSIZE);
+ }
+}
+
+
+int
+midbar(int i, int c)
+{
+ int k;
+
+ k = midbcol(i, c);
+ if (k == 0 && c > 0)
+ k = midbcol(i, c - 1);
+ return(k);
+}
+
+
+int
+midbcol(int i, int c)
+{
+ int ct;
+
+ while ( (ct = ctype(i, c)) == 's')
+ c--;
+ if (ct == '-' || ct == '=')
+ return(ct);
+ if (ct = barent(table[i][c].col))
+ return(ct);
+ return(0);
+}
+
+
+int
+barent(char *s)
+{
+ if (s == 0)
+ return (1);
+ if (!point(s))
+ return(0);
+ if (s[0] == '\\')
+ s++;
+ if (s[1] != 0)
+ return(0);
+ switch (s[0]) {
+ case '_':
+ return('-');
+ case '=':
+ return('=');
+ }
+ return(0);
+}
+
+