Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_posix/sys/src/cmd/troff/n4.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * troff4.c
3
 *
4
 * number registers, conversion, arithmetic
5
 */
6
 
7
#include "tdef.h"
8
#include "fns.h"
9
#include "ext.h"
10
 
11
 
12
int	regcnt = NNAMES;
13
int	falsef	= 0;	/* on if inside false branch of if */
14
 
15
#define	NHASHSIZE	128	/* must be 2**n */
16
#define	NHASH(i)	((i>>6)^i) & (NHASHSIZE-1)
17
Numtab	*nhash[NHASHSIZE];
18
 
19
Numtab *numtabp = NULL;
20
#define NDELTA 400
21
int ncnt = 0;
22
 
23
void setn(void)
24
{
25
	int i, j, f;
26
	Tchar ii;
27
	Uchar *p;
28
	char buf[NTM];		/* for \n(.S */
29
 
30
	f = nform = 0;
31
	if ((i = cbits(ii = getach())) == '+')
32
		f = 1;
33
	else if (i == '-')
34
		f = -1;
35
	else if (ii)	/* don't put it back if it's already back (thanks to jaap) */
36
		ch = ii;
37
	if (falsef)
38
		f = 0;
39
	if ((i = getsn()) == 0)
40
		return;
41
	p = unpair(i);
42
	if (p[0] == '.')
43
		switch (p[1]) {
44
		case 's':
45
			i = pts;
46
			break;
47
		case 'v':
48
			i = lss;
49
			break;
50
		case 'f':
51
			i = font;
52
			break;
53
		case 'p':
54
			i = pl;
55
			break;
56
		case 't':
57
			i = findt1();
58
			break;
59
		case 'o':
60
			i = po;
61
			break;
62
		case 'l':
63
			i = ll;
64
			break;
65
		case 'i':
66
			i = in;
67
			break;
68
		case '$':
69
			i = frame->nargs;
70
			break;
71
		case 'A':
72
			i = ascii;
73
			break;
74
		case 'c':
75
			i = numtabp[CD].val;
76
			break;
77
		case 'n':
78
			i = lastl;
79
			break;
80
		case 'a':
81
			i = ralss;
82
			break;
83
		case 'h':
84
			i = dip->hnl;
85
			break;
86
		case 'd':
87
			if (dip != d)
88
				i = dip->dnl;
89
			else
90
				i = numtabp[NL].val;
91
			break;
92
		case 'u':
93
			i = fi;
94
			break;
95
		case 'j':
96
			i = ad + 2 * admod;
97
			break;
98
		case 'w':
99
			i = widthp;
100
			break;
101
		case 'x':
102
			i = nel;
103
			break;
104
		case 'y':
105
			i = un;
106
			break;
107
		case 'T':
108
			i = dotT;
109
			break;	 /* -Tterm used in nroff */
110
		case 'V':
111
			i = VERT;
112
			break;
113
		case 'H':
114
			i = HOR;
115
			break;
116
		case 'k':
117
			i = ne;
118
			break;
119
		case 'P':
120
			i = print;
121
			break;
122
		case 'L':
123
			i = ls;
124
			break;
125
		case 'R':	/* maximal # of regs that can be addressed */
126
			i = 255*256 - regcnt; 
127
			break;
128
		case 'z':
129
			p = unpair(dip->curd);
130
			*pbp++ = p[1];	/* watch order */
131
			*pbp++ = p[0];
132
			return;
133
		case 'b':
134
			i = bdtab[font];
135
			break;
136
		case 'F':
137
			cpushback(cfname[ifi]);
138
			return;
139
 		case 'S':
140
 			buf[0] = j = 0;	
141
 			for( i = 0; tabtab[i] != 0 && i < NTAB; i++) {
142
 				if (i > 0)
143
 					buf[j++] = ' ';
144
 				sprintf(&buf[j], "%d", tabtab[i] & TABMASK);
145
 				j = strlen(buf);
146
 				if ( tabtab[i] & RTAB)
147
 					sprintf(&buf[j], "uR");
148
 				else if (tabtab[i] & CTAB)
149
 					sprintf(&buf[j], "uC");
150
 				else
151
 					sprintf(&buf[j], "uL");
152
 				j += 2;
153
 			}
154
 			cpushback(buf);
155
 			return;
156
		default:
157
			goto s0;
158
		}
159
	else {
160
s0:
161
		if ((j = findr(i)) == -1)
162
			i = 0;
163
		else {
164
			i = numtabp[j].val = numtabp[j].val + numtabp[j].inc * f;
165
			nform = numtabp[j].fmt;
166
		}
167
	}
168
	setn1(i, nform, (Tchar) 0);
169
}
170
 
