extex.w
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
源码类别:

通讯编程

开发平台:

Visual C++

  1. datethis
  2. @* Introduction. This program is a simple filter that inputs TEX/ or .{CWEB}
  3. files and outputs its best guess at the ``words'' they contain. The word
  4. list can then be passed to a spelling check routine such as {tt wordtest}.
  5. If this program is invoked with the name `{tt excweb}', it will apply
  6. special rules based on the syntax of .{CWEB} files. Otherwise it will
  7. use only the TEX/ conventions. (Note that UNIX/'s {tt ln} command
  8. allows a program to be invoked with more than one name although it
  9. appears only once in the computer's memory.)
  10. The TEX/ conventions adopted here say that words are what remain
  11. after you remove nonletters, control sequences,
  12. comments triggered by .% marks, and material enclosed
  13. within .{$...$} or .{$$...$$}. However, an apostrophe within
  14. a word will be retained. The plain TEX/ control
  15. sequences for accented characters and special text characters, namely
  16. $$vbox{halign{&.{\#}hfilqquadcr
  17. '&`&relax^&"&relax~&=&.&u&vcr
  18. H&t&c&d&b&oe&OE&ae&AEcr
  19. aa&AA&o&O&l&L&ss&i&jcr}}$$
  20. will also be retained, so that users can treat them as parts of words.
  21. A blank space
  22. following any of the alphabetic control sequences in this list will be carried
  23. along too. If any of these control sequences is followed by .{, everything
  24. up to the next .} will also be retained. Thus, for example, the
  25. construction `.{m\={\i}n\u us}' will be considered a single word,
  26. in spite of the control sequences and the space between the two u's.
  27. The .{CWEB} conventions are essentially the same as the TEX/ conventions,
  28. in the TEX/ parts of a .{CWEB} file. The CEE/ parts of the file
  29. are blanked out.
  30. No attempt is made to reach a high level of artificial intelligence,
  31. which would be able to truly understand the input file. Tricky users can
  32.  confuse us. But we claim that devious tricks are their problem, not ours.
  33. @ So here goes. The main idea is to keep a one-character lookahead
  34. buffer, called |c|, which is set to zero when the character has been
  35. processed. A giant switch to various cases, depending on the value of~|c|,
  36. keeps everything moving.
  37. If you don't like |goto| statements, don't read this. (And don't read
  38. any other programs that simulate finite-state automata.)
  39. @c
  40. #include <stdio.h>
  41. #include <ctype.h>
  42. extern void exit(); /* system routine that terminates execution */
  43. @#
  44. @<Global variables@>@;
  45. @<Procedures@>@;
  46. @#
  47. int main(argc,argv)
  48.   int argc; /* the number of arguments (should be 1, but this isn't checked) */
  49.   char *argv[]; /* the arguments (|*argv| is the program name) */
  50. {
  51.   @<Local variables@>;
  52.   if (strlen(*argv)>=6 && strcmp(*argv+strlen(*argv)-6,"excweb")==0) {
  53.     web=1;
  54.     @<Adjust tables for .{CWEB} mode@>;
  55.   } else web=0;
  56.   comment=skipping=c=0;
  57.   main_cycle: if (c) goto big_switch;
  58.   restart: c=get();
  59.   big_switch: switch(c) {
  60.      @<Special cases of the giant switch where we don't just discard |c|@>@;
  61.     case EOF: exit(0);
  62.     default: goto restart;
  63.     }
  64.     @<Labeled code segments, which exit by explicit |goto|@>;
  65. }
  66. @ @<Global variables@>=
  67. int c; /* one-character look-see buffer */
  68. @ @<Local variables@>=
  69. int web; /* are we looking for .{CWEB} constructs? */
  70. int comment; /* are we inside a CEE/ comment in a .{CWEB} document? */
  71. int skipping; /* are we skipping CEE/ code in a .{CWEB} document? */
  72. int save_skipping; /* value of |skipping| outside current CEE/ mode */
  73. register int cc; /* temporary buffer */
  74. @* Simple cases.
  75. Let's do some of the easiest things first, in order to get the hang of
  76. this program. Several special characters will cause us to ignore everything
  77. until the first appearance of something else.
  78. @d discard_to(x) {@+while (get()!=x) ;@+}
  79. @<Special cases...@>=
  80. case '%': discard_to('n');@+goto restart;
  81. case '$': c=getchar();
  82.   if (c!='$') discard_to('$')@;
  83.   else { /* after .{$$} we discard everything to the next .{$$} */
  84.     do discard_to('$')@;
  85.     while (getchar()!='$');
  86.   }
  87.   goto restart;
  88. @ The `|get|' procedure in the code above is like Cee's standard
  89. `|getchar|', except that it immediately terminates execution at the end of
  90. the input file. Otherwise malformed input files could lead to
  91. infinite loops.
  92. @<Procedures@>=
  93. int get()
  94. {@+register int x;
  95.   x=getchar();
  96.   if (x==EOF) exit(0);
  97.   return x;
  98. }
  99.  
  100. @ More complex behavior is handled by jumping out of the |switch| statement
  101. to one of the routines following it. None of the cases say |break|, so
  102. the code following the switch statement is accessible only via |goto|.
  103. @<Special cases...@>=
  104. case 'a': case 'A':
  105. case 'b': case 'B':
  106. case 'c': case 'C':
  107. case 'd': case 'D':
  108. case 'e': case 'E':
  109. case 'f': case 'F':
  110. case 'g': case 'G':
  111. case 'h': case 'H':
  112. case 'i': case 'I':
  113. case 'j': case 'J':
  114. case 'k': case 'K':
  115. case 'l': case 'L':
  116. case 'm': case 'M':
  117. case 'n': case 'N':
  118. case 'o': case 'O':
  119. case 'p': case 'P':
  120. case 'q': case 'Q':
  121. case 'r': case 'R':
  122. case 's': case 'S':
  123. case 't': case 'T':
  124. case 'u': case 'U':
  125. case 'v': case 'V':
  126. case 'w': case 'W':
  127. case 'x': case 'X':
  128. case 'y': case 'Y':
  129. case 'z': case 'Z':
  130. goto out_word;
  131. @ When letters appear in |stdin|, we pass them immediately through to |stdout|
  132. with little further ado.
  133. An apostrophe is rejected unless it is immediately followed by a letter.
  134. @<Labeled code...@>=
  135. out_word: putchar(c);
  136. continue_word: c=getchar();
  137. checkout_word:
  138. if (isalpha(c)) goto out_word;
  139. if (c==''') {
  140.   c=getchar();
  141.   if (isalpha(c)) {
  142.     putchar(''');@+goto out_word;
  143.   }
  144.   goto end_word;
  145. }
  146. if (c=='\' && controlseq()) goto control_seq_in_word;
  147. end_word: putchar('n');
  148.   goto main_cycle;
  149. @* Control sequences.  The |controlseq()| function is the only
  150. delicate part of this program.  After a backslash has been scanned,
  151. |controlseq| looks to see if the next characters define one of the
  152. special plain TEX/ macros listed above. If so, the control sequence
  153. and its immediately following argument (if any) are output and
  154. |controlseq| returns a nonzero value. If not, nothing is output and
  155. |controlseq| returns zero. In both cases the value of |c| will be
  156. nonzero if and only if |controlseq| has had to look ahead at a
  157. character it decided not to process.
  158. @ @<Labeled code...@>=
  159. control_seq_in_word: if (!c) goto continue_word;
  160. goto checkout_word;
  161. @ @<Special cases...@>=
  162. case '\': if (controlseq()) goto control_seq_in_word;
  163. goto main_cycle;
  164. @ @<Procedures@>=
  165. int controlseq()
  166. {
  167.   int l; /* number of letters in the control sequence */
  168.   char a,b; /* the first two characters after `.\' */
  169.   l=0;
  170.   a=c=getchar();
  171.   while (isalpha(c)) {
  172.     l++;
  173.     c=getchar();
  174.     if (l==1) b=c;
  175.   }
  176.   if (l==0) c=getchar();
  177.   @<Check for special plain TEX/ control sequences;
  178.     output them and |return 1| if found@>;
  179.   return 0;
  180. }
  181. @ @d pair(x,y) (a==x && b==y)
  182. @<Check for special...@>=
  183. if ((a>='"' && a<='~' && ptab[a-'"']==l) ||
  184.  (l==2 && (pair('a','e') || pair('A','E')@|
  185.            || pair('o','e') || pair('O','E')@|
  186.            || pair('a','a') || pair('A','A') || pair('s','s')))) {
  187.   putchar('\');
  188.   putchar(a);
  189.   if (l==2) putchar(b);
  190.   if (l && c==' ') {
  191.     putchar(' '); /* optional space after alphabetic control sequence */
  192.     c=getchar();
  193.   }
  194.   if (c=='{') {
  195.     do@+{putchar(c);
  196.       c=get();
  197.     }@+while (c!='}'); /* optional argument after special control sequence */
  198.     putchar(c);
  199.     c=0;
  200.   }
  201.   return 1;
  202. }
  203. @ The |ptab| entries for nonletters are 0 when the control sequence is
  204. special, otherwise~1; the conventions for letters are reversed.
  205. @<Global...@>=
  206. char ptab[]={0,1,1,1,1,0, /* .{\"} and .{\'} */
  207.   1,1,1,1,1,1,0,1, /* .{\.} */
  208.   1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1, /* .{\=} */
  209.   1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1, /* .{\H}, .{\L}, .{\O} */
  210.   0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1, /* .{\^} */
  211.   0,0,1,1,1,0,0,0, /* .{\`}, .{\b}, .{\c}, .{\d} */
  212.   0,1,1,0,1,0,0,1, /* .{\i}, .{\j}, .{\l}, .{\o} */
  213.   0,0,0,0,1,1,1,0, /* .{\t}, .{\u}, .{\v} */
  214.   0,0,0,1,1,1,0}; /* .{\~} */
  215. @ In .{CWEB} the TEX/ control sequence `.{\.}' denotes the typewriter
  216. font used for strings, not the dot-over accent. We must modify
  217. |ptab| to reflect this unfortunate (but too-late-too-change) design decision.
  218. @<Adjust tables for .{CWEB} mode@>=
  219. ptab[12]=1;
  220. @* CWEB considerations.
  221. We're finished now with all that would be needed if we only wanted to
  222. handle TEX/. For .{CWEB} a bit more should be done.
  223. The .{CWEB} escape character is .{@@}, and the character following
  224. it tells us what mode we should enter. In TEX/ mode we should not
  225. only do what we normally do for TEX/ files, we should also ignore
  226. material delimited by .{char"7C...char"7C}, being careful to recognize when
  227. |'|'| is part of a string (as it just was). And we should stop TEX/
  228. mode if we scan .{*/} while in a CEE/ comment.
  229. @<Special cases...@>=
  230. case '@@': if (web) goto do_web;
  231.   goto restart;
  232. case '|': if (web>1) {
  233.      save_skipping=skipping;
  234.      goto skip_C_prime;
  235.    }
  236.    goto restart;
  237. case '*': if (!comment) goto restart;
  238.   c=getchar();
  239.   if (c=='/') {
  240.     comment=0;
  241.     goto skip_C;
  242.   }
  243.   goto big_switch;
  244. @ The characters that follow .@@ in a .{CWEB} file can be classified into
  245. a few types that have distinct implications for {tt excweb}.
  246. @d nop 0 /* control code that doesn't matter to us */
  247. @d start_section 1 /* control code that begins a .{CWEB} section */
  248. @d start_C 2 /* control code that begins CEE/ code */
  249. @d start_name 3 /* control code that begins a section name */
  250. @d start_index 4 /* control code for .{CWEB} index entry */
  251. @d start_insert 5 /* control code for CEE/ material ended by `.{@@>}' */
  252. @d end_item 6 /* `.{@@>}' */
  253. @d ignore_line 7 /* `.{@@i}' or `.{@@l}' */
  254. @<Global...@>=
  255. char wtab[]={start_section,nop,nop,nop,nop,nop,nop,nop, /* .{ !"#$%&'} */
  256.  start_name,nop,start_section,nop,nop,nop,start_index,nop, /* .{()*+,-./} */
  257.  nop,nop,nop,nop,nop,nop,nop,nop, /* .{01234567} */
  258.  nop,nop,start_index,nop,start_name,start_insert,end_item,nop,
  259.     /* .{89:;<=>?} */
  260.  nop,nop,nop,start_C,start_C,nop,start_C,nop, /* .{@@ABCDEFG} */
  261.  nop,ignore_line,nop,nop,ignore_line,nop,nop,nop, /* .{HIJKLMNO} */
  262.  start_C,start_insert,nop,start_C,start_insert,nop,nop,nop, /* .{PQRSTUVW} */
  263.  nop,nop,nop,nop,nop,nop,start_index,nop, /* .{XYZ[\]^_} */
  264.  nop,nop,nop,start_C,start_C,nop,start_C,nop, /* .{`abcdefg} */
  265.  nop,ignore_line,nop,nop,ignore_line,nop,nop,nop, /* .{hijklmno} */
  266.  start_C,start_insert,nop,start_C,start_insert}; /* .{pqrst} */
  267. @ We do not leave TEX/ mode until the first .{WEB} section has begun.
  268. @<Labeled code...@>=
  269. do_web: c=getchar();
  270.   if (c<' ' || c>'t') goto restart;
  271.   switch(wtab[c-' ']){
  272.  case nop: case start_index: goto restart;
  273.  case start_section: web++; /* out of ``limbo'' */
  274.   comment=skipping=0;@+goto restart;
  275.  case start_C: if (web>1) goto skip_C;
  276.   goto restart;
  277.  case start_name: case start_insert: if (web>1) skipping=1;
  278.   goto restart;
  279.  case end_item: if (skipping) goto skip_C;
  280.    goto restart;
  281.  case ignore_line: discard_to('n');
  282.    goto restart;
  283.   }
  284. @ The final piece of program we need is a sub-automaton to pass over
  285. the CEE/ parts of a .{CWEB} document. The main subtlety here is that
  286. we don't want to get out of synch while scanning over a supposed
  287. string constant or verbatim insert.
  288. @<Labeled code...@>=
  289. skip_C: save_skipping=2;
  290. skip_C_prime: skipping=1;
  291.   while (1) {
  292.     c=get();
  293.   C_switch: switch(c) {
  294.    case '/': c=get();
  295.      if (c!='*') goto C_switch;
  296.      comment=1; /* fall through to the next case, returning to TEX/ mode */
  297.    case '|': if (save_skipping==2) continue; /* |'|'| as CEE/ operator */
  298.      skipping=save_skipping;@+goto restart; /* |'|'| as .{CWEB} delimiter */
  299.    case '@@': c=getchar();
  300.     inner_switch: if (c<' ' || c>'t') continue;
  301.      switch(wtab[c-' ']) {
  302.     case nop: case start_C: case end_item: continue;
  303.     case start_section: web++;
  304.      comment=skipping=0;@+goto restart;
  305.     case start_name: case start_index: goto restart;
  306.     case start_insert: do@+discard_to('@@')@;@+while ((c=getchar())=='@@');
  307.       goto inner_switch; /* now |c| should equal |'>'| */
  308.     case ignore_line: discard_to('n');
  309.      continue;
  310.      }
  311.    case ''': case '"':    
  312.      while ((cc=get())!=c && cc!='n')
  313.        if (cc=='\') getchar();
  314.        else if (cc=='@@') {
  315.          cc=getchar();
  316.          if (cc!='@@') { /* syntax error, we try to recover */
  317.            c=cc; goto inner_switch;
  318.          }
  319.        };
  320.      continue; /* .{CWEB} strings do not extend past one line */
  321.     default: continue;
  322.     }
  323.   }
  324. @* Index.