|
|
researchv10 Norman
#include <ctype.h>
#include "tdef.h"
extern
#include "d.h"
extern
#include "v.h"
#ifdef NROFF
extern
#include "tw.h"
#endif
#include "s.h"
/*
troff4.c
number registers, conversion, arithmetic
*/
#include <sgtty.h>
#include "ext.h"
int regcnt = NNAMES;
int falsef = 0; /* on if inside false branch of if */
setn()
{
register i, j;
tchar ii;
int f;
f = nform = 0;
if ((i = cbits(ii = getch())) == '+')
f = 1;
else if (i == '-')
f = -1;
else
ch = ii;
if (falsef)
f = 0;
if ((i = getsn()) == 0)
return;
if ((i & 0177) == '.')
switch (i >> BYTE) {
case 's':
i = pts;
break;
case 'v':
i = lss;
break;
case 'f':
i = font;
break;
case 'p':
i = pl;
break;
case 't':
i = findt1();
break;
case 'o':
i = po;
break;
case 'l':
i = ll;
break;
case 'i':
i = in;
break;
case '$':
i = frame->nargs;
break;
case 'A':
i = ascii;
break;
case 'c':
i = v.cd;
break;
case 'n':
i = lastl;
break;
case 'a':
i = ralss;
break;
case 'h':
i = dip->hnl;
break;
case 'd':
if (dip != d)
i = dip->dnl;
else
i = v.nl;
break;
case 'u':
i = fi;
break;
case 'j':
i = ad + 2 * admod;
break;
case 'w':
i = width(*(pinchar-1)); /* XXX */
break;
case 'x':
i = nel;
break;
case 'y':
i = un;
break;
case 'T':
i = dotT;
break; /*-Tterm used in nroff*/
case 'V':
i = VERT;
break;
case 'H':
i = HOR;
break;
case 'k':
i = ne;
break;
case 'P':
i = print;
break;
case 'L':
i = ls;
break;
case 'R':
i = NN - regcnt;
break;
case 'z':
i = dip->curd;
cbuf[0] = i & BMASK;
cbuf[1] = (i >> BYTE) & BMASK;
cbuf[2] = 0;
cp = cbuf;
return;
case 'b':
i = bdtab[font];
break;
default:
goto s0;
}
else {
s0:
if ((j = findr(i)) == -1)
i = 0;
else {
i = (vlist[j] = (vlist[j] + inc[j] * f));
nform = fmt[j];
}
}
setn1(i);
cp = cbuf;
}
setn1(i)
int i;
{
extern int wrc();
cp = cbuf;
nrbits = 0;
fnumb(i, wrc);
*cp = 0;
cp = cbuf;
}
findr(i)
register int i;
{
register j;
register int *p;
if (i == 0)
return(-1);
for (p = r; p < &r[NN]; p++) {
if (i == *p)
break;
}
if (p != &r[NN])
return(p - r);
for (p = r; p < &r[NN]; p++) {
if (*p == 0) {
*p = i;
regcnt++;
break;
}
}
if (p == &r[NN]) {
fprintf(stderr, "troff: too many number registers (%d).\n", NN);
done2(04);
}
return(p - r);
}
usedr(i) /* returns -1 if nr i has never been used */
register int i;
{
register j;
register int *p;
if (i == 0)
return(-1);
for (p = r; p < &r[NN]; p++) {
if (i == *p)
break;
}
if (p != &r[NN])
return(p - r);
else
return -1;
}
fnumb(i, f)
int i, (*f)();
{
register j;
j = 0;
if (i < 0) {
j = (*f)('-' | nrbits);
i = -i;
}
switch (nform) {
default:
case '1':
case 0:
return(decml(i, f) + j);
case 'i':
case 'I':
return(roman(i, f) + j);
case 'a':
case 'A':
return(abc(i, f) + j);
}
}
decml(i, f)
int i, (*f)();
{
register j, k;
k = 0;
nform--;
if ((j = i / 10) || (nform > 0))
k = decml(j, f);
return(k + (*f)((i % 10 + '0') | nrbits));
}
roman(i, f)
int i, (*f)();
{
if (!i)
return((*f)('0' | nrbits));
if (nform == 'i')
return(roman0(i, f, "ixcmz", "vldw"));
else
return(roman0(i, f, "IXCMZ", "VLDW"));
}
roman0(i, f, onesp, fivesp)
int i, (*f)();
char *onesp, *fivesp;
{
register q, rem, k;
k = 0;
if (!i)
return(0);
k = roman0(i / 10, f, onesp + 1, fivesp + 1);
q = (i = i % 10) / 5;
rem = i % 5;
if (rem == 4) {
k += (*f)(*onesp | nrbits);
if (q)
i = *(onesp + 1);
else
i = *fivesp;
return(k += (*f)(i | nrbits));
}
if (q)
k += (*f)(*fivesp | nrbits);
while (--rem >= 0)
k += (*f)(*onesp | nrbits);
return(k);
}
abc(i, f)
int i, (*f)();
{
if (!i)
return((*f)('0' | nrbits));
else
return(abc0(i - 1, f));
}
abc0(i, f)
int i, (*f)();
{
register j, k;
k = 0;
if (j = i / 26)
k = abc0(j - 1, f);
return(k + (*f)((i % 26 + nform) | nrbits));
}
wrc(i)
tchar i;
{
if (cp >= &cbuf[NC])
return(0);
*cp++ = i;
return(1);
}
long atoi0()
{
register c, k, cnt;
tchar ii;
long i, acc;
extern long ckph();
i = 0;
acc = 0;
nonumb = 0;
cnt = -1;
a0:
cnt++;
ii = getch();
c = cbits(ii);
switch (c) {
default:
ch = ii;
if (cnt)
break;
case '+':
i = ckph();
if (nonumb)
break;
acc += i;
goto a0;
case '-':
i = ckph();
if (nonumb)
break;
acc -= i;
goto a0;
case '*':
i = ckph();
if (nonumb)
break;
acc *= i;
goto a0;
case '/':
i = ckph();
if (nonumb)
break;
if (i == 0) {
flusho();
fprintf(stderr, "troff: divide by zero.\n");
acc = 0;
} else
acc /= i;
goto a0;
case '%':
i = ckph();
if (nonumb)
break;
acc %= i;
goto a0;
case '&': /*and*/
i = ckph();
if (nonumb)
break;
if ((acc > 0) && (i > 0))
acc = 1;
else
acc = 0;
goto a0;
case ':': /*or*/
i = ckph();
if (nonumb)
break;
if ((acc > 0) || (i > 0))
acc = 1;
else
acc = 0;
goto a0;
case '=':
if (cbits(ii = getch()) != '=')
ch = ii;
i = ckph();
if (nonumb) {
acc = 0;
break;
}
if (i == acc)
acc = 1;
else
acc = 0;
goto a0;
case '>':
k = 0;
if (cbits(ii = getch()) == '=')
k++;
else
ch = ii;
i = ckph();
if (nonumb) {
acc = 0;
break;
}
if (acc > (i - k))
acc = 1;
else
acc = 0;
goto a0;
case '<':
k = 0;
if (cbits(ii = getch()) == '=')
k++;
else
ch = ii;
i = ckph();
if (nonumb) {
acc = 0;
break;
}
if (acc < (i + k))
acc = 1;
else
acc = 0;
goto a0;
case ')':
break;
case '(':
acc = atoi0();
goto a0;
}
return(acc);
}
long ckph()
{
tchar i;
long j;
extern long atoi0();
extern long atoi1();
if (cbits(i = getch()) == '(')
j = atoi0();
else {
ch = i;
j = atoi1();
}
return(j);
}
long atoi1()
{
register i, j, digits;
tchar ii;
long acc;
int neg, abs, field;
neg = abs = field = digits = 0;
acc = 0;
a0:
ii = getch();
i = cbits(ii);
switch (i) {
default:
ch = ii;
break;
case '+':
goto a0;
case '-':
neg = 1;
goto a0;
case '|':
abs = 1 + neg;
neg = 0;
goto a0;
}
a1:
while (((j = (cbits(ii = getch())) - '0') >= 0) && (j <= 9)) {
field++;
digits++;
acc = 10 * acc + j;
}
if (cbits(ii) == '.') {
field++;
digits = 0;
goto a1;
}
ch = ii;
if (!field)
goto a2;
ii = getch();
switch (i = cbits(ii)) {
case 'u':
i = j = 1; /* should this be related to HOR?? */
break;
case 'v': /*VSs - vert spacing*/
j = lss;
i = 1;
break;
case 'm': /*Ems*/
j = EM;
i = 1;
break;
case 'n': /*Ens*/
j = EM;
#ifndef NROFF
i = 2;
#endif
#ifdef NROFF
i = 1; /*Same as Ems in NROFF*/
#endif
break;
case 'p': /*Points*/
j = INCH;
i = 72;
break;
case 'i': /*Inches*/
j = INCH;
i = 1;
break;
case 'c': /*Centimeters*/
/* if INCH is too big, this will overflow */
j = INCH * 50;
i = 127;
break;
case 'P': /*Picas*/
j = INCH;
i = 6;
break;
default:
j = dfact;
ch = ii;
i = dfactd;
}
if (neg)
acc = -acc;
if (!noscale) {
acc = (acc * j) / i;
}
if ((field != digits) && (digits > 0))
while (digits--)
acc /= 10;
if (abs) {
if (dip != d)
j = dip->dnl;
else
j = v.nl;
if (!vflag) {
j = v.hp = sumhp(); /* XXX */
}
if (abs == 2)
j = -j;
acc -= j;
}
a2:
nonumb = !field;
return(acc);
}
caserr()
{
register i, j;
lgf++;
while (!skip() && (i = getrq()) ) {
for (j = NNAMES; j < NN; j++) { /*NNAMES predefined names*/
if (i == r[j])
break;
}
if (j != NN) {
r[j] = vlist[j] = inc[j] = fmt[j] = 0;
regcnt--;
}
}
}
casenr()
{
register i, j;
lgf++;
skip();
if ((i = findr(getrq())) == -1)
goto rtn;
skip();
j = inumb(&vlist[i]);
if (nonumb)
goto rtn;
vlist[i] = j;
skip();
j = atoi();
if (nonumb)
goto rtn;
inc[i] = j;
rtn:
return;
}
caseaf()
{
register i, k;
tchar j;
lgf++;
if (skip() || !(i = getrq()) || skip())
return;
k = 0;
j = getch();
if (!isalpha(cbits(j))) {
ch = j;
while ((j = cbits(getch())) >= '0' && j <= '9')
k++;
}
if (!k)
k = j;
fmt[findr(i)] = k & BMASK;
}
setaf() /* return format of number register */
{
register int i, j;
i = usedr(getsn());
if (i == -1)
return;
cp = cbuf;
if (fmt[i] > 20) /* it was probably a, A, i or I */
*cp++ = fmt[i];
else
for (j = (fmt[i] ? fmt[i] : 1); j; j--)
*cp++ = '0';
*cp = 0;
cp = cbuf;
}
vnumb(i)
int *i;
{
vflag++;
dfact = lss;
res = VERT;
return(inumb(i));
}
hnumb(i)
int *i;
{
dfact = EM;
res = HOR;
return(inumb(i));
}
inumb(n)
int *n;
{
register i, j, f;
tchar ii;
f = 0;
if (n) {
if ((j = cbits(ii = getch())) == '+')
f = 1;
else if (j == '-')
f = -1;
else
ch = ii;
}
i = atoi();
if (n && f)
i = *n + f * i;
i = quant(i, res);
vflag = 0;
res = dfactd = dfact = 1;
if (nonumb)
i = 0;
return(i);
}
quant(n, m)
int n, m;
{
register i, neg;
neg = 0;
if (n < 0) {
neg++;
n = -n;
}
/* better as i = ((n + (m/2))/m)*m */
i = n / m;
if ((n - m * i) > (m / 2))
i += 1;
i *= m;
if (neg)
i = -i;
return(i);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.