aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/htmlroff/t16.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/htmlroff/t16.c')
-rw-r--r--src/cmd/htmlroff/t16.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/cmd/htmlroff/t16.c b/src/cmd/htmlroff/t16.c
new file mode 100644
index 00000000..3a9c427e
--- /dev/null
+++ b/src/cmd/htmlroff/t16.c
@@ -0,0 +1,156 @@
+#include "a.h"
+
+/*
+ * 16. Conditional acceptance of input.
+ *
+ * conditions are
+ * c - condition letter (o, e, t, n)
+ * !c - not c
+ * N - N>0
+ * !N - N <= 0
+ * 'a'b' - if a==b
+ * !'a'b' - if a!=b
+ *
+ * \{xxx\} can be used for newline in bodies
+ *
+ * .if .ie .el
+ *
+ */
+
+int iftrue[20];
+int niftrue;
+
+void
+startbody(void)
+{
+ int c;
+
+ while((c = getrune()) == ' ' || c == '\t')
+ ;
+ ungetrune(c);
+}
+
+void
+skipbody(void)
+{
+ int c, cc, nbrace;
+
+ nbrace = 0;
+ for(cc=0; (c = getrune()) >= 0; cc=c){
+ if(c == '\n' && nbrace <= 0)
+ break;
+ if(cc == '\\' && c == '{')
+ nbrace++;
+ if(cc == '\\' && c == '}')
+ nbrace--;
+ }
+}
+
+int
+ifeval(void)
+{
+ int c, cc, neg, nc;
+ Rune line[MaxLine], *p, *e, *q;
+ Rune *a;
+
+ while((c = getnext()) == ' ' || c == '\t')
+ ;
+ neg = 0;
+ while(c == '!'){
+ neg = !neg;
+ c = getnext();
+ }
+
+ if('0' <= c && c <= '9'){
+ ungetnext(c);
+ a = copyarg();
+ c = (eval(a)>0) ^ neg;
+ free(a);
+ return c;
+ }
+
+ switch(c){
+ case ' ':
+ case '\n':
+ ungetnext(c);
+ return !neg;
+ case 'o': /* odd page */
+ case 't': /* troff */
+ case 'h': /* htmlroff */
+ while((c = getrune()) != ' ' && c != '\t' && c != '\n' && c >= 0)
+ ;
+ return 1 ^ neg;
+ case 'n': /* nroff */
+ case 'e': /* even page */
+ while((c = getnext()) != ' ' && c != '\t' && c != '\n' && c >= 0)
+ ;
+ return 0 ^ neg;
+ }
+
+ /* string comparison 'string1'string2' */
+ p = line;
+ e = p+nelem(line);
+ nc = 0;
+ q = nil;
+ while((cc=getnext()) >= 0 && cc != '\n' && p<e){
+ if(cc == c){
+ if(++nc == 2)
+ break;
+ q = p;
+ }
+ *p++ = cc;
+ }
+ if(cc != c){
+ ungetnext(cc);
+ return 0;
+ }
+ if(nc < 2){
+ return 0;
+ }
+ *p = 0;
+ return (q-line == p-(q+1)
+ && memcmp(line, q+1, (q-line)*sizeof(Rune))==0) ^ neg;
+}
+
+void
+r_if(Rune *name)
+{
+ int n;
+
+ n = ifeval();
+ if(runestrcmp(name, L("ie")) == 0){
+ if(niftrue >= nelem(iftrue))
+ sysfatal("%Cie overflow", dot);
+ iftrue[niftrue++] = n;
+ }
+ if(n)
+ startbody();
+ else
+ skipbody();
+}
+
+void
+r_el(Rune *name)
+{
+ USED(name);
+
+ if(niftrue <= 0){
+ warn("%Cel underflow", dot);
+ return;
+ }
+ if(iftrue[--niftrue])
+ skipbody();
+ else
+ startbody();
+}
+
+void
+t16init(void)
+{
+ addraw(L("if"), r_if);
+ addraw(L("ie"), r_if);
+ addraw(L("el"), r_el);
+
+ addesc('{', e_nop, HtmlMode|ArgMode);
+ addesc('}', e_nop, HtmlMode|ArgMode);
+}