xref: /plan9/sys/src/cmd/htmlroff/t16.c (revision 426d2b71458df9b491ba6c167f699b3f1f7b0428)
1*426d2b71SDavid du Colombier #include "a.h"
2*426d2b71SDavid du Colombier 
3*426d2b71SDavid du Colombier /*
4*426d2b71SDavid du Colombier  * 16. Conditional acceptance of input.
5*426d2b71SDavid du Colombier  *
6*426d2b71SDavid du Colombier  *	conditions are
7*426d2b71SDavid du Colombier  *		c - condition letter (o, e, t, n)
8*426d2b71SDavid du Colombier  *		!c - not c
9*426d2b71SDavid du Colombier  *		N - N>0
10*426d2b71SDavid du Colombier  *		!N - N <= 0
11*426d2b71SDavid du Colombier  *		'a'b' - if a==b
12*426d2b71SDavid du Colombier  *		!'a'b'	- if a!=b
13*426d2b71SDavid du Colombier  *
14*426d2b71SDavid du Colombier  *	\{xxx\} can be used for newline in bodies
15*426d2b71SDavid du Colombier  *
16*426d2b71SDavid du Colombier  *	.if .ie .el
17*426d2b71SDavid du Colombier  *
18*426d2b71SDavid du Colombier  */
19*426d2b71SDavid du Colombier 
20*426d2b71SDavid du Colombier int iftrue[20];
21*426d2b71SDavid du Colombier int niftrue;
22*426d2b71SDavid du Colombier 
23*426d2b71SDavid du Colombier void
startbody(void)24*426d2b71SDavid du Colombier startbody(void)
25*426d2b71SDavid du Colombier {
26*426d2b71SDavid du Colombier 	int c;
27*426d2b71SDavid du Colombier 
28*426d2b71SDavid du Colombier 	while((c = getrune()) == ' ' || c == '\t')
29*426d2b71SDavid du Colombier 		;
30*426d2b71SDavid du Colombier 	ungetrune(c);
31*426d2b71SDavid du Colombier }
32*426d2b71SDavid du Colombier 
33*426d2b71SDavid du Colombier void
skipbody(void)34*426d2b71SDavid du Colombier skipbody(void)
35*426d2b71SDavid du Colombier {
36*426d2b71SDavid du Colombier 	int c, cc, nbrace;
37*426d2b71SDavid du Colombier 
38*426d2b71SDavid du Colombier 	nbrace = 0;
39*426d2b71SDavid du Colombier 	for(cc=0; (c = getrune()) >= 0; cc=c){
40*426d2b71SDavid du Colombier 		if(c == '\n' && nbrace <= 0)
41*426d2b71SDavid du Colombier 			break;
42*426d2b71SDavid du Colombier 		if(cc == '\\' && c == '{')
43*426d2b71SDavid du Colombier 			nbrace++;
44*426d2b71SDavid du Colombier 		if(cc == '\\' && c == '}')
45*426d2b71SDavid du Colombier 			nbrace--;
46*426d2b71SDavid du Colombier 	}
47*426d2b71SDavid du Colombier }
48*426d2b71SDavid du Colombier 
49*426d2b71SDavid du Colombier int
ifeval(void)50*426d2b71SDavid du Colombier ifeval(void)
51*426d2b71SDavid du Colombier {
52*426d2b71SDavid du Colombier 	int c, cc, neg, nc;
53*426d2b71SDavid du Colombier 	Rune line[MaxLine], *p, *e, *q;
54*426d2b71SDavid du Colombier 	Rune *a;
55*426d2b71SDavid du Colombier 
56*426d2b71SDavid du Colombier 	while((c = getnext()) == ' ' || c == '\t')
57*426d2b71SDavid du Colombier 		;
58*426d2b71SDavid du Colombier 	neg = 0;
59*426d2b71SDavid du Colombier 	while(c == '!'){
60*426d2b71SDavid du Colombier 		neg = !neg;
61*426d2b71SDavid du Colombier 		c = getnext();
62*426d2b71SDavid du Colombier 	}
63*426d2b71SDavid du Colombier 
64*426d2b71SDavid du Colombier 	if('0' <= c && c <= '9'){
65*426d2b71SDavid du Colombier 		ungetnext(c);
66*426d2b71SDavid du Colombier 		a = copyarg();
67*426d2b71SDavid du Colombier 		c = (eval(a)>0) ^ neg;
68*426d2b71SDavid du Colombier 		free(a);
69*426d2b71SDavid du Colombier 		return c;
70*426d2b71SDavid du Colombier 	}
71*426d2b71SDavid du Colombier 
72*426d2b71SDavid du Colombier 	switch(c){
73*426d2b71SDavid du Colombier 	case ' ':
74*426d2b71SDavid du Colombier 	case '\n':
75*426d2b71SDavid du Colombier 		ungetnext(c);
76*426d2b71SDavid du Colombier 		return !neg;
77*426d2b71SDavid du Colombier 	case 'o':	/* odd page */
78*426d2b71SDavid du Colombier 	case 't':	/* troff */
79*426d2b71SDavid du Colombier 	case 'h':	/* htmlroff */
80*426d2b71SDavid du Colombier 		while((c = getrune()) != ' ' && c != '\t' && c != '\n' && c >= 0)
81*426d2b71SDavid du Colombier 			;
82*426d2b71SDavid du Colombier 		return 1 ^ neg;
83*426d2b71SDavid du Colombier 	case 'n':	/* nroff */
84*426d2b71SDavid du Colombier 	case 'e':	/* even page */
85*426d2b71SDavid du Colombier 		while((c = getnext()) != ' ' && c != '\t' && c != '\n' && c >= 0)
86*426d2b71SDavid du Colombier 			;
87*426d2b71SDavid du Colombier 		return 0 ^ neg;
88*426d2b71SDavid du Colombier 	}
89*426d2b71SDavid du Colombier 
90*426d2b71SDavid du Colombier 	/* string comparison 'string1'string2' */
91*426d2b71SDavid du Colombier 	p = line;
92*426d2b71SDavid du Colombier 	e = p+nelem(line);
93*426d2b71SDavid du Colombier 	nc = 0;
94*426d2b71SDavid du Colombier 	q = nil;
95*426d2b71SDavid du Colombier 	while((cc=getnext()) >= 0 && cc != '\n' && p<e){
96*426d2b71SDavid du Colombier 		if(cc == c){
97*426d2b71SDavid du Colombier 			if(++nc == 2)
98*426d2b71SDavid du Colombier 				break;
99*426d2b71SDavid du Colombier 			q = p;
100*426d2b71SDavid du Colombier 		}
101*426d2b71SDavid du Colombier 		*p++ = cc;
102*426d2b71SDavid du Colombier 	}
103*426d2b71SDavid du Colombier 	if(cc != c){
104*426d2b71SDavid du Colombier 		ungetnext(cc);
105*426d2b71SDavid du Colombier 		return 0;
106*426d2b71SDavid du Colombier 	}
107*426d2b71SDavid du Colombier 	if(nc < 2){
108*426d2b71SDavid du Colombier 		return 0;
109*426d2b71SDavid du Colombier 	}
110*426d2b71SDavid du Colombier 	*p = 0;
111*426d2b71SDavid du Colombier 	return (q-line == p-(q+1)
112*426d2b71SDavid du Colombier 		&& memcmp(line, q+1, (q-line)*sizeof(Rune))==0) ^ neg;
113*426d2b71SDavid du Colombier }
114*426d2b71SDavid du Colombier 
115*426d2b71SDavid du Colombier void
r_if(Rune * name)116*426d2b71SDavid du Colombier r_if(Rune *name)
117*426d2b71SDavid du Colombier {
118*426d2b71SDavid du Colombier 	int n;
119*426d2b71SDavid du Colombier 
120*426d2b71SDavid du Colombier 	n = ifeval();
121*426d2b71SDavid du Colombier 	if(runestrcmp(name, L("ie")) == 0){
122*426d2b71SDavid du Colombier 		if(niftrue >= nelem(iftrue))
123*426d2b71SDavid du Colombier 			sysfatal("%Cie overflow", dot);
124*426d2b71SDavid du Colombier 		iftrue[niftrue++] = n;
125*426d2b71SDavid du Colombier 	}
126*426d2b71SDavid du Colombier 	if(n)
127*426d2b71SDavid du Colombier 		startbody();
128*426d2b71SDavid du Colombier 	else
129*426d2b71SDavid du Colombier 		skipbody();
130*426d2b71SDavid du Colombier }
131*426d2b71SDavid du Colombier 
132*426d2b71SDavid du Colombier void
r_el(Rune * name)133*426d2b71SDavid du Colombier r_el(Rune *name)
134*426d2b71SDavid du Colombier {
135*426d2b71SDavid du Colombier 	USED(name);
136*426d2b71SDavid du Colombier 
137*426d2b71SDavid du Colombier 	if(niftrue <= 0){
138*426d2b71SDavid du Colombier 		warn("%Cel underflow", dot);
139*426d2b71SDavid du Colombier 		return;
140*426d2b71SDavid du Colombier 	}
141*426d2b71SDavid du Colombier 	if(iftrue[--niftrue])
142*426d2b71SDavid du Colombier 		skipbody();
143*426d2b71SDavid du Colombier 	else
144*426d2b71SDavid du Colombier 		startbody();
145*426d2b71SDavid du Colombier }
146*426d2b71SDavid du Colombier 
147*426d2b71SDavid du Colombier void
t16init(void)148*426d2b71SDavid du Colombier t16init(void)
149*426d2b71SDavid du Colombier {
150*426d2b71SDavid du Colombier 	addraw(L("if"), r_if);
151*426d2b71SDavid du Colombier 	addraw(L("ie"), r_if);
152*426d2b71SDavid du Colombier 	addraw(L("el"), r_el);
153*426d2b71SDavid du Colombier 
154*426d2b71SDavid du Colombier 	addesc('{', e_nop, HtmlMode|ArgMode);
155*426d2b71SDavid du Colombier 	addesc('}', e_nop, HtmlMode|ArgMode);
156*426d2b71SDavid du Colombier }
157