plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

t16.c (2261B)


      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 }