Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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