2 * nreq.c - cawf(1) processing of nroff requests
6 * Copyright (c) 1991 Purdue University Research Foundation,
7 * West Lafayette, Indiana 47907. All rights reserved.
9 * Written by Victor A. Abell <abe@mace.cc.purdue.edu>, Purdue
10 * University Computing Center. Not derived from licensed software;
11 * derived from awf(1) by Henry Spencer of the University of Toronto.
13 * Permission is granted to anyone to use this software for any
14 * purpose on any computer system, and to alter it and redistribute
15 * it freely, subject to the following restrictions:
17 * 1. The author is not responsible for any consequences of use of
18 * this software, even if they arise from flaws in it.
20 * 2. The origin of this software must not be misrepresented, either
21 * by explicit claim or by omission. Credits must appear in the
24 * 3. Altered versions must be plainly marked as such, and must not
25 * be misrepresented as being the original software. Credits must
26 * appear in the documentation.
28 * 4. This notice may not be removed or altered.
36 * Prototypes for request processing functions.
39 static void nr_UL(unsigned char *line
, int brk
);
40 static void nr_Ub(unsigned char *line
, int brk
);
41 static void nr_Uc(unsigned char *line
, int brk
);
42 static void nr_Uf(unsigned char *line
, int brk
);
43 static void nr_Ur(unsigned char *line
, int brk
);
44 static void nr_ad(unsigned char *line
, int brk
);
45 static void nr_bp(unsigned char *line
, int brk
);
46 static void nr_br(unsigned char *line
, int brk
);
47 static void nr_ce(unsigned char *line
, int brk
);
48 static void nr_di(unsigned char *line
, int brk
);
49 static void nr_ds(unsigned char *line
, int brk
);
50 static void nr_fi(unsigned char *line
, int brk
);
51 static void nr_fl(unsigned char *line
, int brk
);
52 static void nr_ft(unsigned char *line
, int brk
);
53 static void nr_it(unsigned char *line
, int brk
);
54 static void nr_na(unsigned char *line
, int brk
);
55 static void nr_nf(unsigned char *line
, int brk
);
56 static void nr_ns(unsigned char *line
, int brk
);
57 static void nr_rm(unsigned char *line
, int brk
);
58 static void nr_rn(unsigned char *line
, int brk
);
59 static void nr_rr(unsigned char *line
, int brk
);
60 static void nr_rs(unsigned char *line
, int brk
);
61 static void nr_tm(unsigned char *line
, int brk
);
62 static void nr_tr(unsigned char *line
, int brk
);
64 static void nr_nil(unsigned char *line
, int brk
);
68 * NrReqt[] - nroff request processing table
70 * CAUTION: place new entries in their proper alphabetical order, since
71 * this table is processed with a binary search.
74 static struct nr_req
{
75 char *nm
; /* nroff request */
76 void (*fun
)(); /* processing function */
78 { "\\\"", nr_nil
}, /* backslash-quote */
115 * Nreq(line, brk) - process miscellaneous nroff requests from line
116 * buffer with request status of (brk)
124 unsigned char c
[3]; /* command buffer */
125 int cmp
, hi
, low
, mid
; /* binary search indixes */
127 c
[0] = c
[1] = c
[2] = '\0';
128 if ((c
[0] = line
[1]) != '\0')
132 hi
= sizeof(NrReqt
) / sizeof(struct nr_req
);
134 mid
= (low
+ hi
) / 2;
135 if ((cmp
= strcmp((char *)c
, NrReqt
[mid
].nm
)) < 0)
140 (void) (*NrReqt
[mid
].fun
)(line
, brk
);
145 * Unknown request starting with a '.' or '\''..
147 Error(WARN
, LINE
, " unknown request", NULL
);
160 Pass3(NOBREAK
, (unsigned char *)"both", NULL
, 0);
165 * Begin new page - "^[.']bp"
173 Pass3(brk
, (unsigned char *)"need", NULL
, 999);
186 Pass3(brk
, (unsigned char *)"flush", NULL
, 0);
199 unsigned char *s
; /* string poiner */
201 if ((s
= Field(2, line
, 0)) != NULL
)
202 Centering
= atoi((char *)s
);
209 * Diversion on and off - "^[.']di"
217 Pass3(DOBREAK
, (unsigned char *)"flush", NULL
, 0);
223 * Define string - "^[.']ds"
231 unsigned char buf
[MAXLINE
]; /* temporary buffer */
232 unsigned char nm
[4], nm1
[4]; /* name buffers */
233 unsigned char *s1
, *s2
, *s3
, /* temporary string pointers */
236 if (Asmname(&line
[3], nm
) == 0) {
237 Error(WARN
, LINE
, " no name", NULL
);
240 s1
= Field(3, line
, 0);
241 s2
= Findstr(nm
, s1
, 1);
242 while (*s2
== '\\' && *(s2
+ 1) == '*') {
244 s3
= Asmcode(&s2
, nm1
);
245 s2
= Findstr(nm1
, NULL
, 0);
250 * Look for names LH, LF, CH, CF, RH, RF.
252 if ((nm
[0]=='L' || nm
[0]=='C' || nm
[0]=='R')
253 && (nm
[1]=='F' || nm
[1]=='H')) {
254 (void) sprintf((char *)buf
, "%s", (char *)nm
);
255 Pass3(NOBREAK
, buf
, s2
, 0);
272 Pass3(brk
, (unsigned char *)"flush", NULL
, 0);
285 Pass3(brk
, (unsigned char *)"flush", NULL
, 0);
290 * Font - "^[.']ft <font_name>"
298 int i
; /* temporary index */
300 if (line
[3] == '\0' || line
[4] == '\0')
302 if (line
[4] == 'P') {
306 for (i
= 0; Fcode
[i
].nm
; i
++) {
307 if (Fcode
[i
].nm
== line
[4])
310 if (Fcode
[i
].status
== '\0') {
311 Error(WARN
, LINE
, " bad font code", NULL
);
320 * Input trap - "^[.']it [1 <request>]"
329 unsigned char buf
[MAXLINE
]; /* temporary buffer */
330 int i
; /* temporary index */
331 unsigned char *s1
, *s2
; /* temporary string pointers */
333 if ((s1
= Field(2, line
, 0)) == NULL
) {
337 if ((i
= atoi((char *)s1
)) != 1) {
338 Error(WARN
, LINE
, " first .it arg must be 1", NULL
);
341 if ((s2
= Field(3, line
, 0)) == NULL
)
344 (void) sprintf((char *)buf
, "%s,%s",
345 (Aftnxt
== NULL
) ? "" : (char *)Aftnxt
,
348 Aftnxt
= Newstr(buf
);
354 * Comment - "^[.']\\" - do nothing
356 * Debug - "^[.']\^d" - do nothing
358 * Finalization - "[.']\^e" - do nothing
360 * Error file - "^[.']\^x <name>" - do nothing
362 * "^[.']i0", "^[.']lg" and "^[.']li" - do nothing
364 * Point size - "^[.']ps" - do nothing
366 * Vertical spacing - "^[.']vs" - do nothing
379 * No adjust "^[.']na"
387 Pass3(NOBREAK
, (unsigned char *)"left", NULL
, 0);
392 * No fill - "^[.']nf"
401 Pass3(brk
, (unsigned char *)"flush", NULL
, 0);
406 * No space - "^[.']ns"
414 Pass3(NOBREAK
, (unsigned char *)"nospace", NULL
, 0);
419 * Remove macro or string - "^[.']rm"
427 int i
; /* temporary index */
428 unsigned char nm
[4]; /* name buffer */
430 if (Asmname(&line
[3], nm
) == 0) {
431 Error(WARN
, LINE
, " no name", NULL
);
434 if ((i
= Findmacro(nm
, 0)) >= 0) {
438 (void) Findstr(nm
, NULL
, 0);
443 Error(WARN
, LINE
, " no macro/string", NULL
);
448 * Rename macro or string - "^[.']rn"
456 int i
, j
; /* temporary indexes */
457 unsigned char nm
[4], nm1
[4]; /* name buffers */
458 unsigned char *s1
; /* temporary string pointer */
460 if ((s1
= Field(2, line
, 0)) == NULL
|| Asmname(s1
, nm
) == 0) {
461 Error(WARN
, LINE
, " no name", NULL
);
464 if ((s1
= Field(3, line
, 0)) == NULL
|| Asmname(s1
, nm1
) == 0) {
465 Error(WARN
, LINE
, " no new name", NULL
);
468 if ((i
= Findmacro(nm
, 0)) >= 0) {
469 if ((j
= Findmacro(nm1
, 0)) >= 0)
471 j
= Findmacro(nm1
, 1);
472 Macrotab
[j
].bx
= Macrotab
[i
].bx
;
474 Macrotab
[j
].ct
= Macrotab
[i
].ct
;
479 (void) Findstr(nm
, NULL
, 0);
481 (void) Findstr(nm1
, Str
[i
].str
, 1);
485 if (Findmacro(nm1
, 0) < 0)
486 (void) Findmacro(nm1
, 1);
491 * Remove register - "^[.']rr"
499 int i
; /* temporary index */
500 unsigned char nm
[4]; /* name buffer */
502 if (Asmname(&line
[3], nm
) == 0) {
503 Error(WARN
, LINE
, " no name", NULL
);
506 if ((i
= Findnum(nm
, 0, 0)) < 0) {
507 Error(WARN
, LINE
, " no register", NULL
);
515 * Resume space - "^[.']rs"
523 Pass3(NOBREAK
, (unsigned char *)"yesspace", NULL
, 0);
528 * Message - "^[.']tm"
536 Pass3(MESSAGE
, Inname
, (line
[3] == ' ') ? &line
[4] : &line
[3], NR
);
541 * Translate - "^[.']tr abcd..."
549 unsigned char buf
[MAXLINE
]; /* temporary buffer */
550 int i
, j
; /* temporary indexes */
551 unsigned char nm
[4], nm1
[4]; /* name buffers */
552 unsigned char *s1
, *s2
; /* temporary string pointers */
553 int trin
, trout
; /* types: 0 = char; 1 = named char */
554 unsigned char xbuf
[MAXLINE
]; /* temporary buffer */
556 if (line
[3] != ' ') {
557 Error(WARN
, LINE
, " unknown translation", NULL
);
560 for (s1
= &line
[4]; *s1
;) {
561 nm
[1] = nm
[2] = '\0';
564 * Assemble the input value.
566 if (*s1
== '\\' && (*s2
== '*' || *s2
== '(')) {
569 * Input is named character -- "\(xx".
573 if ((nm
[0] = *s1
) != '\0') {
575 if ((nm
[1] = *s1
) != '\0')
580 * Input is interpolated string -- "\*x" or "\*(xx".
582 s1
= Asmcode(&s2
, nm
);
585 s2
= Findstr(nm
, NULL
, 0);
587 if ((strlen((char *)s2
) + strlen((char *)s1
) + 1)
589 Error(WARN
, LINE
, " string too long: ", (char *)nm
);
591 (void) sprintf((char *)buf
, "%s%s",
592 (char *)s2
, (char *)s1
);
593 (void) strcpy((char *)xbuf
, (char *)buf
);
602 * Input is a simple character.
605 if ((nm
[0] = *s1
) != '\0')
609 * Assemble the output value.
613 nm1
[1] = nm1
[2] = '\0';
617 * Supply a space if there is no output character.
623 if (*s1
== '\\' && (*s2
== '(' || *s2
== '*')) {
626 * The output is a named character -- "\(xx".
630 if ((nm1
[0] = *s1
) != '\0') {
632 if ((nm1
[1] = *s1
) != '\0')
637 * The output is an interpolated string -- * "\*x" or "\*(xx".
639 s1
= Asmcode(&s2
, nm1
);
642 s2
= Findstr(nm1
, NULL
, 0);
645 * Interpolate a string value.
647 if ((strlen((char *)s2
) + strlen((char *)s1
) + 1)
649 Error(WARN
, LINE
, " string too long: ",
652 (void) sprintf((char *)buf
, "%s%s", (char *)s2
,
654 (void) strcpy((char *)xbuf
, (char *)buf
);
658 goto assemble_output
;
662 if ((nm1
[0] = *s1
) != '0')
669 * Do the translation.
673 case 0: /* simple char */
676 case 0: /* to simple char */
677 Trtbl
[(int)nm
[0]] = nm1
[0];
679 case 1: /* to named char */
680 if ((i
= Findchar(nm1
, 0, NULL
, 0)) < 0
681 || strlen((char *)Schar
[i
].str
) != 1)
682 Error(WARN
, LINE
, " bad named character: ",
685 Trtbl
[(int)nm
[0]] = *(Schar
[i
].str
);
689 case 1: /* named char */
690 if ((i
= Findchar(nm
, 0, NULL
, 0)) < 0)
691 Error(WARN
, LINE
, " unknown named character: ", (char *)nm
);
695 case 0: /* to simple char */
697 Schar
[i
].str
= Newstr(nm1
);
700 case 1: /* to named char */
701 if ((j
= Findchar(nm1
, 0, NULL
, 0)) < 0)
702 Error(WARN
, LINE
, " unknown named character: ",
705 (void) Findchar(nm
, Schar
[j
].len
, Schar
[j
].str
, 1);
716 * Initialization - "^[.']\^b (fh|HF|NH) [01]"
718 * fh = first page header status
719 * HF = header/footer status
720 * NH = initialize number headers
728 int i
; /* temporary index */
729 unsigned char *s1
, *s2
; /* temporary string pointers */
731 if ((s1
= Field(2, line
, 0)) == NULL
)
733 if ((s2
= Field(3, line
, 0)) == NULL
)
736 i
= atoi((char *)s2
);
737 if (s1
[0] == 'f' && s1
[1] == 'h')
738 Pass3(NOBREAK
, (unsigned char *)"fph", NULL
, i
);
739 else if (s1
[0] == 'H' && s1
[1] == 'F')
741 else if (s1
[0] == 'N' && s1
[1] == 'H') {
742 for (i
= 0; i
< MAXNHNR
; i
++)
745 Error(WARN
, LINE
, " unknown initialization", NULL
);
750 * Character definitions - "^[.']\^c"
758 unsigned char buf
[MAXLINE
]; /* temporary buffer */
759 int i
; /* temporary index */
760 unsigned char *s1
, *s2
, *s3
, /* temporary string pointers */
763 s2
= Field(2, line
, 0);
764 i
= atoi((char *)Field(3, line
, 0));
765 s4
= Field(4, line
, 0);
766 if (i
< 0 || i
> MAXLINE
/2 || *s2
== '\0') {
767 Error(WARN
, LINE
, " bad character definition", NULL
);
771 s4
= (unsigned char *)"";
775 while ((s5
= (unsigned char *)strchr((char *)s4
, '\\')) != NULL
) {
786 while (*s1
++ = *s4
++)
788 if (*s2
== 'h' && *(s2
+1) == 'y')
789 (void) Findhy(buf
, i
, 1);
791 (void) Findchar(s2
, i
, buf
, 1);
796 * Font is OK - "[.']\^f <font_name_character>"
804 int i
; /* temporary index */
806 if (line
[3] != '\0' && line
[4] != '\0') {
807 for (i
= 0; Fcode
[i
].nm
; i
++) {
808 if (line
[4] == Fcode
[i
].nm
) {
809 Fcode
[i
].status
= '1';
814 Error(WARN
, LINE
, " unknown font", NULL
);
819 * Resolutions - "[.']\^r cpi horizontal vertical"
827 unsigned char buf
[MAXLINE
]; /* temporary buffer */
828 int i
, j
; /* temporary indexes */
829 double tval
; /* temporary value */
831 if ((i
= atoi((char *)Field(3, line
, 0))) <= 0
832 || (j
= atoi((char *)Field(4, line
, 0))) <= 0) {
833 Error(WARN
, LINE
, " bad cpi resolutions", NULL
);
836 tval
= (double) (240.0 / (double) i
);
837 if (Findscale((int)'m', tval
, 1) < 0)
838 Error(FATAL
, LINE
, " missing Scal['m']", NULL
);
841 (void) sprintf((char *)buf
, " bad Scale['n'] (%f)", Scalen
);
842 Error(FATAL
, LINE
, (char *)buf
, NULL
);
844 if (Findscale((int)'n', tval
, 1) < 0)
845 Error(FATAL
, LINE
, " missing Scale['n']", NULL
);
846 Scalev
= (double) (240.0 / (double) j
);
848 (void) sprintf((char *)buf
, " bad Scale['v'] (%f)", Scalen
);
849 Error(FATAL
, LINE
, (char *)buf
, NULL
);
851 if (Findscale((int)'v', Scalev
, 1) < 0)
852 Error(FATAL
, LINE
, " missing Scale['v']", NULL
);
857 * Set line number and file name - "^[.']\^# <number> <file>"
859 * Lock line number and file name - "^[.']\^= <number> <file>"
867 unsigned char *s1
; /* temporary string pointer */
869 if ((s1
= Field(2, line
, 0)) != NULL
)
870 P2il
= atoi((char *)s1
) - 1;
873 Lockil
= (line
[2] == '#') ? 0 : 1;
875 if (Field(3, line
, 1) != NULL
) {