diff options
Diffstat (limited to 'src/cmd/tbl/t4.c')
-rw-r--r-- | src/cmd/tbl/t4.c | 405 |
1 files changed, 405 insertions, 0 deletions
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); +} + + |