171
Tchar	numbuf[25];
172
Tchar	*numbufp;
173
 
174
int wrc(Tchar i)
175
{
176
	if (numbufp >= &numbuf[24])
177
		return(0);
178
	*numbufp++ = i;
179
	return(1);
180
}
181
 
182
 
183
 
184
/* insert into input number i, in format form, with size-font bits bits */
185
void setn1(int i, int form, Tchar bits)
186
{
187
	numbufp = numbuf;
188
	nrbits = bits;
189
	nform = form;
190
	fnumb(i, wrc);
191
	*numbufp = 0;
192
	pushback(numbuf);
193
}
194
 
195
void prnumtab(Numtab *p)
196
{
197
	int i;
198
	for (i = 0; i < ncnt; i++)
199
		if (p)
200
			if (p[i].r != 0)
201
				fprintf(stderr, "slot %d, %s, val %d\n", i, unpair(p[i].r), p[i].val);
202
			else
203
				fprintf(stderr, "slot %d empty\n", i);
204
		else
205
			fprintf(stderr, "slot %d empty\n", i);
206
}
207
 
208
void nnspace(void)
209
{
210
	ncnt = sizeof(numtab)/sizeof(Numtab) + NDELTA;
211
	numtabp = (Numtab *) grow((char *)numtabp, ncnt, sizeof(Numtab));
212
	if (numtabp == NULL) {
213
		ERROR "not enough memory for registers (%d)", ncnt WARN;
214
		exit(1);
215
	}
216
	numtabp = (Numtab *) memcpy((char *)numtabp, (char *)numtab,
217
							sizeof(numtab));
218
	if (numtabp == NULL) {
219
		ERROR "Cannot initialize registers" WARN;
220
		exit(1);
221
	}
222
}
223
 
224
void grownumtab(void)
225
{
226
	ncnt += NDELTA;
227
	numtabp = (Numtab *) grow((char *) numtabp, ncnt, sizeof(Numtab));
228
	if (numtabp == NULL) {
229
		ERROR "Too many number registers (%d)", ncnt WARN;
230
		done2(04);
231
	} else {
232
		memset((char *)(numtabp) + (ncnt - NDELTA) * sizeof(Numtab),
233
						0, NDELTA * sizeof(Numtab));
234
		nrehash();
235
	}
236
}
237
 
238
void nrehash(void)
239
{
240
	Numtab *p;
241
	int i;
242
 
243
	for (i=0; i<NHASHSIZE; i++)
244
		nhash[i] = 0;
245
	for (p=numtabp; p < &numtabp[ncnt]; p++)
246
		p->link = 0;
247
	for (p=numtabp; p < &numtabp[ncnt]; p++) {
248
		if (p->r == 0)
249
			continue;
250
		i = NHASH(p->r);
251
		p->link = nhash[i];
252
		nhash[i] = p;
253
	}
254
}
255
 
256
void nunhash(Numtab *rp)
257
{
258
	Numtab *p;
259
	Numtab **lp;
260
 
261
	if (rp->r == 0)
262
		return;
263
	lp = &nhash[NHASH(rp->r)];
264
	p = *lp;
265
	while (p) {
266
		if (p == rp) {
267
			*lp = p->link;
268
			p->link = 0;
269
			return;
270
		}
271
		lp = &p->link;
272
		p = p->link;
273
	}
274
}
275
 
276
int findr(int i)
277
{
278
	Numtab *p;
279
	int h = NHASH(i);
280
 
281
	if (i == 0)
282
		return(-1);
283
a0:
284
	for (p = nhash[h]; p; p = p->link)
285
		if (i == p->r)
286
			return(p - numtabp);
287
	for (p = numtabp; p < &numtabp[ncnt]; p++) {
288
		if (p->r == 0) {
289
			p->r = i;
290
			p->link = nhash[h];
291
			nhash[h] = p;
292
			regcnt++;
293
			return(p - numtabp);
294
		}
295
	}
296
	grownumtab();
297
	goto a0;
298
}
299
 
300
int usedr(int i)	/* returns -1 if nr i has never been used */
301
{
302
	Numtab *p;
303
 
304
	if (i == 0)
305
		return(-1);
306
	for (p = nhash[NHASH(i)]; p; p = p->link)
307
		if (i == p->r)
308
			return(p - numtabp);
309
	return -1;
310
}
311
 
