2011-03-30 05:46:40 -07:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
|
|
|
#include <bio.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deroff command -- strip troff, eqn, and tbl sequences from
|
|
|
|
* a file. Has three flags argument, -w, to cause output one word per line
|
|
|
|
* rather than in the original format.
|
|
|
|
* -mm (or -ms) causes the corresponding macro's to be interpreted
|
|
|
|
* so that just sentences are output
|
|
|
|
* -ml also gets rid of lists.
|
|
|
|
* -i causes deroff to ignore .so and .nx commands.
|
|
|
|
* Deroff follows .so and .nx commands, removes contents of macro
|
|
|
|
* definitions, equations (both .EQ ... .EN and $...$),
|
|
|
|
* Tbl command sequences, and Troff backslash vconstructions.
|
|
|
|
*
|
|
|
|
* All input is through the C macro; the most recently read character is in c.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
#define C ((c = Bgetrune(infile)) < 0?\
|
|
|
|
eof():\
|
|
|
|
((c == ldelim) && (filesp == files)?\
|
|
|
|
skeqn():\
|
|
|
|
(c == '\n'?\
|
|
|
|
(linect++,c):\
|
|
|
|
c)))
|
|
|
|
|
|
|
|
#define C1 ((c = Bgetrune(infile)) == Beof?\
|
|
|
|
eof():\
|
|
|
|
(c == '\n'?\
|
|
|
|
(linect++,c):\
|
|
|
|
c))
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* lose those macros! */
|
|
|
|
#define C fC()
|
|
|
|
#define C1 fC1()
|
|
|
|
|
|
|
|
#define SKIP while(C != '\n')
|
|
|
|
#define SKIP1 while(C1 != '\n')
|
|
|
|
#define SKIP_TO_COM SKIP;\
|
|
|
|
SKIP;\
|
|
|
|
pc=c;\
|
|
|
|
while(C != '.' || pc != '\n' || C > 'Z')\
|
|
|
|
pc=c
|
|
|
|
|
|
|
|
#define YES 1
|
|
|
|
#define NO 0
|
|
|
|
#define MS 0
|
|
|
|
#define MM 1
|
|
|
|
#define ONE 1
|
|
|
|
#define TWO 2
|
|
|
|
|
|
|
|
#define NOCHAR -2
|
|
|
|
#define EXTENDED -1 /* All runes above 0x7F */
|
|
|
|
#define SPECIAL 0
|
|
|
|
#define APOS 1
|
|
|
|
#define PUNCT 2
|
|
|
|
#define DIGIT 3
|
|
|
|
#define LETTER 4
|
|
|
|
|
|
|
|
|
|
|
|
int linect = 0;
|
|
|
|
int wordflag= NO;
|
|
|
|
int underscoreflag = NO;
|
|
|
|
int msflag = NO;
|
|
|
|
int iflag = NO;
|
|
|
|
int mac = MM;
|
|
|
|
int disp = 0;
|
|
|
|
int inmacro = NO;
|
|
|
|
int intable = NO;
|
|
|
|
int eqnflag = 0;
|
|
|
|
|
|
|
|
#define MAX_ASCII 0X80
|
|
|
|
|
|
|
|
char chars[MAX_ASCII]; /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
|
|
|
|
|
|
|
|
Rune line[30000];
|
|
|
|
Rune* lp;
|
|
|
|
|
|
|
|
long c;
|
|
|
|
long pc;
|
|
|
|
int ldelim = NOCHAR;
|
|
|
|
int rdelim = NOCHAR;
|
|
|
|
|
|
|
|
|
|
|
|
char** argv;
|
|
|
|
|
|
|
|
char fname[50];
|
|
|
|
Biobuf* files[15];
|
|
|
|
Biobuf**filesp;
|
|
|
|
Biobuf* infile;
|
|
|
|
char* devnull = "/dev/null";
|
|
|
|
Biobuf *infile;
|
|
|
|
Biobuf bout;
|
|
|
|
|
|
|
|
long skeqn(void);
|
|
|
|
Biobuf* opn(char *p);
|
|
|
|
int eof(void);
|
|
|
|
int charclass(int);
|
|
|
|
void getfname(void);
|
|
|
|
void fatal(char *s, char *p);
|
|
|
|
void usage(void);
|
|
|
|
void work(void);
|
|
|
|
void putmac(Rune *rp, int vconst);
|
|
|
|
void regline(int macline, int vconst);
|
|
|
|
void putwords(void);
|
|
|
|
void comline(void);
|
|
|
|
void macro(void);
|
|
|
|
void eqn(void);
|
|
|
|
void tbl(void);
|
|
|
|
void stbl(void);
|
|
|
|
void sdis(char a1, char a2);
|
|
|
|
void sce(void);
|
|
|
|
void backsl(void);
|
|
|
|
char* copys(char *s);
|
|
|
|
void refer(int c1);
|
|
|
|
void inpic(void);
|
|
|
|
|
|
|
|
int
|
|
|
|
fC(void)
|
|
|
|
{
|
|
|
|
c = Bgetrune(infile);
|
|
|
|
if(c < 0)
|
|
|
|
return eof();
|
|
|
|
if(c == ldelim && filesp == files)
|
|
|
|
return skeqn();
|
|
|
|
if(c == '\n')
|
|
|
|
linect++;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fC1(void)
|
|
|
|
{
|
|
|
|
c = Bgetrune(infile);
|
|
|
|
if(c == Beof)
|
|
|
|
return eof();
|
|
|
|
if(c == '\n')
|
|
|
|
linect++;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
main(int argc, char *av[])
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *f;
|
|
|
|
|
|
|
|
argv = av;
|
|
|
|
Binit(&bout, 1, OWRITE);
|
|
|
|
ARGBEGIN{
|
|
|
|
case 'w':
|
|
|
|
wordflag = YES;
|
|
|
|
break;
|
|
|
|
case '_':
|
|
|
|
wordflag = YES;
|
|
|
|
underscoreflag = YES;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
msflag = YES;
|
|
|
|
if(f = ARGF())
|
|
|
|
switch(*f)
|
|
|
|
{
|
|
|
|
case 'm': mac = MM; break;
|
|
|
|
case 's': mac = MS; break;
|
|
|
|
case 'l': disp = 1; break;
|
|
|
|
default: usage();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
usage();
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
iflag = YES;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}ARGEND
|
|
|
|
if(*argv)
|
|
|
|
infile = opn(*argv++);
|
|
|
|
else{
|
|
|
|
infile = malloc(sizeof(Biobuf));
|
|
|
|
Binit(infile, 0, OREAD);
|
|
|
|
}
|
|
|
|
files[0] = infile;
|
|
|
|
filesp = &files[0];
|
|
|
|
|
|
|
|
for(i='a'; i<='z' ; ++i)
|
|
|
|
chars[i] = LETTER;
|
|
|
|
for(i='A'; i<='Z'; ++i)
|
|
|
|
chars[i] = LETTER;
|
|
|
|
for(i='0'; i<='9'; ++i)
|
|
|
|
chars[i] = DIGIT;
|
|
|
|
chars['\''] = APOS;
|
|
|
|
chars['&'] = APOS;
|
|
|
|
chars['\b'] = APOS;
|
|
|
|
chars['.'] = PUNCT;
|
|
|
|
chars[','] = PUNCT;
|
|
|
|
chars[';'] = PUNCT;
|
|
|
|
chars['?'] = PUNCT;
|
|
|
|
chars[':'] = PUNCT;
|
|
|
|
work();
|
|
|
|
}
|
|
|
|
|
|
|
|
long
|
|
|
|
skeqn(void)
|
|
|
|
{
|
|
|
|
while(C1 != rdelim)
|
|
|
|
if(c == '\\')
|
|
|
|
c = C1;
|
|
|
|
else if(c == '"')
|
|
|
|
while(C1 != '"')
|
|
|
|
if(c == '\\')
|
|
|
|
C1;
|
|
|
|
if (msflag)
|
|
|
|
eqnflag = 1;
|
|
|
|
return(c = ' ');
|
|
|
|
}
|
|
|
|
|
|
|
|
Biobuf*
|
|
|
|
opn(char *p)
|
|
|
|
{
|
|
|
|
Biobuf *fd;
|
|
|
|
|
|
|
|
while ((fd = Bopen(p, OREAD)) == 0) {
|
|
|
|
if(msflag || p == devnull)
|
|
|
|
fatal("Cannot open file %s - quitting\n", p);
|
|
|
|
else {
|
|
|
|
fprint(2, "Deroff: Cannot open file %s - continuing\n", p);
|
|
|
|
p = devnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
linect = 0;
|
|
|
|
return(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
eof(void)
|
|
|
|
{
|
|
|
|
if(Bfildes(infile) != 0)
|
|
|
|
Bterm(infile);
|
|
|
|
if(filesp > files)
|
|
|
|
infile = *--filesp;
|
|
|
|
else
|
|
|
|
if(*argv)
|
|
|
|
infile = opn(*argv++);
|
|
|
|
else
|
|
|
|
exits(0);
|
|
|
|
return(C);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
getfname(void)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
Rune r;
|
|
|
|
Dir *dir;
|
|
|
|
struct chain
|
|
|
|
{
|
|
|
|
struct chain* nextp;
|
|
|
|
char* datap;
|
|
|
|
} *q;
|
|
|
|
|
|
|
|
static struct chain *namechain= 0;
|
|
|
|
|
|
|
|
while(C == ' ')
|
|
|
|
;
|
|
|
|
for(p = fname; (r=c) != '\n' && r != ' ' && r != '\t' && r != '\\'; C)
|
|
|
|
p += runetochar(p, &r);
|
|
|
|
*p = '\0';
|
|
|
|
while(c != '\n')
|
|
|
|
C;
|
|
|
|
if(!strcmp(fname, "/sys/lib/tmac/tmac.cs")
|
|
|
|
|| !strcmp(fname, "/sys/lib/tmac/tmac.s")) {
|
|
|
|
fname[0] = '\0';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
dir = dirstat(fname);
|
|
|
|
if(dir!=nil && ((dir->mode & DMDIR) || dir->type != 'M')) {
|
|
|
|
free(dir);
|
|
|
|
fname[0] = '\0';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
free(dir);
|
|
|
|
/*
|
|
|
|
* see if this name has already been used
|
|
|
|
*/
|
|
|
|
|
|
|
|
for(q = namechain; q; q = q->nextp)
|
|
|
|
if( !strcmp(fname, q->datap)) {
|
|
|
|
fname[0] = '\0';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
q = (struct chain*)malloc(sizeof(struct chain));
|
|
|
|
q->nextp = namechain;
|
|
|
|
q->datap = copys(fname);
|
|
|
|
namechain = q;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
usage(void)
|
|
|
|
{
|
|
|
|
fprint(2,"usage: deroff [-nw_pi] [-m (m s l)] [file ...] \n");
|
|
|
|
exits("usage");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
fatal(char *s, char *p)
|
|
|
|
{
|
|
|
|
fprint(2, "deroff: ");
|
|
|
|
fprint(2, s, p);
|
|
|
|
exits(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
work(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
eqnflag = 0;
|
|
|
|
if(C == '.' || c == '\'')
|
|
|
|
comline();
|
|
|
|
else
|
|
|
|
regline(NO, TWO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
regline(int macline, int vconst)
|
|
|
|
{
|
|
|
|
line[0] = c;
|
|
|
|
lp = line;
|
|
|
|
for(;;) {
|
|
|
|
if(c == '\\') {
|
|
|
|
*lp = ' ';
|
|
|
|
backsl();
|
|
|
|
if(c == '%') /* no blank for hyphenation char */
|
|
|
|
lp--;
|
|
|
|
}
|
|
|
|
if(c == '\n')
|
|
|
|
break;
|
|
|
|
if(intable && c=='T') {
|
|
|
|
*++lp = C;
|
|
|
|
if(c=='{' || c=='}') {
|
|
|
|
lp[-1] = ' ';
|
|
|
|
*lp = C;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(msflag == 1 && eqnflag == 1) {
|
|
|
|
eqnflag = 0;
|
|
|
|
*++lp = 'x';
|
|
|
|
}
|
|
|
|
*++lp = C;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*lp = '\0';
|
|
|
|
if(lp != line) {
|
|
|
|
if(wordflag)
|
|
|
|
putwords();
|
|
|
|
else
|
|
|
|
if(macline)
|
|
|
|
putmac(line,vconst);
|
|
|
|
else
|
|
|
|
Bprint(&bout, "%S\n", line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
putmac(Rune *rp, int vconst)
|
|
|
|
{
|
|
|
|
Rune *t;
|
|
|
|
int found;
|
|
|
|
Rune last;
|
|
|
|
|
|
|
|
found = 0;
|
|
|
|
last = 0;
|
|
|
|
while(*rp) {
|
|
|
|
while(*rp == ' ' || *rp == '\t')
|
|
|
|
Bputrune(&bout, *rp++);
|
|
|
|
for(t = rp; *t != ' ' && *t != '\t' && *t != '\0'; t++)
|
|
|
|
;
|
|
|
|
if(*rp == '\"')
|
|
|
|
rp++;
|
|
|
|
if(t > rp+vconst && charclass(*rp) == LETTER
|
|
|
|
&& charclass(rp[1]) == LETTER) {
|
|
|
|
while(rp < t)
|
|
|
|
if(*rp == '\"')
|
|
|
|
rp++;
|
|
|
|
else
|
|
|
|
Bputrune(&bout, *rp++);
|
|
|
|
last = t[-1];
|
|
|
|
found++;
|
|
|
|
} else
|
|
|
|
if(found && charclass(*rp) == PUNCT && rp[1] == '\0')
|
|
|
|
Bputrune(&bout, *rp++);
|
|
|
|
else {
|
|
|
|
last = t[-1];
|
|
|
|
rp = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bputc(&bout, '\n');
|
|
|
|
if(msflag && charclass(last) == PUNCT)
|
|
|
|
Bprint(&bout, " %C\n", last);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* break into words for -w option
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
putwords(void)
|
|
|
|
{
|
|
|
|
Rune *p, *p1;
|
|
|
|
int i, nlet;
|
|
|
|
|
|
|
|
|
|
|
|
for(p1 = line;;) {
|
|
|
|
/*
|
|
|
|
* skip initial specials ampersands and apostrophes
|
|
|
|
*/
|
|
|
|
while((i = charclass(*p1)) != EXTENDED && i < DIGIT)
|
|
|
|
if(*p1++ == '\0')
|
|
|
|
return;
|
|
|
|
nlet = 0;
|
|
|
|
for(p = p1; (i = charclass(*p)) != SPECIAL || (underscoreflag && *p=='_'); p++)
|
|
|
|
if(i == LETTER || (underscoreflag && *p == '_'))
|
|
|
|
nlet++;
|
|
|
|
/*
|
|
|
|
* MDM definition of word
|
|
|
|
*/
|
|
|
|
if(nlet > 1) {
|
|
|
|
/*
|
|
|
|
* delete trailing ampersands and apostrophes
|
|
|
|
*/
|
|
|
|
while(*--p == '\'' || *p == '&'
|
|
|
|
|| charclass(*p) == PUNCT)
|
|
|
|
;
|
|
|
|
while(p1 <= p)
|
|
|
|
Bputrune(&bout, *p1++);
|
|
|
|
Bputc(&bout, '\n');
|
|
|
|
} else
|
|
|
|
p1 = p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
comline(void)
|
|
|
|
{
|
|
|
|
long c1, c2;
|
|
|
|
|
|
|
|
while(C==' ' || c=='\t')
|
|
|
|
;
|
|
|
|
comx:
|
|
|
|
if((c1=c) == '\n')
|
|
|
|
return;
|
|
|
|
c2 = C;
|
|
|
|
if(c1=='.' && c2!='.')
|
|
|
|
inmacro = NO;
|
|
|
|
if(msflag && c1 == '['){
|
|
|
|
refer(c2);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(c2 == '\n')
|
|
|
|
return;
|
|
|
|
if(c1 == '\\' && c2 == '\"')
|
|
|
|
SKIP;
|
|
|
|
else
|
|
|
|
if (filesp==files && c1=='E' && c2=='Q')
|
|
|
|
eqn();
|
|
|
|
else
|
|
|
|
if(filesp==files && c1=='T' && (c2=='S' || c2=='C' || c2=='&')) {
|
|
|
|
if(msflag)
|
|
|
|
stbl();
|
|
|
|
else
|
|
|
|
tbl();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(c1=='T' && c2=='E')
|
|
|
|
intable = NO;
|
|
|
|
else if (!inmacro &&
|
|
|
|
((c1 == 'd' && c2 == 'e') ||
|
|
|
|
(c1 == 'i' && c2 == 'g') ||
|
|
|
|
(c1 == 'a' && c2 == 'm')))
|
|
|
|
macro();
|
|
|
|
else
|
|
|
|
if(c1=='s' && c2=='o') {
|
|
|
|
if(iflag)
|
|
|
|
SKIP;
|
|
|
|
else {
|
|
|
|
getfname();
|
|
|
|
if(fname[0]) {
|
|
|
|
if(infile = opn(fname))
|
|
|
|
*++filesp = infile;
|
|
|
|
else infile = *filesp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(c1=='n' && c2=='x')
|
|
|
|
if(iflag)
|
|
|
|
SKIP;
|
|
|
|
else {
|
|
|
|
getfname();
|
|
|
|
if(fname[0] == '\0')
|
|
|
|
exits(0);
|
|
|
|
if(Bfildes(infile) != 0)
|
|
|
|
Bterm(infile);
|
|
|
|
infile = *filesp = opn(fname);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(c1 == 't' && c2 == 'm')
|
|
|
|
SKIP;
|
|
|
|
else
|
|
|
|
if(c1=='h' && c2=='w')
|
|
|
|
SKIP;
|
|
|
|
else
|
|
|
|
if(msflag && c1 == 'T' && c2 == 'L') {
|
|
|
|
SKIP_TO_COM;
|
|
|
|
goto comx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(msflag && c1=='N' && c2 == 'R')
|
|
|
|
SKIP;
|
|
|
|
else
|
|
|
|
if(msflag && c1 == 'A' && (c2 == 'U' || c2 == 'I')){
|
|
|
|
if(mac==MM)SKIP;
|
|
|
|
else {
|
|
|
|
SKIP_TO_COM;
|
|
|
|
goto comx;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if(msflag && c1=='F' && c2=='S') {
|
|
|
|
SKIP_TO_COM;
|
|
|
|
goto comx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(msflag && (c1=='S' || c1=='N') && c2=='H') {
|
|
|
|
SKIP_TO_COM;
|
|
|
|
goto comx;
|
|
|
|
} else
|
|
|
|
if(c1 == 'U' && c2 == 'X') {
|
|
|
|
if(wordflag)
|
|
|
|
Bprint(&bout, "UNIX\n");
|
|
|
|
else
|
|
|
|
Bprint(&bout, "UNIX ");
|
|
|
|
} else
|
|
|
|
if(msflag && c1=='O' && c2=='K') {
|
|
|
|
SKIP_TO_COM;
|
|
|
|
goto comx;
|
|
|
|
} else
|
|
|
|
if(msflag && c1=='N' && c2=='D')
|
|
|
|
SKIP;
|
|
|
|
else
|
|
|
|
if(msflag && mac==MM && c1=='H' && (c2==' '||c2=='U'))
|
|
|
|
SKIP;
|
|
|
|
else
|
|
|
|
if(msflag && mac==MM && c2=='L') {
|
|
|
|
if(disp || c1=='R')
|
|
|
|
sdis('L', 'E');
|
|
|
|
else {
|
|
|
|
SKIP;
|
|
|
|
Bprint(&bout, " .");
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if(!msflag && c1=='P' && c2=='S') {
|
|
|
|
inpic();
|
|
|
|
} else
|
|
|
|
if(msflag && (c1=='D' || c1=='N' || c1=='K'|| c1=='P') && c2=='S') {
|
|
|
|
sdis(c1, 'E');
|
|
|
|
} else
|
|
|
|
if(msflag && (c1 == 'K' && c2 == 'F')) {
|
|
|
|
sdis(c1,'E');
|
|
|
|
} else
|
|
|
|
if(msflag && c1=='n' && c2=='f')
|
|
|
|
sdis('f','i');
|
|
|
|
else
|
|
|
|
if(msflag && c1=='c' && c2=='e')
|
|
|
|
sce();
|
|
|
|
else {
|
|
|
|
if(c1=='.' && c2=='.') {
|
|
|
|
if(msflag) {
|
|
|
|
SKIP;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
while(C == '.')
|
|
|
|
;
|
|
|
|
}
|
|
|
|
inmacro++;
|
|
|
|
if(c1 <= 'Z' && msflag)
|
|
|
|
regline(YES,ONE);
|
|
|
|
else {
|
|
|
|
if(wordflag)
|
|
|
|
C;
|
|
|
|
regline(YES,TWO);
|
|
|
|
}
|
|
|
|
inmacro--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
macro(void)
|
|
|
|
{
|
|
|
|
if(msflag) {
|
|
|
|
do {
|
|
|
|
SKIP1;
|
|
|
|
} while(C1 != '.' || C1 != '.' || C1 == '.');
|
|
|
|
if(c != '\n')
|
|
|
|
SKIP;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SKIP;
|
|
|
|
inmacro = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sdis(char a1, char a2)
|
|
|
|
{
|
|
|
|
int c1, c2;
|
|
|
|
int eqnf;
|
|
|
|
int lct;
|
|
|
|
|
|
|
|
if(a1 == 'P'){
|
|
|
|
while(C1 == ' ')
|
|
|
|
;
|
|
|
|
if(c == '<') {
|
|
|
|
SKIP1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lct = 0;
|
|
|
|
eqnf = 1;
|
|
|
|
if(c != '\n')
|
|
|
|
SKIP1;
|
|
|
|
for(;;) {
|
|
|
|
while(C1 != '.')
|
|
|
|
if(c == '\n')
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
SKIP1;
|
|
|
|
if((c1=C1) == '\n')
|
|
|
|
continue;
|
|
|
|
if((c2=C1) == '\n') {
|
|
|
|
if(a1 == 'f' && (c1 == 'P' || c1 == 'H'))
|
|
|
|
return;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(c1==a1 && c2 == a2) {
|
|
|
|
SKIP1;
|
|
|
|
if(lct != 0){
|
|
|
|
lct--;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(eqnf)
|
|
|
|
Bprint(&bout, " .");
|
|
|
|
Bputc(&bout, '\n');
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
if(a1 == 'L' && c2 == 'L') {
|
|
|
|
lct++;
|
|
|
|
SKIP1;
|
|
|
|
} else
|
|
|
|
if(a1 == 'D' && c1 == 'E' && c2 == 'Q') {
|
|
|
|
eqn();
|
|
|
|
eqnf = 0;
|
|
|
|
} else
|
|
|
|
if(a1 == 'f') {
|
|
|
|
if((mac == MS && c2 == 'P') ||
|
|
|
|
(mac == MM && c1 == 'H' && c2 == 'U')){
|
|
|
|
SKIP1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SKIP1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
SKIP1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tbl(void)
|
|
|
|
{
|
|
|
|
while(C != '.')
|
|
|
|
;
|
|
|
|
SKIP;
|
|
|
|
intable = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
stbl(void)
|
|
|
|
{
|
|
|
|
while(C != '.')
|
|
|
|
;
|
|
|
|
SKIP_TO_COM;
|
|
|
|
if(c != 'T' || C != 'E') {
|
|
|
|
SKIP;
|
|
|
|
pc = c;
|
|
|
|
while(C != '.' || pc != '\n' || C != 'T' || C != 'E')
|
|
|
|
pc = c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
eqn(void)
|
|
|
|
{
|
|
|
|
long c1, c2;
|
|
|
|
int dflg;
|
|
|
|
char last;
|
|
|
|
|
|
|
|
last = 0;
|
|
|
|
dflg = 1;
|
|
|
|
SKIP;
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
if(C1 == '.' || c == '\'') {
|
|
|
|
while(C1==' ' || c=='\t')
|
|
|
|
;
|
|
|
|
if(c=='E' && C1=='N') {
|
|
|
|
SKIP;
|
|
|
|
if(msflag && dflg) {
|
|
|
|
Bputc(&bout, 'x');
|
|
|
|
Bputc(&bout, ' ');
|
|
|
|
if(last) {
|
|
|
|
Bputc(&bout, last);
|
|
|
|
Bputc(&bout, '\n');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if(c == 'd') {
|
|
|
|
if(C1=='e' && C1=='l')
|
|
|
|
if(C1=='i' && C1=='m') {
|
|
|
|
while(C1 == ' ')
|
|
|
|
;
|
|
|
|
if((c1=c)=='\n' || (c2=C1)=='\n' ||
|
|
|
|
(c1=='o' && c2=='f' && C1=='f')) {
|
|
|
|
ldelim = NOCHAR;
|
|
|
|
rdelim = NOCHAR;
|
|
|
|
} else {
|
|
|
|
ldelim = c1;
|
|
|
|
rdelim = c2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dflg = 0;
|
|
|
|
}
|
|
|
|
if(c != '\n')
|
|
|
|
while(C1 != '\n') {
|
2020-08-01 10:54:03 -07:00
|
|
|
if(charclass(c) == PUNCT)
|
2011-03-30 05:46:40 -07:00
|
|
|
last = c;
|
|
|
|
else
|
|
|
|
if(c != ' ')
|
|
|
|
last = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* skip over a complete backslash vconstruction
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
backsl(void)
|
|
|
|
{
|
|
|
|
int bdelim;
|
|
|
|
|
|
|
|
sw:
|
|
|
|
switch(C1)
|
|
|
|
{
|
|
|
|
case '"':
|
|
|
|
SKIP1;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
if(C1 == '\\')
|
|
|
|
backsl();
|
|
|
|
else {
|
|
|
|
while(C1>='0' && c<='9')
|
|
|
|
;
|
|
|
|
Bungetrune(infile);
|
|
|
|
c = '0';
|
|
|
|
}
|
|
|
|
lp--;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 'f':
|
|
|
|
case 'n':
|
|
|
|
case '*':
|
|
|
|
if(C1 != '(')
|
|
|
|
return;
|
|
|
|
|
|
|
|
case '(':
|
|
|
|
if(msflag) {
|
|
|
|
if(C == 'e') {
|
|
|
|
if(C1 == 'm') {
|
|
|
|
*lp = '-';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if(c != '\n')
|
|
|
|
C1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(C1 != '\n')
|
|
|
|
C1;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case '$':
|
|
|
|
C1; /* discard argument number */
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 'b':
|
|
|
|
case 'x':
|
|
|
|
case 'v':
|
|
|
|
case 'h':
|
|
|
|
case 'w':
|
|
|
|
case 'o':
|
|
|
|
case 'l':
|
|
|
|
case 'L':
|
|
|
|
if((bdelim=C1) == '\n')
|
|
|
|
return;
|
|
|
|
while(C1!='\n' && c!=bdelim)
|
|
|
|
if(c == '\\')
|
|
|
|
backsl();
|
|
|
|
return;
|
|
|
|
|
|
|
|
case '\\':
|
|
|
|
if(inmacro)
|
|
|
|
goto sw;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char*
|
|
|
|
copys(char *s)
|
|
|
|
{
|
|
|
|
char *t, *t0;
|
|
|
|
|
|
|
|
if((t0 = t = malloc((strlen(s)+1))) == 0)
|
|
|
|
fatal("Cannot allocate memory", (char*)0);
|
|
|
|
while(*t++ = *s++)
|
|
|
|
;
|
|
|
|
return(t0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sce(void)
|
|
|
|
{
|
|
|
|
int n = 1;
|
|
|
|
|
|
|
|
while (C != L'\n' && !(L'0' <= c && c <= L'9'))
|
|
|
|
;
|
|
|
|
if (c != L'\n') {
|
|
|
|
for (n = c-L'0';'0' <= C && c <= L'9';)
|
|
|
|
n = n*10 + c-L'0';
|
|
|
|
}
|
|
|
|
while(n) {
|
|
|
|
if(C == '.') {
|
|
|
|
if(C == 'c') {
|
|
|
|
if(C == 'e') {
|
|
|
|
while(C == ' ')
|
|
|
|
;
|
|
|
|
if(c == '0') {
|
|
|
|
SKIP;
|
|
|
|
break;
|
|
|
|
} else
|
|
|
|
SKIP;
|
|
|
|
} else
|
|
|
|
SKIP;
|
|
|
|
} else
|
|
|
|
if(c == 'P' || C == 'P') {
|
|
|
|
if(c != '\n')
|
|
|
|
SKIP;
|
|
|
|
break;
|
|
|
|
} else
|
|
|
|
if(c != '\n')
|
|
|
|
SKIP;
|
|
|
|
} else {
|
|
|
|
SKIP;
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
refer(int c1)
|
|
|
|
{
|
|
|
|
int c2;
|
|
|
|
|
|
|
|
if(c1 != '\n')
|
|
|
|
SKIP;
|
|
|
|
c2 = 0;
|
|
|
|
for(;;) {
|
|
|
|
if(C != '.')
|
|
|
|
SKIP;
|
|
|
|
else {
|
|
|
|
if(C != ']')
|
|
|
|
SKIP;
|
|
|
|
else {
|
|
|
|
while(C != '\n')
|
|
|
|
c2 = c;
|
|
|
|
if(charclass(c2) == PUNCT)
|
|
|
|
Bprint(&bout, " %C",c2);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
inpic(void)
|
|
|
|
{
|
|
|
|
int c1;
|
|
|
|
Rune *p1;
|
|
|
|
|
|
|
|
/* SKIP1;*/
|
|
|
|
while(C1 != '\n')
|
|
|
|
if(c == '<'){
|
|
|
|
SKIP1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p1 = line;
|
|
|
|
c = '\n';
|
|
|
|
for(;;) {
|
|
|
|
c1 = c;
|
|
|
|
if(C1 == '.' && c1 == '\n') {
|
|
|
|
if(C1 != 'P' || C1 != 'E') {
|
|
|
|
if(c != '\n'){
|
|
|
|
SKIP1;
|
|
|
|
c = '\n';
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
SKIP1;
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
if(c == '\"') {
|
|
|
|
while(C1 != '\"') {
|
|
|
|
if(c == '\\') {
|
|
|
|
if(C1 == '\"')
|
|
|
|
continue;
|
|
|
|
Bungetrune(infile);
|
|
|
|
backsl();
|
|
|
|
} else
|
|
|
|
*p1++ = c;
|
|
|
|
}
|
|
|
|
*p1++ = ' ';
|
|
|
|
} else
|
|
|
|
if(c == '\n' && p1 != line) {
|
|
|
|
*p1 = '\0';
|
|
|
|
if(wordflag)
|
|
|
|
putwords();
|
|
|
|
else
|
|
|
|
Bprint(&bout, "%S\n\n", line);
|
|
|
|
p1 = line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
charclass(int c)
|
|
|
|
{
|
|
|
|
if(c < MAX_ASCII)
|
|
|
|
return chars[c];
|
|
|
|
switch(c){
|
|
|
|
case 0x2013: case 0x2014: /* en dash, em dash */
|
|
|
|
return SPECIAL;
|
|
|
|
}
|
|
|
|
return EXTENDED;
|
|
|
|
}
|