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)
119 void Nreq(unsigned char *line
, int brk
) {
120 unsigned char c
[3]; /* command buffer */
121 int cmp
, hi
, low
, mid
; /* binary search indixes */
123 c
[0] = c
[1] = c
[2] = '\0';
124 if ((c
[0] = line
[1]) != '\0')
128 hi
= sizeof(NrReqt
) / sizeof(struct nr_req
);
130 mid
= (low
+ hi
) / 2;
131 if ((cmp
= strcmp((char *)c
, NrReqt
[mid
].nm
)) < 0)
136 (void) (*NrReqt
[mid
].fun
)(line
, brk
);
141 * Unknown request starting with a '.' or '\''..
143 Error(WARN
, LINE
, " unknown request", NULL
);
151 static void nr_ad(unsigned char *line
, int brk
) {
152 Pass3(NOBREAK
, (unsigned char *)"both", NULL
, 0);
157 * Begin new page - "^[.']bp"
160 static void nr_bp(unsigned char *line
, int brk
) {
161 Pass3(brk
, (unsigned char *)"need", NULL
, 999);
169 static void nr_br(unsigned char *line
, int brk
) {
170 Pass3(brk
, (unsigned char *)"flush", NULL
, 0);
178 static void nr_ce(unsigned char *line
, int brk
) {
179 unsigned char *s
; /* string poiner */
181 if ((s
= Field(2, line
, 0)) != NULL
)
182 Centering
= atoi((char *)s
);
189 * Diversion on and off - "^[.']di"
192 static void nr_di(unsigned char *line
, int brk
) {
193 Pass3(DOBREAK
, (unsigned char *)"flush", NULL
, 0);
199 * Define string - "^[.']ds"
202 static void nr_ds(unsigned char *line
, int brk
) {
203 unsigned char buf
[MAXLINE
]; /* temporary buffer */
204 unsigned char nm
[4], nm1
[4]; /* name buffers */
205 unsigned char *s1
, *s2
, *s3
, /* temporary string pointers */
208 if (Asmname(&line
[3], nm
) == 0) {
209 Error(WARN
, LINE
, " no name", NULL
);
212 s1
= Field(3, line
, 0);
213 s2
= Findstr(nm
, s1
, 1);
214 while (*s2
== '\\' && *(s2
+ 1) == '*') {
216 s3
= Asmcode(&s2
, nm1
);
217 s2
= Findstr(nm1
, NULL
, 0);
222 * Look for names LH, LF, CH, CF, RH, RF.
224 if ((nm
[0]=='L' || nm
[0]=='C' || nm
[0]=='R')
225 && (nm
[1]=='F' || nm
[1]=='H')) {
226 (void) sprintf((char *)buf
, "%s", (char *)nm
);
227 Pass3(NOBREAK
, buf
, s2
, 0);
238 static void nr_fi(unsigned char *line
, int brk
) {
240 Pass3(brk
, (unsigned char *)"flush", NULL
, 0);
248 static void nr_fl(unsigned char *line
, int brk
) {
249 Pass3(brk
, (unsigned char *)"flush", NULL
, 0);
254 * Font - "^[.']ft <font_name>"
257 static void nr_ft(unsigned char *line
, int brk
) {
258 int i
; /* temporary index */
260 if (line
[3] == '\0' || line
[4] == '\0')
262 if (line
[4] == 'P') {
266 for (i
= 0; Fcode
[i
].nm
; i
++) {
267 if (Fcode
[i
].nm
== line
[4])
270 if (Fcode
[i
].status
== '\0') {
271 Error(WARN
, LINE
, " bad font code", NULL
);
280 * Input trap - "^[.']it [1 <request>]"
283 static void nr_it(unsigned char *line
, int brk
) {
284 unsigned char buf
[MAXLINE
]; /* temporary buffer */
285 int i
; /* temporary index */
286 unsigned char *s1
, *s2
; /* temporary string pointers */
288 if ((s1
= Field(2, line
, 0)) == NULL
) {
292 if ((i
= atoi((char *)s1
)) != 1) {
293 Error(WARN
, LINE
, " first .it arg must be 1", NULL
);
296 if ((s2
= Field(3, line
, 0)) == NULL
)
299 (void) sprintf((char *)buf
, "%s,%s",
300 (Aftnxt
== NULL
) ? "" : (char *)Aftnxt
,
303 Aftnxt
= Newstr(buf
);
309 * Comment - "^[.']\\" - do nothing
311 * Debug - "^[.']\^d" - do nothing
313 * Finalization - "[.']\^e" - do nothing
315 * Error file - "^[.']\^x <name>" - do nothing
317 * "^[.']i0", "^[.']lg" and "^[.']li" - do nothing
319 * Point size - "^[.']ps" - do nothing
321 * Vertical spacing - "^[.']vs" - do nothing
325 static void nr_nil(unsigned char *line
, int brk
) {
330 * No adjust "^[.']na"
333 static void nr_na(unsigned char *line
, int brk
) {
334 Pass3(NOBREAK
, (unsigned char *)"left", NULL
, 0);
339 * No fill - "^[.']nf"
342 static void nr_nf(unsigned char *line
, int brk
) {
344 Pass3(brk
, (unsigned char *)"flush", NULL
, 0);
349 * No space - "^[.']ns"
352 static void nr_ns(unsigned char *line
, int brk
) {
353 Pass3(NOBREAK
, (unsigned char *)"nospace", NULL
, 0);
358 * Remove macro or string - "^[.']rm"
361 static void nr_rm(unsigned char *line
, int brk
) {
362 int i
; /* temporary index */
363 unsigned char nm
[4]; /* name buffer */
365 if (Asmname(&line
[3], nm
) == 0) {
366 Error(WARN
, LINE
, " no name", NULL
);
369 if ((i
= Findmacro(nm
, 0)) >= 0) {
373 (void) Findstr(nm
, NULL
, 0);
378 Error(WARN
, LINE
, " no macro/string", NULL
);
383 * Rename macro or string - "^[.']rn"
386 static void nr_rn(unsigned char *line
, int brk
) {
387 int i
, j
; /* temporary indexes */
388 unsigned char nm
[4], nm1
[4]; /* name buffers */
389 unsigned char *s1
; /* temporary string pointer */
391 if ((s1
= Field(2, line
, 0)) == NULL
|| Asmname(s1
, nm
) == 0) {
392 Error(WARN
, LINE
, " no name", NULL
);
395 if ((s1
= Field(3, line
, 0)) == NULL
|| Asmname(s1
, nm1
) == 0) {
396 Error(WARN
, LINE
, " no new name", NULL
);
399 if ((i
= Findmacro(nm
, 0)) >= 0) {
400 if ((j
= Findmacro(nm1
, 0)) >= 0)
402 j
= Findmacro(nm1
, 1);
403 Macrotab
[j
].bx
= Macrotab
[i
].bx
;
405 Macrotab
[j
].ct
= Macrotab
[i
].ct
;
410 (void) Findstr(nm
, NULL
, 0);
412 (void) Findstr(nm1
, Str
[i
].str
, 1);
416 if (Findmacro(nm1
, 0) < 0)
417 (void) Findmacro(nm1
, 1);
422 * Remove register - "^[.']rr"
425 static void nr_rr(unsigned char *line
, int brk
) {
426 int i
; /* temporary index */
427 unsigned char nm
[4]; /* name buffer */
429 if (Asmname(&line
[3], nm
) == 0) {
430 Error(WARN
, LINE
, " no name", NULL
);
433 if ((i
= Findnum(nm
, 0, 0)) < 0) {
434 Error(WARN
, LINE
, " no register", NULL
);
442 * Resume space - "^[.']rs"
445 static void nr_rs(unsigned char *line
, int brk
) {
446 Pass3(NOBREAK
, (unsigned char *)"yesspace", NULL
, 0);
451 * Message - "^[.']tm"
454 static void nr_tm(unsigned char *line
, int brk
) {
455 Pass3(MESSAGE
, Inname
, (line
[3] == ' ') ? &line
[4] : &line
[3], NR
);
460 * Translate - "^[.']tr abcd..."
463 static void nr_tr(unsigned char *line
, int brk
) {
464 unsigned char buf
[MAXLINE
]; /* temporary buffer */
465 int i
, j
; /* temporary indexes */
466 unsigned char nm
[4], nm1
[4]; /* name buffers */
467 unsigned char *s1
, *s2
; /* temporary string pointers */
468 int trin
, trout
; /* types: 0 = char; 1 = named char */
469 unsigned char xbuf
[MAXLINE
]; /* temporary buffer */
471 if (line
[3] != ' ') {
472 Error(WARN
, LINE
, " unknown translation", NULL
);
475 for (s1
= &line
[4]; *s1
;) {
476 nm
[1] = nm
[2] = '\0';
479 * Assemble the input value.
481 if (*s1
== '\\' && (*s2
== '*' || *s2
== '(')) {
484 * Input is named character -- "\(xx".
488 if ((nm
[0] = *s1
) != '\0') {
490 if ((nm
[1] = *s1
) != '\0')
495 * Input is interpolated string -- "\*x" or "\*(xx".
497 s1
= Asmcode(&s2
, nm
);
500 s2
= Findstr(nm
, NULL
, 0);
502 if ((strlen((char *)s2
) + strlen((char *)s1
) + 1)
504 Error(WARN
, LINE
, " string too long: ", (char *)nm
);
506 (void) sprintf((char *)buf
, "%s%s",
507 (char *)s2
, (char *)s1
);
508 (void) strcpy((char *)xbuf
, (char *)buf
);
517 * Input is a simple character.
520 if ((nm
[0] = *s1
) != '\0')
524 * Assemble the output value.
528 nm1
[1] = nm1
[2] = '\0';
532 * Supply a space if there is no output character.
538 if (*s1
== '\\' && (*s2
== '(' || *s2
== '*')) {
541 * The output is a named character -- "\(xx".
545 if ((nm1
[0] = *s1
) != '\0') {
547 if ((nm1
[1] = *s1
) != '\0')
552 * The output is an interpolated string -- * "\*x" or "\*(xx".
554 s1
= Asmcode(&s2
, nm1
);
557 s2
= Findstr(nm1
, NULL
, 0);
560 * Interpolate a string value.
562 if ((strlen((char *)s2
) + strlen((char *)s1
) + 1)
564 Error(WARN
, LINE
, " string too long: ",
567 (void) sprintf((char *)buf
, "%s%s", (char *)s2
,
569 (void) strcpy((char *)xbuf
, (char *)buf
);
573 goto assemble_output
;
577 if ((nm1
[0] = *s1
) != '0')
584 * Do the translation.
588 case 0: /* simple char */
591 case 0: /* to simple char */
592 Trtbl
[(int)nm
[0]] = nm1
[0];
594 case 1: /* to named char */
595 if ((i
= Findchar(nm1
, 0, NULL
, 0)) < 0
596 || strlen((char *)Schar
[i
].str
) != 1)
597 Error(WARN
, LINE
, " bad named character: ",
600 Trtbl
[(int)nm
[0]] = *(Schar
[i
].str
);
604 case 1: /* named char */
605 if ((i
= Findchar(nm
, 0, NULL
, 0)) < 0)
606 Error(WARN
, LINE
, " unknown named character: ", (char *)nm
);
610 case 0: /* to simple char */
612 Schar
[i
].str
= Newstr(nm1
);
615 case 1: /* to named char */
616 if ((j
= Findchar(nm1
, 0, NULL
, 0)) < 0)
617 Error(WARN
, LINE
, " unknown named character: ",
620 (void) Findchar(nm
, Schar
[j
].len
, Schar
[j
].str
, 1);
631 * Initialization - "^[.']\^b (fh|HF|NH) [01]"
633 * fh = first page header status
634 * HF = header/footer status
635 * NH = initialize number headers
638 static void nr_Ub(unsigned char *line
, int brk
) {
639 int i
; /* temporary index */
640 unsigned char *s1
, *s2
; /* temporary string pointers */
642 if ((s1
= Field(2, line
, 0)) == NULL
)
644 if ((s2
= Field(3, line
, 0)) == NULL
)
647 i
= atoi((char *)s2
);
648 if (s1
[0] == 'f' && s1
[1] == 'h')
649 Pass3(NOBREAK
, (unsigned char *)"fph", NULL
, i
);
650 else if (s1
[0] == 'H' && s1
[1] == 'F')
652 else if (s1
[0] == 'N' && s1
[1] == 'H') {
653 for (i
= 0; i
< MAXNHNR
; i
++)
656 Error(WARN
, LINE
, " unknown initialization", NULL
);
661 * Character definitions - "^[.']\^c"
664 static void nr_Uc(unsigned char *line
, int brk
) {
665 unsigned char buf
[MAXLINE
]; /* temporary buffer */
666 int i
; /* temporary index */
667 unsigned char *s1
, *s2
, *s3
, /* temporary string pointers */
670 s2
= Field(2, line
, 0);
671 i
= atoi((char *)Field(3, line
, 0));
672 s4
= Field(4, line
, 0);
673 if (i
< 0 || i
> MAXLINE
/2 || *s2
== '\0') {
674 Error(WARN
, LINE
, " bad character definition", NULL
);
678 s4
= (unsigned char *)"";
682 while ((s5
= (unsigned char *)strchr((char *)s4
, '\\')) != NULL
) {
693 while ((*s1
++ = *s4
++))
695 if (*s2
== 'h' && *(s2
+1) == 'y')
696 (void) Findhy(buf
, i
, 1);
698 (void) Findchar(s2
, i
, buf
, 1);
703 * Font is OK - "[.']\^f <font_name_character>"
706 static void nr_Uf(unsigned char *line
, int brk
) {
707 int i
; /* temporary index */
709 if (line
[3] != '\0' && line
[4] != '\0') {
710 for (i
= 0; Fcode
[i
].nm
; i
++) {
711 if (line
[4] == Fcode
[i
].nm
) {
712 Fcode
[i
].status
= '1';
717 Error(WARN
, LINE
, " unknown font", NULL
);
722 * Resolutions - "[.']\^r cpi horizontal vertical"
725 static void nr_Ur(unsigned char *line
, int brk
) {
726 unsigned char buf
[MAXLINE
]; /* temporary buffer */
727 int i
, j
; /* temporary indexes */
728 double tval
; /* temporary value */
730 if ((i
= atoi((char *)Field(3, line
, 0))) <= 0
731 || (j
= atoi((char *)Field(4, line
, 0))) <= 0) {
732 Error(WARN
, LINE
, " bad cpi resolutions", NULL
);
735 tval
= (double) (240.0 / (double) i
);
736 if (Findscale((int)'m', tval
, 1) < 0)
737 Error(FATAL
, LINE
, " missing Scal['m']", NULL
);
740 (void) sprintf((char *)buf
, " bad Scale['n'] (%f)", Scalen
);
741 Error(FATAL
, LINE
, (char *)buf
, NULL
);
743 if (Findscale((int)'n', tval
, 1) < 0)
744 Error(FATAL
, LINE
, " missing Scale['n']", NULL
);
745 Scalev
= (double) (240.0 / (double) j
);
747 (void) sprintf((char *)buf
, " bad Scale['v'] (%f)", Scalen
);
748 Error(FATAL
, LINE
, (char *)buf
, NULL
);
750 if (Findscale((int)'v', Scalev
, 1) < 0)
751 Error(FATAL
, LINE
, " missing Scale['v']", NULL
);
756 * Set line number and file name - "^[.']\^# <number> <file>"
758 * Lock line number and file name - "^[.']\^= <number> <file>"
761 static void nr_UL(unsigned char *line
, int brk
) {
762 unsigned char *s1
; /* temporary string pointer */
764 if ((s1
= Field(2, line
, 0)) != NULL
)
765 P2il
= atoi((char *)s1
) - 1;
768 Lockil
= (line
[2] == '#') ? 0 : 1;
770 if (Field(3, line
, 1) != NULL
) {