312
 
313
int fnumb(int i, int (*f)(Tchar))
314
{
315
	int j;
316
 
317
	j = 0;
318
	if (i < 0) {
319
		j = (*f)('-' | nrbits);
320
		i = -i;
321
	}
322
	switch (nform) {
323
	default:
324
	case '1':
325
	case 0:
326
		return decml(i, f) + j;
327
	case 'i':
328
	case 'I':
329
		return roman(i, f) + j;
330
	case 'a':
331
	case 'A':
332
		return abc(i, f) + j;
333
	}
334
}
335
 
336
 
337
int decml(int i, int (*f)(Tchar))
338
{
339
	int j, k;
340
 
341
	k = 0;
342
	nform--;
343
	if ((j = i / 10) || (nform > 0))
344
		k = decml(j, f);
345
	return(k + (*f)((i % 10 + '0') | nrbits));
346
}
347
 
348
 
349
int roman(int i, int (*f)(Tchar))
350
{
351
 
352
	if (!i)
353
		return((*f)('0' | nrbits));
354
	if (nform == 'i')
355
		return(roman0(i, f, "ixcmz", "vldw"));
356
	else
357
		return(roman0(i, f, "IXCMZ", "VLDW"));
358
}
359
 
360
 
361
int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp)
362
{
363
	int q, rem, k;
364
 
365
	if (!i)
366
		return(0);
367
	k = roman0(i / 10, f, onesp + 1, fivesp + 1);
368
	q = (i = i % 10) / 5;
369
	rem = i % 5;
370
	if (rem == 4) {
371
		k += (*f)(*onesp | nrbits);
372
		if (q)
373
			i = *(onesp + 1);
374
		else
375
			i = *fivesp;
376
		return(k += (*f)(i | nrbits));
377
	}
378
	if (q)
379
		k += (*f)(*fivesp | nrbits);
380
	while (--rem >= 0)
381
		k += (*f)(*onesp | nrbits);
382
	return(k);
383
}
384
 
385
 
386
int abc(int i, int (*f)(Tchar))
387
{
388
	if (!i)
389
		return((*f)('0' | nrbits));
390
	else
391
		return(abc0(i - 1, f));
392
}
393
 
394
 
395
int abc0(int i, int (*f)(Tchar))
396
{
397
	int j, k;
398
 
399
	k = 0;
400
	if (j = i / 26)
401
		k = abc0(j - 1, f);
402
	return(k + (*f)((i % 26 + nform) | nrbits));
403
}
404
 
405
long atoi0(void)
406
{
407
	int c, k, cnt;
408
	Tchar ii;
409
	long i, acc;
410
 
411
	acc = 0;
412
	nonumb = 0;
413
	cnt = -1;
414
a0:
415
	cnt++;
416
	ii = getch();
417
	c = cbits(ii);
418
	switch (c) {
419
	default:
420
		ch = ii;
421
		if (cnt)
422
			break;
423
	case '+':
424
		i = ckph();
425
		if (nonumb)
426
			break;
427
		acc += i;
428
		goto a0;
429
	case '-':
430
		i = ckph();
431
		if (nonumb)
432
			break;
433
		acc -= i;
434
		goto a0;
435
	case '*':
436
		i = ckph();
437
		if (nonumb)
438
			break;
439
		acc *= i;
440
		goto a0;
441
	case '/':
442
		i = ckph();
443
		if (nonumb)
444
			break;
445
		if (i == 0) {
446
			flusho();
447
			ERROR "divide by zero." WARN;
448
			acc = 0;
449
		} else
450
			acc /= i;
451
		goto a0;
452
	case '%':
453
		i = ckph();
454
		if (nonumb)
455
			break;
456
		acc %= i;
457
		goto a0;
458
	case '&':	/*and*/
459
		i = ckph();
460
		if (nonumb)
461
			break;
462
		if ((acc > 0) && (i > 0))
463
			acc = 1;
464
		else
465
			acc = 0;
466
		goto a0;
467
	case ':':	/*or*/
468
		i = ckph();
469
		if (nonumb)
470
			break;
471
		if ((acc > 0) || (i > 0))
472
			acc = 1;
473
		else
474
			acc = 0;
475
		goto a0;
476
	case '=':
477
		if (cbits(ii = getch()) != '=')
478
			ch = ii;
479
		i = ckph();
480
		if (nonumb) {
481
			acc = 0;
482
			break;
483
		}
484
		if (i == acc)
485
			acc = 1;
486
		else
487
			acc = 0;
488
		goto a0;
489
	case '>':
490
		k = 0;
491
		if (cbits(ii = getch()) == '=')
492
			k++;
493
		else
494
			ch = ii;
495
		i = ckph();
496
		if (nonumb) {
497
			acc = 0;
498
			break;
499
		}
500
		if (acc > (i - k))
501
			acc = 1;
502
		else
503
			acc = 0;
504
		goto a0;
505
	case '<':
506
		k = 0;
507
		if (cbits(ii = getch()) == '=')
508
			k++;
509
		else
510
			ch = ii;
511
		i = ckph();
512
		if (nonumb) {
513
			acc = 0;
514
			break;
515
		}
516
		if (acc < (i + k))
517
			acc = 1;
518
		else
519
			acc = 0;
520
		goto a0;
521
	case ')':
522
		break;
523
	case '(':
524
		acc = atoi0();
525
		goto a0;
526
	}
527
	return(acc);
528
}
529
 
