t16.c 2.2 KB

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