xref: /minix/minix/commands/cawf/nreq.c (revision 9f988b79)
1 /*
2  *	nreq.c - cawf(1) processing of nroff requests
3  */
4 
5 /*
6  *	Copyright (c) 1991 Purdue University Research Foundation,
7  *	West Lafayette, Indiana 47907.  All rights reserved.
8  *
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.
12  *
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:
16  *
17  *	1. The author is not responsible for any consequences of use of
18  *	   this software, even if they arise from flaws in it.
19  *
20  *	2. The origin of this software must not be misrepresented, either
21  *	   by explicit claim or by omission.  Credits must appear in the
22  *	   documentation.
23  *
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.
27  *
28  *	4. This notice may not be removed or altered.
29  */
30 
31 #include "cawf.h"
32 #include <ctype.h>
33 
34 
35 /*
36  * Prototypes for request processing functions.
37  */
38 
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);
63 
64 static void nr_nil(unsigned char *line, int brk);
65 
66 
67 /*
68  * NrReqt[] - nroff request processing table
69  *
70  * CAUTION: place new entries in their proper alphabetical order, since
71  *	    this table is processed with a binary search.
72  */
73 
74 static struct nr_req {
75 	char *nm;			/* nroff request */
76 	void (*fun)();			/* processing function */
77 } NrReqt[] = {
78 	{ "\\\"",	nr_nil },	/* backslash-quote */
79 	{ "^#",		nr_UL  },
80 	{ "^=",		nr_UL  },
81 	{ "^b",		nr_Ub  },
82 	{ "^c",		nr_Uc  },
83 	{ "^d",		nr_nil },
84 	{ "^e",		nr_nil },
85 	{ "^f",		nr_Uf  },
86 	{ "^r",		nr_Ur  },
87 	{ "^x",		nr_nil },
88 	{ "ad",		nr_ad  },
89 	{ "bp",		nr_bp  },
90 	{ "br",		nr_br  },
91 	{ "ce",		nr_ce  },
92 	{ "di",		nr_di  },
93 	{ "ds",		nr_ds  },
94 	{ "fi",		nr_fi  },
95 	{ "fl",		nr_fl  },
96 	{ "ft",		nr_ft  },
97 	{ "hy",		nr_nil },
98 	{ "i0",		nr_nil },
99 	{ "it",		nr_it  },
100 	{ "lg",		nr_nil },
101 	{ "li",		nr_nil },
102 	{ "na",		nr_na  },
103 	{ "nf",		nr_nf  },
104 	{ "ns",		nr_ns  },
105 	{ "ps",		nr_nil },
106 	{ "rm",		nr_rm  },
107 	{ "rn",		nr_rn  },
108 	{ "rr",		nr_rr  },
109 	{ "rs",		nr_rs  },
110 	{ "tm",		nr_tm  },
111 	{ "tr",		nr_tr  },
112 	{ "vs",		nr_nil },
113 };
114 /*
115  * Nreq(line, brk) - process miscellaneous nroff requests from line
116  *		     buffer with request status of (brk)
117  */
118 
119 void Nreq(unsigned char *line, int brk) {
120 	unsigned char c[3];		/* command buffer */
121 	int cmp, hi, low, mid;		/* binary search indixes */
122 
123 	c[0] = c[1] = c[2] = '\0';
124 	if ((c[0] = line[1]) != '\0')
125 		c[1] = line[2];
126 
127 	low = mid = 0;
128 	hi = sizeof(NrReqt) / sizeof(struct nr_req);
129 	while (low <= hi) {
130 		mid = (low + hi) / 2;
131 		if ((cmp = strcmp((char *)c, NrReqt[mid].nm)) < 0)
132 			hi = mid - 1;
133 		else if (cmp > 0)
134 			low = mid + 1;
135 		else {
136 			(void) (*NrReqt[mid].fun)(line, brk);
137 			return;
138 		}
139 	}
140     /*
141      * Unknown request starting with a '.' or '\''..
142      */
143 	Error(WARN, LINE, " unknown request", NULL);
144 }
145 
146 
147 /*
148  * Adjust - "^[.']ad"
149  */
150 
151 static void nr_ad(unsigned char *line, int brk) {
152 	Pass3(NOBREAK, (unsigned char *)"both", NULL, 0);
153 }
154 
155 
156 /*
157 * Begin new page - "^[.']bp"
158 */
159 
160 static void nr_bp(unsigned char *line, int brk) {
161 	Pass3(brk, (unsigned char *)"need", NULL, 999);
162 }
163 
164 
165 /*
166 * Break - "^[.']br"
167 */
168 
169 static void nr_br(unsigned char *line, int brk) {
170 	Pass3(brk, (unsigned char *)"flush", NULL, 0);
171 }
172 
173 
174 /*
175  * Center - "^[.']ce"
176  */
177 
178 static void nr_ce(unsigned char *line, int brk) {
179 	unsigned char *s;			/* string poiner */
180 
181 	if ((s = Field(2, line, 0)) != NULL)
182 		Centering = atoi((char *)s);
183 	else
184 		Centering = 1;
185 }
186 
187 
188 /*
189  * Diversion on and off - "^[.']di"
190  */
191 
192 static void nr_di(unsigned char *line, int brk) {
193 	Pass3(DOBREAK, (unsigned char *)"flush", NULL, 0);
194 	Divert ^= 1;
195 }
196 
197 
198 /*
199  * Define string - "^[.']ds"
200  */
201 
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 */
206 		       *s4;
207 
208 	if (Asmname(&line[3], nm) == 0) {
209 		Error(WARN, LINE, " no name", NULL);
210 		return;
211 	}
212 	s1 = Field(3, line, 0);
213 	s2 = Findstr(nm, s1, 1);
214 	while (*s2 == '\\' && *(s2 + 1) == '*') {
215 		s2++;
216 		s3 = Asmcode(&s2, nm1);
217 		s2 = Findstr(nm1, NULL, 0);
218 	}
219 	if (Hdft) {
220 
221 	/*
222 	 * Look for names LH, LF, CH, CF, RH, RF.
223 	 */
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);
228 		}
229 	}
230 }
231 
232 
233 
234 /*
235  * Fill - "^[.']fi"
236  */
237 
238 static void nr_fi(unsigned char *line, int brk) {
239 	Fill = 1;
240 	Pass3(brk, (unsigned char *)"flush", NULL, 0);
241 }
242 
243 
244 /*
245  * Flush - "^[.']fl"
246  */
247 
248 static void nr_fl(unsigned char *line, int brk) {
249 	Pass3(brk, (unsigned char *)"flush", NULL, 0);
250 }
251 
252 
253 /*
254  * Font - "^[.']ft <font_name>"
255  */
256 
257 static void nr_ft(unsigned char *line, int brk) {
258 	int i;				/* temporary index */
259 
260 	if (line[3] == '\0' || line[4] == '\0')
261 		line[4] = 'P';
262 	if (line[4] == 'P') {
263 		Font[0] = Prevfont;
264 		return;
265 	}
266 	for (i = 0; Fcode[i].nm; i++) {
267 		if (Fcode[i].nm == line[4])
268 		break;
269 	}
270 	if (Fcode[i].status == '\0') {
271 		Error(WARN, LINE, " bad font code", NULL);
272 		return;
273 	}
274 	Prevfont = Font[0];
275 	Font[0] = line[4];
276 }
277 
278 
279 /*
280  * Input trap - "^[.']it [1 <request>]"
281  */
282 
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 */
287 
288 	if ((s1 = Field(2, line, 0)) == NULL) {
289 		Free(&Aftnxt);
290 		return;
291 	}
292 	if ((i = atoi((char *)s1)) != 1) {
293 		Error(WARN, LINE, " first .it arg must be 1", NULL);
294 		return;
295 	}
296 	if ((s2 = Field(3, line, 0)) == NULL)
297 		Free(&Aftnxt);
298 	else {
299 		(void) sprintf((char *)buf, "%s,%s",
300 			(Aftnxt == NULL) ? "" : (char *)Aftnxt,
301 			(char *)s2);
302 		Free(&Aftnxt);
303 		Aftnxt = Newstr(buf);
304 	}
305 }
306 
307 
308 /*
309  * Comment - "^[.']\\" - do nothing
310  *
311  * Debug - "^[.']\^d" - do nothing
312  *
313  * Finalization - "[.']\^e" - do nothing
314  *
315  * Error file - "^[.']\^x <name>" - do nothing
316  *
317  * "^[.']i0", "^[.']lg" and "^[.']li" - do nothing
318  *
319  * Point size - "^[.']ps" - do nothing
320  *
321  * Vertical spacing - "^[.']vs" - do nothing
322  *
323  */
324 
325 static void nr_nil(unsigned char *line, int brk) {
326 }
327 
328 
329 /*
330  * No adjust "^[.']na"
331  */
332 
333 static void nr_na(unsigned char *line, int brk) {
334 	Pass3(NOBREAK, (unsigned char *)"left", NULL, 0);
335 }
336 
337 
338 /*
339  * No fill - "^[.']nf"
340  */
341 
342 static void nr_nf(unsigned char *line, int brk) {
343 	Fill = 0;
344 	Pass3(brk, (unsigned char *)"flush", NULL, 0);
345 }
346 
347 
348 /*
349  * No space - "^[.']ns"
350  */
351 
352 static void nr_ns(unsigned char *line, int brk) {
353 	Pass3(NOBREAK, (unsigned char *)"nospace", NULL, 0);
354 }
355 
356 
357 /*
358  * Remove macro or string - "^[.']rm"
359  */
360 
361 static void nr_rm(unsigned char *line, int brk) {
362 	int i;				/* temporary index */
363 	unsigned char nm[4];		/* name buffer */
364 
365 	if (Asmname(&line[3], nm) == 0) {
366 		Error(WARN, LINE, " no name", NULL);
367 		return;
368 	}
369 	if ((i = Findmacro(nm, 0)) >= 0) {
370 		Delmacro(i);
371 		return;
372 			}
373 	(void) Findstr(nm, NULL, 0);
374 		if (Sx >= 0) {
375 			Delstr(Sx);
376 			return;
377 	}
378 	Error(WARN, LINE, " no macro/string", NULL);
379 }
380 
381 
382 /*
383  * Rename macro or string - "^[.']rn"
384  */
385 
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 */
390 
391 	if ((s1 = Field(2, line, 0)) == NULL ||  Asmname(s1, nm) == 0) {
392 		Error(WARN, LINE, " no name", NULL);
393 		return;
394 	}
395 	if ((s1 = Field(3, line, 0)) == NULL ||  Asmname(s1, nm1) == 0) {
396 		Error(WARN, LINE, " no new name", NULL);
397 		return;
398 	}
399 	if ((i = Findmacro(nm, 0)) >= 0) {
400 		if ((j = Findmacro(nm1, 0)) >= 0)
401 			Delmacro(j);
402 		j = Findmacro(nm1, 1);
403 		Macrotab[j].bx = Macrotab[i].bx;
404 		Macrotab[i].bx = -1;
405 		Macrotab[j].ct = Macrotab[i].ct;
406 		Macrotab[i].ct = 0;
407 		Delmacro(i);
408 		return;
409 	}
410 	(void) Findstr(nm, NULL, 0);
411 	if ((i = Sx) >= 0) {
412 		(void) Findstr(nm1, Str[i].str, 1);
413 		Delstr(i);
414 		return;
415 	}
416 	if (Findmacro(nm1, 0) < 0)
417 		(void) Findmacro(nm1, 1);
418 }
419 
420 
421 /*
422  * Remove register - "^[.']rr"
423  */
424 
425 static void nr_rr(unsigned char *line, int brk) {
426 	int i;				/* temporary index */
427 	unsigned char nm[4];		/* name buffer */
428 
429 	if (Asmname(&line[3], nm) == 0) {
430 		Error(WARN, LINE, " no name", NULL);
431 		return;
432 	}
433 	if ((i = Findnum(nm, 0, 0)) < 0) {
434 		Error(WARN, LINE, " no register", NULL);
435 		return;
436 	}
437 	Delnum(i);
438 }
439 
440 
441 /*
442  * Resume space - "^[.']rs"
443  */
444 
445 static void nr_rs(unsigned char *line, int brk) {
446 	Pass3(NOBREAK, (unsigned char *)"yesspace", NULL, 0);
447 }
448 
449 
450 /*
451  * Message - "^[.']tm"
452  */
453 
454 static void nr_tm(unsigned char *line, int brk) {
455 	Pass3(MESSAGE, Inname, (line[3] == ' ') ? &line[4] : &line[3], NR);
456 }
457 
458 
459 /*
460  * Translate - "^[.']tr abcd..."
461  */
462 
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 */
470 
471 	if (line[3] != ' ') {
472 		Error(WARN, LINE, " unknown translation", NULL);
473 		return;
474 	}
475 	for (s1 = &line[4]; *s1;) {
476 	    nm[1] = nm[2] = '\0';
477 	    s2 = s1 + 1;
478 	/*
479 	 * Assemble the input value.
480 	 */
481 	    if (*s1 == '\\' && (*s2 == '*' || *s2 == '(')) {
482 		if (*s2 == '(') {
483 	    /*
484 	     * Input is named character -- "\(xx".
485 	     */
486 		    trin = 1;
487 		    s1 = s2 + 1;
488 		    if ((nm[0] = *s1) != '\0') {
489 			s1++;
490 			if ((nm[1] = *s1) != '\0')
491 			    s1++;
492 		    }
493 		} else {
494 	    /*
495 	     * Input is interpolated string -- "\*x" or "\*(xx".
496 	     */
497 		    s1 = Asmcode(&s2, nm);
498 		    if (*s1)
499 			s1++;
500 		    s2 = Findstr(nm, NULL, 0);
501 		    if (*s2 != '\0') {
502 			if ((strlen((char *)s2) + strlen((char *)s1) + 1)
503 			>= MAXLINE)
504 			    Error(WARN, LINE, " string too long: ", (char *)nm);
505 			else {
506 			    (void) sprintf((char *)buf, "%s%s",
507 				(char *)s2, (char *)s1);
508 			    (void) strcpy((char *)xbuf, (char *)buf);
509 			    s1 = xbuf;
510 			}
511 		    }
512 		    continue;
513 		}
514 	    } else {
515 
516 	    /*
517 	     * Input is a simple character.
518 	     */
519 		trin = 0;
520 		if ((nm[0] = *s1) != '\0')
521 		    s1++;
522 	    }
523 	/*
524 	 * Assemble the output value.
525 	 */
526 
527 assemble_output:
528 	    nm1[1] = nm1[2] = '\0';
529 	    if (*s1 == '\0') {
530 
531 	    /*
532 	     * Supply a space if there is no output character.
533 	     */
534 		trout = 0;
535 		nm1[0] = ' ';
536 	    } else {
537 		s2 = s1 + 1;
538 		if (*s1 == '\\' && (*s2 == '(' || *s2 == '*')) {
539 		    if (*s2 == '(') {
540 		/*
541 		 * The output is a named character -- "\(xx".
542 		 */
543 			trout = 1;
544 			s1 = s2 + 1;
545 			if ((nm1[0] = *s1) != '\0') {
546 			    s1++;
547 			    if ((nm1[1] = *s1) != '\0')
548 				s1++;
549 			}
550 		    } else {
551 		/*
552 		 * The output is an interpolated string -- * "\*x" or "\*(xx".
553 		 */
554 			s1 = Asmcode(&s2, nm1);
555 			if (*s1)
556 			    s1++;
557 			s2 = Findstr(nm1, NULL, 0);
558 			if (*s2 != '\0') {
559 		    /*
560 		     * Interpolate a string value.
561 		     */
562 			    if ((strlen((char *)s2) + strlen((char *)s1) + 1)
563 			    >= MAXLINE)
564 				Error(WARN, LINE, " string too long: ",
565 				    (char *)nm);
566 			    else {
567 				(void) sprintf((char *)buf, "%s%s", (char *)s2,
568 				    (char *)s1);
569 				(void) strcpy((char *)xbuf, (char *)buf);
570 			        s1 = xbuf;
571 			    }
572 			}
573 			goto assemble_output;
574 		    }
575 		} else {
576 		    trout = 0;
577 		    if ((nm1[0] = *s1) != '0')
578 			s1++;
579 		    else
580 			nm1[0] = ' ';
581 		}
582 	    }
583 	/*
584 	 * Do the translation.
585 	 */
586 	    switch (trin) {
587 
588 	    case 0:			/* simple char */
589 		switch (trout) {
590 
591 		case 0:			/* to simple char */
592 		    Trtbl[(int)nm[0]] = nm1[0];
593 		    break;
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: ",
598 			    (char *)nm1);
599 		    else
600 			Trtbl[(int)nm[0]] = *(Schar[i].str);
601 		    break;
602 		}
603 		break;
604 	    case 1:			/* named char */
605 		if ((i = Findchar(nm, 0, NULL, 0)) < 0)
606 		    Error(WARN, LINE, " unknown named character: ", (char *)nm);
607 		else {
608 		    switch (trout) {
609 
610 		    case 0:		/* to simple char */
611 			Free(&Schar[i].str);
612 			Schar[i].str = Newstr(nm1);
613 			Schar[i].len = 1;
614 			break;
615 		    case 1:		/* to named char */
616 			if ((j = Findchar(nm1, 0, NULL, 0)) < 0)
617 			    Error(WARN, LINE, " unknown named character: ",
618 				(char *)nm1);
619 			else
620 			    (void) Findchar(nm, Schar[j].len, Schar[j].str, 1);
621 			break;
622 		    }
623 		}
624 		break;
625 	    }
626 	}
627 }
628 
629 
630 /*
631  * Initialization - "^[.']\^b (fh|HF|NH) [01]"
632  *
633  * fh = first page header status
634  * HF = header/footer status
635  * NH = initialize number headers
636  */
637 
638 static void nr_Ub(unsigned char *line, int brk) {
639 	int i;				/* temporary index */
640 	unsigned char *s1, *s2;		/* temporary string pointers */
641 
642 	if ((s1 = Field(2, line, 0)) == NULL)
643 		return;
644 	if ((s2 = Field(3, line, 0)) == NULL)
645 		i = 0;
646 	else
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')
651 		Hdft = i;
652 	else if (s1[0] == 'N' && s1[1] == 'H') {
653 		for (i = 0; i < MAXNHNR; i++)
654 			Nhnr[i] = 0;
655 	} else
656 		Error(WARN, LINE, " unknown initialization", NULL);
657 }
658 
659 
660 /*
661  * Character definitions - "^[.']\^c"
662  */
663 
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 */
668 		      *s4, *s5;
669 
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);
675 		return;
676 	}
677 	if (s4 == NULL)
678 		s4 = (unsigned char *)"";
679 	else if (*s4 == '"')
680 		s4++;
681 	s1 = buf;
682 	while ((s5 = (unsigned char *)strchr((char *)s4, '\\')) != NULL) {
683 		while (s5 > s4)
684 			*s1++ = *s4++;
685 		s4 = ++s5;
686 		if (*s5 == '\\')
687 			*s1++ = '\\';
688 		else if (*s5 == 'b')
689 			*s1++ = '\b';
690 		if (*s4)
691 			s4++;
692 	}
693 	while ((*s1++ = *s4++))
694 		;
695 	if (*s2 == 'h' && *(s2+1) == 'y')
696 		(void) Findhy(buf, i, 1);
697 	else
698 		(void) Findchar(s2, i, buf, 1);
699 }
700 
701 
702 /*
703  * Font is OK - "[.']\^f <font_name_character>"
704  */
705 
706 static void nr_Uf(unsigned char *line, int brk) {
707 	int i;				/* temporary index */
708 
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';
713 				return;
714 			}
715 		}
716 	}
717 	Error(WARN, LINE, " unknown font", NULL);
718 }
719 
720 
721 /*
722  * Resolutions - "[.']\^r cpi horizontal vertical"
723  */
724 
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 */
729 
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);
733 		return;
734 	}
735 	tval = (double) (240.0 / (double) i);
736 	if (Findscale((int)'m', tval, 1) < 0)
737 		Error(FATAL, LINE, " missing Scal['m']", NULL);
738 	Scalen = tval;
739 	if (Scalen <= 0.0) {
740 		(void) sprintf((char *)buf, " bad Scale['n'] (%f)", Scalen);
741 		Error(FATAL, LINE, (char *)buf, NULL);
742 	}
743 	if (Findscale((int)'n', tval, 1) < 0)
744 		Error(FATAL, LINE, " missing Scale['n']", NULL);
745 	Scalev = (double) (240.0 / (double) j);
746 	if (Scalev <= 0.0) {
747 		(void) sprintf((char *)buf, " bad Scale['v'] (%f)", Scalen);
748 		Error(FATAL, LINE, (char *)buf, NULL);
749 	}
750 	if (Findscale((int)'v', Scalev, 1) < 0)
751 		Error(FATAL, LINE, " missing Scale['v']", NULL);
752 }
753 
754 
755 /*
756  * Set line number and file name - "^[.']\^# <number> <file>"
757  *
758  * Lock line number and file name - "^[.']\^= <number> <file>"
759  */
760 
761 static void nr_UL(unsigned char *line, int brk) {
762 	unsigned char *s1;		/* temporary string pointer */
763 
764 	if ((s1 = Field(2, line, 0)) != NULL)
765 		P2il = atoi((char *)s1) - 1;
766 	else
767 		P2il = 0;
768 	Lockil = (line[2] == '#') ? 0 : 1;
769 	Free(&P2name);
770 	if (Field(3, line, 1) != NULL) {
771 		P2name = F;
772 		F = NULL;
773 	} else
774 		P2name = NULL;
775 }
776