530
 
531
long ckph(void)
532
{
533
	Tchar i;
534
	long j;
535
 
536
	if (cbits(i = getch()) == '(')
537
		j = atoi0();
538
	else {
539
		j = atoi1(i);
540
	}
541
	return(j);
542
}
543
 
544
 
545
/*
546
 * print error about illegal numeric argument;
547
 */
548
void prnumerr(void)
549
{
550
	char err_buf[40];
551
	static char warn[] = "Numeric argument expected";
552
	int savcd = numtabp[CD].val;
553
 
554
	if (numerr.type == RQERR)
555
		sprintf(err_buf, "%c%s: %s", nb ? cbits(c2) : cbits(cc),
556
						unpair(numerr.req), warn);
557
	else
558
		sprintf(err_buf, "\\%c'%s': %s", numerr.esc, &numerr.escarg,
559
									warn);
560
	if (frame != stk)	/* uncertainty correction */
561
		numtabp[CD].val--;
562
	ERROR err_buf WARN;
563
	numtabp[CD].val = savcd;
564
}
565
 
566
 
567
long atoi1(Tchar ii)
568
{
569
	int i, j, digits;
570
	double acc;	/* this is the only double in troff! */
571
	int neg, abs, field, decpnt;
572
	extern int ifnum;
573
 
574
 
575
	neg = abs = field = decpnt = digits = 0;
576
	acc = 0;
577
	for (;;) {
578
		i = cbits(ii);
579
		switch (i) {
580
		default:
581
			break;
582
		case '+':
583
			ii = getch();
584
			continue;
585
		case '-':
586
			neg = 1;
587
			ii = getch();
588
			continue;
589
		case '|':
590
			abs = 1 + neg;
591
			neg = 0;
592
			ii = getch();
593
			continue;
594
		}
595
		break;
596
	}
597
a1:
598
	while (i >= '0' && i <= '9') {
599
		field++;
600
		digits++;
601
		acc = 10 * acc + i - '0';
602
		ii = getch();
603
		i = cbits(ii);
604
	}
605
	if (i == '.' && !decpnt++) {
606
		field++;
607
		digits = 0;
608
		ii = getch();
609
		i = cbits(ii);
610
		goto a1;
611
	}
612
	if (!field) {
613
		ch = ii;
614
		goto a2;
615
	}
616
	switch (i) {
617
	case 'u':
618
		i = j = 1;	/* should this be related to HOR?? */
619
		break;
620
	case 'v':	/*VSs - vert spacing*/
621
		j = lss;
622
		i = 1;
623
		break;
624
	case 'm':	/*Ems*/
625
		j = EM;
626
		i = 1;
627
		break;
628
	case 'n':	/*Ens*/
629
		j = EM;
630
		if (TROFF)
631
			i = 2;
632
		else
633
			i = 1;	/*Same as Ems in NROFF*/
634
		break;
635
	case 'p':	/*Points*/
636
		j = INCH;
637
		i = 72;
638
		break;
639
	case 'i':	/*Inches*/
640
		j = INCH;
641
		i = 1;
642
		break;
643
	case 'c':	/*Centimeters*/
644
		/* if INCH is too big, this will overflow */
645
		j = INCH * 50;
646
		i = 127;
647
		break;
648
	case 'P':	/*Picas*/
649
		j = INCH;
650
		i = 6;
651
		break;
652
	default:
653
		j = dfact;
654
		ch = ii;
655
		i = dfactd;
656
	}
657
	if (neg)
658
		acc = -acc;
659
	if (!noscale) {
660
		acc = (acc * j) / i;
661
	}
662
	if (field != digits && digits > 0)
663
		while (digits--)
664
			acc /= 10;
665
	if (abs) {
666
		if (dip != d)
667
			j = dip->dnl;
668
		else
669
			j = numtabp[NL].val;
670
		if (!vflag) {
671
			j = numtabp[HP].val;
672
		}
673
		if (abs == 2)
674
			j = -j;
675
		acc -= j;
676
	}
677
a2:
678
	nonumb = (!field || field == decpnt);
679
	if (nonumb && (trace & TRNARGS) && !ismot(ii) && !nlflg && !ifnum) {
680
		if (cbits(ii) != RIGHT ) /* Too painful to do right */
681
			prnumerr();
682
	}
683
	return(acc);
684
}
685
 
