|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 9043 (0x2353)
Types: TextFile
Notes: UNIX file
Names: »getf.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/nroff/getf.c«
/*
* Nroff/Troff.
* Input handling.
*/
#include <stdio.h>
#include <ctype.h>
#include "roff.h"
#include "code.h"
#include "env.h"
#include "esc.h"
#include "div.h"
#include "reg.h"
#include "str.h"
/*
* Get a character handling escapes.
*/
getf(flags)
{
register REG *rp;
register int c, n;
char charbuf[CBFSIZE], name[2];
escflag = 0;
for (;;) {
if ((c=getl(flags&1)) == esc) {
if ((c=getl(flags&1)) == EOF)
return (c);
if (esctab[c] == 0) {
escflag = 1;
return (c);
}
c = esctab[c] & 0377;
}
switch (c) {
case EIGN:
continue;
case ECOM:
while ((c=getl(0)) != '\n')
;
return (c);
case EARG:
c = getf(0);
if (!isdigit(c)) {
printe("Bad argument reference");
break;
}
if (strp->s_argp[c-='0'])
adscore(strp->s_argp[c]);
continue;
case ESTR:
if ((c=getf(0)) != '(') {
name[0] = c;
name[1] = '\0';
} else {
name[0] = getf(0);
name[1] = getf(0);
}
if ((rp=findreg(name, RTEXT)))
adstreg(rp);
continue;
case ENUM:
n = 0;
if ((c=getf(0)) == '+') {
n = 1;
c = getf(0);
} else if (c == '-') {
n = -1;
c = getf(0);
}
if (c != '(') {
name[0] = c;
name[1] = '\0';
} else {
name[0] = getf(0);
name[1] = getf(0);
}
if ((rp=findreg(name, RNUMR)) == NULL)
spcnreg(name);
else {
rp->r_nval += n*rp->r_incr;
adsnval(rp->r_nval, rp->r_form);
}
continue;
case EWID:
if (flags&2) /* Copy mode */
return (c);
if (scandel(charbuf, CBFSIZE) == 0) {
adsnval(0, '1');
} else {
adsnval(getwidth(charbuf), '1');
}
continue;
case EEND:
if (ifeflag == 0)
continue;
return (c);
default:
return (c);
}
}
}
/*
* Get width of string by processing into temporary environment.
*/
int
getwidth(cp)
char *cp;
{
ENV savenv;
int n;
savenv = env; /* gigantic block copy */
setline();
ind = 0;
tif = 0;
fil = 0;
adscore(cp);
ccc = 0;
strp->s_eoff = 1;
process();
wordbreak(DNULL);
n = nlinsiz;
env = savenv;
return (n);
}
/*
* Given a buffer pointer, `bp', and the size of the buffer, `n',
* get an argument surrounded by delimeters and store it in the
* buffer.
*/
scandel(cp, n)
register char *cp;
{
int r;
register int c;
register int endc;
r = 1;
endc = getf(0);
while ((c=getf(0)) != endc) {
if (c == '\n') {
printe("Syntax error");
return (0);
}
if (--n == 0) {
printe("Delimeter argument too large");
r = 0;
} else if (n > 0)
*cp++ = c;
}
*cp++ = '\0';
return (r);
}
/*
* Get a character from the current input source.
*/
getl(eofflag)
{
register STR *sp;
int n;
register int c;
register char *cp;
sp = strp;
if (sp != NULL)
sp->s_clnc = sp->s_nlnc;
for (;;) {
if (sp == NULL) {
if (eofflag == 0)
panic("Unexpected end of file");
return (EOF);
}
switch (sp->s_type) {
case SSINP:
if ((c=getc(stdin)) == EOF)
break;
if (c == '\0')
break;
if (c == '\n') {
if ((c=getc(stdin)) == '\n')
c = '\0';
ungetc(c, stdin);
c = '\n';
}
goto ret;
case SFILE:
if ((c=getc(sp->s_fp)) == EOF) {
fclose(sp->s_fp);
break;
}
goto ret;
case SCORE:
if ((c=*sp->s_cp++) == '\0') {
if (sp->s_srel)
nfree(sp->s_srel);
break;
}
goto ret;
case SCTEX:
if (sp->s_disk && sp->s_sp >= sp->s_bufend) {
nread(sp->s_seek, sp->s_bufp);
sp->s_seek += DBFSIZE;
sp->s_sp = sp->s_bufp;
}
if ((c=*sp->s_sp++) == '\0') {
if (strnext())
continue;
nfree(sp->s_bufp);
break;
}
goto ret;
case SCDIV:
if (sp->s_n-- == 0) {
if (strnext())
continue;
nfree(sp->s_bufp);
break;
}
n = sizeof (CODE);
cp = (char *) &codeval;
while (n--)
*cp++ = geth();
return (ECOD);
}
if (sp->s_abuf)
nfree(sp->s_abuf);
n = sp->s_eoff;
strp = strp->s_next;
nfree(sp);
sp = strp;
if (n) {
if (eofflag == 0)
panic("Incomplete macro in trap");
return (EOF);
}
}
ret:
if ((c&=0377) == '\n')
sp->s_nlnc++;
return (c);
}
/*
* In a chained macro, set up input stack to point to next
* element in chain.
*/
strnext()
{
register STR *sp;
register MAC *mp;
sp = strp;
if ((mp=sp->s_macp) == NULL)
return (0);
sp->s_macp = mp->m_next;
switch (mp->m_type) {
case MTEXT:
sp->s_type = SCTEX;
break;
case MDIVN:
sp->s_type = SCDIV;
if ((sp->s_n=mp->m_size) == 0)
return (strnext());
break;
}
if (mp->m_core) {
sp->s_disk = 0;
sp->s_sp = mp->m_core;
} else {
sp->s_disk = 1;
sp->s_seek = mp->m_seek/DBFSIZE * DBFSIZE;
sp->s_sp = &(sp->s_bufp[mp->m_seek%DBFSIZE]);
nread(sp->s_seek, sp->s_bufp);
sp->s_seek += DBFSIZE;
}
return (1);
}
/*
* Get a single character assuming the stack has been set up
* for chained I/O.
*/
geth()
{
if (strp->s_disk && strp->s_sp >= strp->s_bufend) {
nread(strp->s_seek, strp->s_bufp);
strp->s_seek += DBFSIZE;
strp->s_sp = strp->s_bufp;
}
return (*strp->s_sp++);
}
/*
* Push down input stack and add the given file on top.
*/
adsfile(file)
char *file;
{
register STR *sp;
register FILE *fp;
if ((fp=fopen(file, "r")) == NULL) {
printe("Cannot open %s", file);
return (0);
}
sp = allstr(SFILE);
sp->s_next = strp;
strp = sp;
sp->s_fp = fp;
return (1);
}
/*
* Push down input stack and add the given unit.
*/
adsunit(u)
FILE *u;
{
register STR *sp;
sp = allstr(SFILE);
sp->s_next = strp;
strp = sp;
sp->s_fp = u;
}
/*
* Push down input stack and add the given register.
*/
adstreg(rp)
register REG *rp;
{
register STR *sp;
if (rp->r_macd.m_type == MREQS)
return;
sp = allstr(0);
sp->s_next = strp;
strp = sp;
sp->s_bufp = nalloc(DBFSIZE);
sp->s_bufend = &sp->s_bufp[DBFSIZE];
sp->s_macp = &rp->r_macd;
if (strnext() == 0) {
strp = strp->s_next;
nfree(sp->s_bufp);
nfree(sp);
return (0);
}
return (1);
}
/*
* Given the name of a special number register, expand it and
* add it onto the input stack.
*/
spcnreg(name)
char name[2];
{
register STR *sp;
register int n;
register char *cp;
n = 0;
if (name[0] == '.') {
switch (name[1]) {
case '$':
if ((n=strp->s_argc) > 0)
--n;
break;
case 'A':
n = antflag;
break;
case 'H':
n = unit(SMHRES, SDHRES);
break;
case 'T':
n = tntflag;
break;
case 'V':
n = unit(SMVRES, SDVRES);
break;
case 'a':
n = arorval;
break;
case 'c':
n = 0;
for (sp=strp; sp; sp=sp->s_next) {
if (sp->s_type == SFILE) {
n = sp->s_clnc;
break;
}
}
break;
case 'd':
n = cdivp->d_rpos;
break;
case 'f':
n = 0;
break;
case 'h':
n = cdivp->d_maxh;
break;
case 'i':
n = ind;
break;
case 'l':
n = lln;
break;
case 'n':
n = nrorval;
break;
case 'o':
n = pof;
break;
case 'p':
n = pgl;
break;
case 's':
n = unit(psz*SDPOIN, SMPOIN);
break;
case 't':
n = cdivp->d_ctpp ? cdivp->d_ctpp->t_apos : pgl;
if (n > pgl)
n = pgl;
n -= cdivp->d_rpos;
break;
case 'u':
n = fil;
break;
case 'v':
n = vls;
break;
case 'w':
n = 0;
break;
case 'x':
n = 0;
break;
case 'y':
n = 0;
break;
case 'z':
cp = nalloc(3);
cp[0] = cdivp->d_name[0];
cp[1] = cdivp->d_name[1];
cp[2] = '\0';
adscore(cp);
strp->s_srel = cp;
return;
}
}
adsnval(n, '1');
}
/*
* Given a value and a format, expand out the value to the
* particular format and add it onto the top of the stack.
*/
adsnval(val, f)
char f;
{
register ROM *op;
int w;
register int n;
char charbuf[CBFSIZE], *str, *cp2;
register char *cp1;
n = val;
if (n <= 0) {
if ((n=-n) <= 0) {
n = 0;
if (!isdigit(f))
f = '0';
}
}
cp1 = charbuf;
switch (f) {
case 'a':
case 'A':
while (n) {
n--;
*cp1++ = 'a' + n%26;
n /= 26;
}
break;
case 'i':
case 'I':
for (cp2="ivxlcdm"; *cp2!='m'; cp2+=2) {
op = &romtab[n%10];
n /= 10;
while (op != &romtab[0]) {
*cp1++ = cp2[op->o_digit];
op = &romtab[op->o_state];
}
}
if (cp1+n >= &charbuf[CBFSIZE]) {
*cp1++ = '*';
break;
}
while (n--)
*cp1++ = 'm';
break;
default:
w = f - '0';
while (n) {
--w;
*cp1++ = n%10 + '0';
n /= 10;
}
while (w-- > 0)
*cp1++ = '0';
if (val < 0)
*cp1++ = '-';
}
cp2 = str = nalloc(cp1-charbuf + 1);
if (isupper(f)) {
while (cp1 > charbuf)
*cp2++ = islower(*--cp1) ? toupper(*cp1) : *cp1;
} else {
while (cp1 > charbuf)
*cp2++ = *--cp1;
}
*cp2 = '\0';
adscore(str);
strp->s_srel = str;
}
/*
* Divert input to the given string.
*/
adscore(cp)
char *cp;
{
register STR *sp;
sp = allstr(SCORE);
sp->s_next = strp;
strp = sp;
sp->s_cp = cp;
sp->s_srel = NULL;
}
/*
* Allocate an entry to add to the input stack.
*/
char *
allstr(type)
{
register STR *sp;
register int i;
sp = (STR *) nalloc(sizeof *sp);
sp->s_type = type;
sp->s_eoff = 0;
sp->s_clnc = 1;
sp->s_nlnc = 1;
sp->s_argc = 0;
for (i=0; i<ARGSIZE; i++)
sp->s_argp[i] = null;
sp->s_abuf = NULL;
return (sp);
}