minix3/commands/cawf/nreq.c

881 lines
17 KiB
C

/*
* nreq.c - cawf(1) processing of nroff requests
*/
/*
* Copyright (c) 1991 Purdue University Research Foundation,
* West Lafayette, Indiana 47907. All rights reserved.
*
* Written by Victor A. Abell <abe@mace.cc.purdue.edu>, Purdue
* University Computing Center. Not derived from licensed software;
* derived from awf(1) by Henry Spencer of the University of Toronto.
*
* Permission is granted to anyone to use this software for any
* purpose on any computer system, and to alter it and redistribute
* it freely, subject to the following restrictions:
*
* 1. The author is not responsible for any consequences of use of
* this software, even if they arise from flaws in it.
*
* 2. The origin of this software must not be misrepresented, either
* by explicit claim or by omission. Credits must appear in the
* documentation.
*
* 3. Altered versions must be plainly marked as such, and must not
* be misrepresented as being the original software. Credits must
* appear in the documentation.
*
* 4. This notice may not be removed or altered.
*/
#include "cawf.h"
#include <ctype.h>
/*
* Prototypes for request processing functions.
*/
static void nr_UL(unsigned char *line, int brk);
static void nr_Ub(unsigned char *line, int brk);
static void nr_Uc(unsigned char *line, int brk);
static void nr_Uf(unsigned char *line, int brk);
static void nr_Ur(unsigned char *line, int brk);
static void nr_ad(unsigned char *line, int brk);
static void nr_bp(unsigned char *line, int brk);
static void nr_br(unsigned char *line, int brk);
static void nr_ce(unsigned char *line, int brk);
static void nr_di(unsigned char *line, int brk);
static void nr_ds(unsigned char *line, int brk);
static void nr_fi(unsigned char *line, int brk);
static void nr_fl(unsigned char *line, int brk);
static void nr_ft(unsigned char *line, int brk);
static void nr_it(unsigned char *line, int brk);
static void nr_na(unsigned char *line, int brk);
static void nr_nf(unsigned char *line, int brk);
static void nr_ns(unsigned char *line, int brk);
static void nr_rm(unsigned char *line, int brk);
static void nr_rn(unsigned char *line, int brk);
static void nr_rr(unsigned char *line, int brk);
static void nr_rs(unsigned char *line, int brk);
static void nr_tm(unsigned char *line, int brk);
static void nr_tr(unsigned char *line, int brk);
static void nr_nil(unsigned char *line, int brk);
/*
* NrReqt[] - nroff request processing table
*
* CAUTION: place new entries in their proper alphabetical order, since
* this table is processed with a binary search.
*/
static struct nr_req {
char *nm; /* nroff request */
void (*fun)(); /* processing function */
} NrReqt[] = {
{ "\\\"", nr_nil }, /* backslash-quote */
{ "^#", nr_UL },
{ "^=", nr_UL },
{ "^b", nr_Ub },
{ "^c", nr_Uc },
{ "^d", nr_nil },
{ "^e", nr_nil },
{ "^f", nr_Uf },
{ "^r", nr_Ur },
{ "^x", nr_nil },
{ "ad", nr_ad },
{ "bp", nr_bp },
{ "br", nr_br },
{ "ce", nr_ce },
{ "di", nr_di },
{ "ds", nr_ds },
{ "fi", nr_fi },
{ "fl", nr_fl },
{ "ft", nr_ft },
{ "hy", nr_nil },
{ "i0", nr_nil },
{ "it", nr_it },
{ "lg", nr_nil },
{ "li", nr_nil },
{ "na", nr_na },
{ "nf", nr_nf },
{ "ns", nr_ns },
{ "ps", nr_nil },
{ "rm", nr_rm },
{ "rn", nr_rn },
{ "rr", nr_rr },
{ "rs", nr_rs },
{ "tm", nr_tm },
{ "tr", nr_tr },
{ "vs", nr_nil },
};
/*
* Nreq(line, brk) - process miscellaneous nroff requests from line
* buffer with request status of (brk)
*/
void
Nreq(line, brk)
unsigned char *line;
int brk;
{
unsigned char c[3]; /* command buffer */
int cmp, hi, low, mid; /* binary search indixes */
c[0] = c[1] = c[2] = '\0';
if ((c[0] = line[1]) != '\0')
c[1] = line[2];
low = mid = 0;
hi = sizeof(NrReqt) / sizeof(struct nr_req);
while (low <= hi) {
mid = (low + hi) / 2;
if ((cmp = strcmp((char *)c, NrReqt[mid].nm)) < 0)
hi = mid - 1;
else if (cmp > 0)
low = mid + 1;
else {
(void) (*NrReqt[mid].fun)(line, brk);
return;
}
}
/*
* Unknown request starting with a '.' or '\''..
*/
Error(WARN, LINE, " unknown request", NULL);
}
/*
* Adjust - "^[.']ad"
*/
static void
nr_ad(line, brk)
unsigned char *line;
int brk;
{
Pass3(NOBREAK, (unsigned char *)"both", NULL, 0);
}
/*
* Begin new page - "^[.']bp"
*/
static void
nr_bp(line, brk)
unsigned char *line;
int brk;
{
Pass3(brk, (unsigned char *)"need", NULL, 999);
}
/*
* Break - "^[.']br"
*/
static void
nr_br(line, brk)
unsigned char *line;
int brk;
{
Pass3(brk, (unsigned char *)"flush", NULL, 0);
}
/*
* Center - "^[.']ce"
*/
static void
nr_ce(line, brk)
unsigned char *line;
int brk;
{
unsigned char *s; /* string poiner */
if ((s = Field(2, line, 0)) != NULL)
Centering = atoi((char *)s);
else
Centering = 1;
}
/*
* Diversion on and off - "^[.']di"
*/
static void
nr_di(line, brk)
unsigned char *line;
int brk;
{
Pass3(DOBREAK, (unsigned char *)"flush", NULL, 0);
Divert ^= 1;
}
/*
* Define string - "^[.']ds"
*/
static void
nr_ds(line, brk)
unsigned char *line;
int brk;
{
unsigned char buf[MAXLINE]; /* temporary buffer */
unsigned char nm[4], nm1[4]; /* name buffers */
unsigned char *s1, *s2, *s3, /* temporary string pointers */
*s4;
if (Asmname(&line[3], nm) == 0) {
Error(WARN, LINE, " no name", NULL);
return;
}
s1 = Field(3, line, 0);
s2 = Findstr(nm, s1, 1);
while (*s2 == '\\' && *(s2 + 1) == '*') {
s2++;
s3 = Asmcode(&s2, nm1);
s2 = Findstr(nm1, NULL, 0);
}
if (Hdft) {
/*
* Look for names LH, LF, CH, CF, RH, RF.
*/
if ((nm[0]=='L' || nm[0]=='C' || nm[0]=='R')
&& (nm[1]=='F' || nm[1]=='H')) {
(void) sprintf((char *)buf, "%s", (char *)nm);
Pass3(NOBREAK, buf, s2, 0);
}
}
}
/*
* Fill - "^[.']fi"
*/
static void
nr_fi(line, brk)
unsigned char *line;
int brk;
{
Fill = 1;
Pass3(brk, (unsigned char *)"flush", NULL, 0);
}
/*
* Flush - "^[.']fl"
*/
static void
nr_fl(line, brk)
unsigned char *line;
int brk;
{
Pass3(brk, (unsigned char *)"flush", NULL, 0);
}
/*
* Font - "^[.']ft <font_name>"
*/
static void
nr_ft(line, brk)
unsigned char *line;
int brk;
{
int i; /* temporary index */
if (line[3] == '\0' || line[4] == '\0')
line[4] = 'P';
if (line[4] == 'P') {
Font[0] = Prevfont;
return;
}
for (i = 0; Fcode[i].nm; i++) {
if (Fcode[i].nm == line[4])
break;
}
if (Fcode[i].status == '\0') {
Error(WARN, LINE, " bad font code", NULL);
return;
}
Prevfont = Font[0];
Font[0] = line[4];
}
/*
* Input trap - "^[.']it [1 <request>]"
*/
static void
nr_it(line, brk)
unsigned char *line;
int brk;
{
unsigned char buf[MAXLINE]; /* temporary buffer */
int i; /* temporary index */
unsigned char *s1, *s2; /* temporary string pointers */
if ((s1 = Field(2, line, 0)) == NULL) {
Free(&Aftnxt);
return;
}
if ((i = atoi((char *)s1)) != 1) {
Error(WARN, LINE, " first .it arg must be 1", NULL);
return;
}
if ((s2 = Field(3, line, 0)) == NULL)
Free(&Aftnxt);
else {
(void) sprintf((char *)buf, "%s,%s",
(Aftnxt == NULL) ? "" : (char *)Aftnxt,
(char *)s2);
Free(&Aftnxt);
Aftnxt = Newstr(buf);
}
}
/*
* Comment - "^[.']\\" - do nothing
*
* Debug - "^[.']\^d" - do nothing
*
* Finalization - "[.']\^e" - do nothing
*
* Error file - "^[.']\^x <name>" - do nothing
*
* "^[.']i0", "^[.']lg" and "^[.']li" - do nothing
*
* Point size - "^[.']ps" - do nothing
*
* Vertical spacing - "^[.']vs" - do nothing
*
*/
static void
nr_nil(line, brk)
unsigned char *line;
int brk;
{
}
/*
* No adjust "^[.']na"
*/
static void
nr_na(line, brk)
unsigned char *line;
int brk;
{
Pass3(NOBREAK, (unsigned char *)"left", NULL, 0);
}
/*
* No fill - "^[.']nf"
*/
static void
nr_nf(line, brk)
unsigned char *line;
int brk;
{
Fill = 0;
Pass3(brk, (unsigned char *)"flush", NULL, 0);
}
/*
* No space - "^[.']ns"
*/
static void
nr_ns(line, brk)
unsigned char *line;
int brk;
{
Pass3(NOBREAK, (unsigned char *)"nospace", NULL, 0);
}
/*
* Remove macro or string - "^[.']rm"
*/
static void
nr_rm(line, brk)
unsigned char *line;
int brk;
{
int i; /* temporary index */
unsigned char nm[4]; /* name buffer */
if (Asmname(&line[3], nm) == 0) {
Error(WARN, LINE, " no name", NULL);
return;
}
if ((i = Findmacro(nm, 0)) >= 0) {
Delmacro(i);
return;
}
(void) Findstr(nm, NULL, 0);
if (Sx >= 0) {
Delstr(Sx);
return;
}
Error(WARN, LINE, " no macro/string", NULL);
}
/*
* Rename macro or string - "^[.']rn"
*/
static void
nr_rn(line, brk)
unsigned char *line;
int brk;
{
int i, j; /* temporary indexes */
unsigned char nm[4], nm1[4]; /* name buffers */
unsigned char *s1; /* temporary string pointer */
if ((s1 = Field(2, line, 0)) == NULL || Asmname(s1, nm) == 0) {
Error(WARN, LINE, " no name", NULL);
return;
}
if ((s1 = Field(3, line, 0)) == NULL || Asmname(s1, nm1) == 0) {
Error(WARN, LINE, " no new name", NULL);
return;
}
if ((i = Findmacro(nm, 0)) >= 0) {
if ((j = Findmacro(nm1, 0)) >= 0)
Delmacro(j);
j = Findmacro(nm1, 1);
Macrotab[j].bx = Macrotab[i].bx;
Macrotab[i].bx = -1;
Macrotab[j].ct = Macrotab[i].ct;
Macrotab[i].ct = 0;
Delmacro(i);
return;
}
(void) Findstr(nm, NULL, 0);
if ((i = Sx) >= 0) {
(void) Findstr(nm1, Str[i].str, 1);
Delstr(i);
return;
}
if (Findmacro(nm1, 0) < 0)
(void) Findmacro(nm1, 1);
}
/*
* Remove register - "^[.']rr"
*/
static void
nr_rr(line, brk)
unsigned char *line;
int brk;
{
int i; /* temporary index */
unsigned char nm[4]; /* name buffer */
if (Asmname(&line[3], nm) == 0) {
Error(WARN, LINE, " no name", NULL);
return;
}
if ((i = Findnum(nm, 0, 0)) < 0) {
Error(WARN, LINE, " no register", NULL);
return;
}
Delnum(i);
}
/*
* Resume space - "^[.']rs"
*/
static void
nr_rs(line, brk)
unsigned char *line;
int brk;
{
Pass3(NOBREAK, (unsigned char *)"yesspace", NULL, 0);
}
/*
* Message - "^[.']tm"
*/
static void
nr_tm(line, brk)
unsigned char *line;
int brk;
{
Pass3(MESSAGE, Inname, (line[3] == ' ') ? &line[4] : &line[3], NR);
}
/*
* Translate - "^[.']tr abcd..."
*/
static void
nr_tr(line, brk)
unsigned char *line;
int brk;
{
unsigned char buf[MAXLINE]; /* temporary buffer */
int i, j; /* temporary indexes */
unsigned char nm[4], nm1[4]; /* name buffers */
unsigned char *s1, *s2; /* temporary string pointers */
int trin, trout; /* types: 0 = char; 1 = named char */
unsigned char xbuf[MAXLINE]; /* temporary buffer */
if (line[3] != ' ') {
Error(WARN, LINE, " unknown translation", NULL);
return;
}
for (s1 = &line[4]; *s1;) {
nm[1] = nm[2] = '\0';
s2 = s1 + 1;
/*
* Assemble the input value.
*/
if (*s1 == '\\' && (*s2 == '*' || *s2 == '(')) {
if (*s2 == '(') {
/*
* Input is named character -- "\(xx".
*/
trin = 1;
s1 = s2 + 1;
if ((nm[0] = *s1) != '\0') {
s1++;
if ((nm[1] = *s1) != '\0')
s1++;
}
} else {
/*
* Input is interpolated string -- "\*x" or "\*(xx".
*/
s1 = Asmcode(&s2, nm);
if (*s1)
s1++;
s2 = Findstr(nm, NULL, 0);
if (*s2 != '\0') {
if ((strlen((char *)s2) + strlen((char *)s1) + 1)
>= MAXLINE)
Error(WARN, LINE, " string too long: ", (char *)nm);
else {
(void) sprintf((char *)buf, "%s%s",
(char *)s2, (char *)s1);
(void) strcpy((char *)xbuf, (char *)buf);
s1 = xbuf;
}
}
continue;
}
} else {
/*
* Input is a simple character.
*/
trin = 0;
if ((nm[0] = *s1) != '\0')
s1++;
}
/*
* Assemble the output value.
*/
assemble_output:
nm1[1] = nm1[2] = '\0';
if (*s1 == '\0') {
/*
* Supply a space if there is no output character.
*/
trout = 0;
nm1[0] = ' ';
} else {
s2 = s1 + 1;
if (*s1 == '\\' && (*s2 == '(' || *s2 == '*')) {
if (*s2 == '(') {
/*
* The output is a named character -- "\(xx".
*/
trout = 1;
s1 = s2 + 1;
if ((nm1[0] = *s1) != '\0') {
s1++;
if ((nm1[1] = *s1) != '\0')
s1++;
}
} else {
/*
* The output is an interpolated string -- * "\*x" or "\*(xx".
*/
s1 = Asmcode(&s2, nm1);
if (*s1)
s1++;
s2 = Findstr(nm1, NULL, 0);
if (*s2 != '\0') {
/*
* Interpolate a string value.
*/
if ((strlen((char *)s2) + strlen((char *)s1) + 1)
>= MAXLINE)
Error(WARN, LINE, " string too long: ",
(char *)nm);
else {
(void) sprintf((char *)buf, "%s%s", (char *)s2,
(char *)s1);
(void) strcpy((char *)xbuf, (char *)buf);
s1 = xbuf;
}
}
goto assemble_output;
}
} else {
trout = 0;
if ((nm1[0] = *s1) != '0')
s1++;
else
nm1[0] = ' ';
}
}
/*
* Do the translation.
*/
switch (trin) {
case 0: /* simple char */
switch (trout) {
case 0: /* to simple char */
Trtbl[(int)nm[0]] = nm1[0];
break;
case 1: /* to named char */
if ((i = Findchar(nm1, 0, NULL, 0)) < 0
|| strlen((char *)Schar[i].str) != 1)
Error(WARN, LINE, " bad named character: ",
(char *)nm1);
else
Trtbl[(int)nm[0]] = *(Schar[i].str);
break;
}
break;
case 1: /* named char */
if ((i = Findchar(nm, 0, NULL, 0)) < 0)
Error(WARN, LINE, " unknown named character: ", (char *)nm);
else {
switch (trout) {
case 0: /* to simple char */
Free(&Schar[i].str);
Schar[i].str = Newstr(nm1);
Schar[i].len = 1;
break;
case 1: /* to named char */
if ((j = Findchar(nm1, 0, NULL, 0)) < 0)
Error(WARN, LINE, " unknown named character: ",
(char *)nm1);
else
(void) Findchar(nm, Schar[j].len, Schar[j].str, 1);
break;
}
}
break;
}
}
}
/*
* Initialization - "^[.']\^b (fh|HF|NH) [01]"
*
* fh = first page header status
* HF = header/footer status
* NH = initialize number headers
*/
static void
nr_Ub(line, brk)
unsigned char *line;
int brk;
{
int i; /* temporary index */
unsigned char *s1, *s2; /* temporary string pointers */
if ((s1 = Field(2, line, 0)) == NULL)
return;
if ((s2 = Field(3, line, 0)) == NULL)
i = 0;
else
i = atoi((char *)s2);
if (s1[0] == 'f' && s1[1] == 'h')
Pass3(NOBREAK, (unsigned char *)"fph", NULL, i);
else if (s1[0] == 'H' && s1[1] == 'F')
Hdft = i;
else if (s1[0] == 'N' && s1[1] == 'H') {
for (i = 0; i < MAXNHNR; i++)
Nhnr[i] = 0;
} else
Error(WARN, LINE, " unknown initialization", NULL);
}
/*
* Character definitions - "^[.']\^c"
*/
static void
nr_Uc(line, brk)
unsigned char *line;
int brk;
{
unsigned char buf[MAXLINE]; /* temporary buffer */
int i; /* temporary index */
unsigned char *s1, *s2, *s3, /* temporary string pointers */
*s4, *s5;
s2 = Field(2, line, 0);
i = atoi((char *)Field(3, line, 0));
s4 = Field(4, line, 0);
if (i < 0 || i > MAXLINE/2 || *s2 == '\0') {
Error(WARN, LINE, " bad character definition", NULL);
return;
}
if (s4 == NULL)
s4 = (unsigned char *)"";
else if (*s4 == '"')
s4++;
s1 = buf;
while ((s5 = (unsigned char *)strchr((char *)s4, '\\')) != NULL) {
while (s5 > s4)
*s1++ = *s4++;
s4 = ++s5;
if (*s5 == '\\')
*s1++ = '\\';
else if (*s5 == 'b')
*s1++ = '\b';
if (*s4)
s4++;
}
while (*s1++ = *s4++)
;
if (*s2 == 'h' && *(s2+1) == 'y')
(void) Findhy(buf, i, 1);
else
(void) Findchar(s2, i, buf, 1);
}
/*
* Font is OK - "[.']\^f <font_name_character>"
*/
static void
nr_Uf(line, brk)
unsigned char *line;
int brk;
{
int i; /* temporary index */
if (line[3] != '\0' && line[4] != '\0') {
for (i = 0; Fcode[i].nm; i++) {
if (line[4] == Fcode[i].nm) {
Fcode[i].status = '1';
return;
}
}
}
Error(WARN, LINE, " unknown font", NULL);
}
/*
* Resolutions - "[.']\^r cpi horizontal vertical"
*/
static void
nr_Ur(line, brk)
unsigned char *line;
int brk;
{
unsigned char buf[MAXLINE]; /* temporary buffer */
int i, j; /* temporary indexes */
double tval; /* temporary value */
if ((i = atoi((char *)Field(3, line, 0))) <= 0
|| (j = atoi((char *)Field(4, line, 0))) <= 0) {
Error(WARN, LINE, " bad cpi resolutions", NULL);
return;
}
tval = (double) (240.0 / (double) i);
if (Findscale((int)'m', tval, 1) < 0)
Error(FATAL, LINE, " missing Scal['m']", NULL);
Scalen = tval;
if (Scalen <= 0.0) {
(void) sprintf((char *)buf, " bad Scale['n'] (%f)", Scalen);
Error(FATAL, LINE, (char *)buf, NULL);
}
if (Findscale((int)'n', tval, 1) < 0)
Error(FATAL, LINE, " missing Scale['n']", NULL);
Scalev = (double) (240.0 / (double) j);
if (Scalev <= 0.0) {
(void) sprintf((char *)buf, " bad Scale['v'] (%f)", Scalen);
Error(FATAL, LINE, (char *)buf, NULL);
}
if (Findscale((int)'v', Scalev, 1) < 0)
Error(FATAL, LINE, " missing Scale['v']", NULL);
}
/*
* Set line number and file name - "^[.']\^# <number> <file>"
*
* Lock line number and file name - "^[.']\^= <number> <file>"
*/
static void
nr_UL(line, brk)
unsigned char *line;
int brk;
{
unsigned char *s1; /* temporary string pointer */
if ((s1 = Field(2, line, 0)) != NULL)
P2il = atoi((char *)s1) - 1;
else
P2il = 0;
Lockil = (line[2] == '#') ? 0 : 1;
Free(&P2name);
if (Field(3, line, 1) != NULL) {
P2name = F;
F = NULL;
} else
P2name = NULL;
}