686
 
687
void caserr(void)
688
{
689
	int i, j;
690
	Numtab *p;
691
 
692
	lgf++;
693
	while (!skip() && (i = getrq()) ) {
694
		j = usedr(i);
695
		if (j < 0)
696
			continue;
697
		p = &numtabp[j];
698
		nunhash(p);
699
		p->r = p->val = p->inc = p->fmt = 0;
700
		regcnt--;
701
	}
702
}
703
 
704
/*
705
 * .nr request; if tracing, don't check optional
706
 * 2nd argument because tbl generates .in 1.5n
707
 */
708
void casenr(void)
709
{
710
	int i, j;
711
	int savtr = trace;
712
 
713
	lgf++;
714
	skip();
715
	if ((i = findr(getrq())) == -1)
716
		goto rtn;
717
	skip();
718
	j = inumb(&numtabp[i].val);
719
	if (nonumb)
720
		goto rtn;
721
	numtabp[i].val = j;
722
	skip();
723
	trace = 0;
724
	j = atoi0();		/* BUG??? */
725
	trace = savtr;
726
	if (nonumb)
727
		goto rtn;
728
	numtabp[i].inc = j;
729
rtn:
730
	return;
731
}
732
 
733
void caseaf(void)
734
{
735
	int i, k;
736
	Tchar j;
737
 
738
	lgf++;
739
	if (skip() || !(i = getrq()) || skip())
740
		return;
741
	k = 0;
742
	j = getch();
743
	if (!isalpha(cbits(j))) {
744
		ch = j;
745
		while ((j = cbits(getch())) >= '0' &&  j <= '9')
746
			k++;
747
	}
748
	if (!k)
749
		k = j;
750
	numtabp[findr(i)].fmt = k;	/* was k & BYTEMASK */
751
}
752
 
753
void setaf(void)	/* return format of number register */
754
{
755
	int i, j;
756
 
757
	i = usedr(getsn());
758
	if (i == -1)
759
		return;
760
	if (numtabp[i].fmt > 20)	/* it was probably a, A, i or I */
761
		*pbp++ = numtabp[i].fmt;
762
	else
763
		for (j = (numtabp[i].fmt ? numtabp[i].fmt : 1); j; j--)
764
			*pbp++ = '0';
765
}
766
 
767
 
768
int vnumb(int *i)
769
{
770
	vflag++;
771
	dfact = lss;
772
	res = VERT;
773
	return(inumb(i));
774
}
775
 
776
 
777
int hnumb(int *i)
778
{
779
	dfact = EM;
780
	res = HOR;
781
	return(inumb(i));
782
}
783
 
784
 
785
int inumb(int *n)
786
{
787
	int i, j, f;
788
	Tchar ii;
789
 
790
	f = 0;
791
	if (n) {
792
		if ((j = cbits(ii = getch())) == '+')
793
			f = 1;
794
		else if (j == '-')
795
			f = -1;
796
		else
797
			ch = ii;
798
	}
799
	i = atoi0();
800
	if (n && f)
801
		i = *n + f * i;
802
	i = quant(i, res);
803
	vflag = 0;
804
	res = dfactd = dfact = 1;
805
	if (nonumb)
806
		i = 0;
807
	return(i);
808
}
809
 
810
 
811
int quant(int n, int m)
812
{
813
	int i, neg;
814
 
815
	neg = 0;
816
	if (n < 0) {
817
		neg++;
818
		n = -n;
819
	}
820
	/* better as i = ((n + m/2)/m)*m */
821
	i = n / m;
822
	if (n - m * i > m / 2)
823
		i += 1;
824
	i *= m;
825
	if (neg)
826
		i = -i;
827
	return(i);
828
}