home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / SPIDER / MASTER / WEAVE.WEB (.txt) < prev    next >
Encoding:
Texinfo Document  |  1990-02-08  |  114.5 KB  |  2,588 lines

  1. % Copyright 1989 by Norman Ramsey, Odyssey Research Associates
  2. % To be used for research purposes only
  3. % For more information, see file COPYRIGHT in the parent directory
  4. % This file is part of Spidery WEB
  5. % This program by Norman Ramsey is based on programs Silvio Levy
  6. % and D. E. Knuth.  Silvio Levy wrote most of the code.
  7. % It is distributed WITHOUT ANY WARRANTY, express or implied.
  8. % Dec 1987
  9. % Here is TeX material that gets inserted after \input webmac
  10. \message{Entering \string\batchmode...}
  11. \batchmode
  12. \def\hang{\hangindent 3em\indent\ignorespaces}
  13. \font\ninerm=cmr9
  14. \let\mc=\ninerm % medium caps
  15. \def\cee{C}
  16. \def\Pascal{Pascal}
  17. \def\PASCAL{Ada}
  18. \def\pb{$\.|\ldots\.|$} % C brackets (|...|)
  19. \def\v{\.{\char'174}} % vertical (|) in typewriter font
  20. \def\dleft{[\![} \def\dright{]\!]} % double brackets
  21. \mathchardef\RA="3221 % right arrow
  22. \mathchardef\BA="3224 % double arrow
  23. \def\({} % kludge for alphabetizing certain module names
  24. \def\title{Spidery WEAVE}
  25. \def\contentspagenumber{1} % should be odd
  26. \def\topofcontents{\null\vfill
  27.   \titlefalse % include headline on the contents page
  28.   \def\rheader{\hfil}
  29.   \centerline{\titlefont The {\ttitlefont Spidery WEAVE} processor}
  30.   \vfill}
  31. \pageno=\contentspagenumber \advance\pageno by 1
  32. \let\maybe=\iftrue
  33. @* Introduction.
  34. \.{CWEAVE} has a fairly straightforward outline.  It operates in
  35. three phases: first it inputs the source file and stores cross-reference
  36. data, then it inputs the source once again and produces the \TeX\ output
  37. file, and finally it sorts and outputs the index.  It can be compiled
  38. with certain optional flags, |DEBUG| and |STAT|, the latter being used
  39. to keep track of how much of \.{WEAVE}'s resources were actually used.
  40. @<Include files@>@;
  41. @<Common code for \.{WEAVE} and \.{TANGLE}@>@;
  42. @<Typedef declarations@>@;
  43. @<Global variables@>@;
  44. main (ac, av)
  45. char **av;
  46.   argc=ac; argv=av;
  47.   program=weave;
  48.   common_init();
  49.   @<Set initial values@>;
  50.   printf(banner); /* print a ``banner line'' */
  51.   @<Store all the reserved words@>;
  52.   phase_one(); /* read all the user's text and store the cross-references */
  53.   phase_two(); /* read all the text again and translate it to \TeX\ form */
  54.   phase_three(); /* output the cross-reference index */
  55. #ifdef STAT
  56.   @<Print statistics about memory usage@>;
  57. #endif STAT
  58.   wrap_up();
  59. @ The following parameters were sufficient in the original \.{WEAVE} to
  60. handle \TeX, so they should be sufficient for most applications of \.{CWEAVE}.
  61. @d max_bytes = 90000 /* the number of bytes in identifiers,
  62.   index entries, and module names */
  63. @d max_names = 4000 /* number of identifiers, strings, module names;
  64.   must be less than 10240 */
  65. @d max_modules = 2000 /* greater than the total number of modules */
  66. @d hash_size = 353 /* should be prime */
  67. @d buf_size = 100 /* maximum length of input line, plus one */
  68. @d longest_name = 400 /* module names and strings shouldn't be longer than this */
  69. @d long_buf_size = 500 /* |buf_size+longest_name| */
  70. @d line_length = 80 /* lines of \TeX\ output have at most this many characters;
  71.   should be less than 256 */
  72. @d max_refs = 20000 /* number of cross-references; must be less than 65536 */
  73. @d max_toks = 20000 /* number of symbols in \cee\ texts being parsed;
  74.   must be less than 65536 */
  75. @d max_texts = 2000 /* number of phrases in \cee\ texts being parsed;
  76.   must be less than 10240 */
  77. @d max_scraps = 1000 /* number of tokens in \cee\ texts being parsed */
  78. @d stack_size = 400 /* number of simultaneous output levels */
  79. @i common.h
  80. @ Should include wlang.web but can't because AWK runs out of files.
  81. @* Data structures exclusive to {\tt WEAVE}.
  82. As explained in \.{common.web}, the field of a |name_info| structure
  83. that contains the |rlink| of a module name is used for a completely
  84. different purpose in the case of identifiers.  If is then called the
  85. |ilk| of the identifier, and it is used to
  86. distinguish between various types of identifiers, as follows:
  87. @ Several types of identifiers are distinguished by their |ilk|:
  88. \yskip\hang |normal| identifiers are part of the \PASCAL\ program and
  89. will appear in italic type.
  90. \yskip\hang |roman| identifiers are index entries that appear after
  91. \.{@@\^} in the \.{WEB} file.
  92. \yskip\hang |wildcard| identifiers are index entries that appear after
  93. \.{@@:} in the \.{WEB} file.
  94. \yskip\hang |typewriter| identifiers are index entries that appear after
  95. \.{@@.} in the \.{WEB} file.
  96. \yskip\hang |array_like|, |begin_like|, \dots, |var_like|
  97. identifiers are \PASCAL\ reserved words whose |ilk| explains how they are
  98. to be treated when \PASCAL\ code is being formatted.
  99. \yskip\hang Finally, if |c| is an ASCII code, an |ilk| equal to
  100. |char_like+c| denotes a reserved word that will be converted to character
  101. @d normal = 0 /*ordinary identifiers have |normal| ilk */
  102. @d roman = 1 /*normal index entries have |roman| ilk */
  103. @d wildcard = 2 /*user-formatted index entries have |wildcard| ilk */
  104. @d typewriter = 3 /*`typewriter type' entries have |typewriter| ilk */
  105. @d reserved(a) = (a->ilk>typewriter) /* tells if a name is a reserved word */
  106. /* begin with 64 */
  107. /* ilks are generated by spider into file grammar.web */
  108. @ We keep track of the current module number in |module_count|, which
  109. is the total number of modules that have started.  Modules which have
  110. been altered by a change file entry have their |changed_module| flag
  111. turned on during the first phase.
  112. @<Global...@>=
  113. boolean change_exists; /* has any module changed? */
  114. @ The other large memory area in \.{CWEAVE} keeps the cross-reference data.
  115. All uses of the name |p| are recorded in a linked list beginning at
  116. |p->xref|, which points into the |xmem| array. The elements of |xmem|
  117. are structures consisting of an integer, |num|, and a pointer |xlink|
  118. to another element of |xmem|.  If |x=p->xref| is a pointer into |xmem|,
  119. the value of |x->num| is either a module number where |p| is used,
  120. or it is |def_flag| plus a module number where |p| is defined,
  121. or it is |file_flag| plus a module number where the file |p| is defined;
  122. and |x->xlink| points to the next such cross-reference for |p|,
  123. if any. This list of cross-references is in decreasing order by
  124. module number. The next unused slot in |xmem| is |xref_ptr|.
  125. The global variable |xref_switch| is set either to |def_flag|, or to zero, 
  126. depending on whether the next cross-reference to an identifier is to be
  127. underlined or not in the index. This switch is set to |def_flag| when
  128. \.{@@!} or \.{@@d} or \.{@@f} is scanned, and it is cleared to zero when
  129. the next identifier or index entry cross-reference has been made. 
  130. Similarly,
  131. the global variable |mod_xref_switch| is either |def_flag|, 
  132. |file_flag|, or zero, depending
  133. on whether a module name is being defined, defined as a file, or used.
  134. @<Type...@>=
  135. typedef struct xref_info {
  136.   sixteen_bits num; /* module number plus zero,|def_flag|, or |file_flag| */
  137.   struct xref_info *xlink; /* pointer to the previous cross-reference */
  138. } xref_info;
  139. typedef xref_info *xref_pointer;
  140. @ @<Global...@>=
  141. xref_info xmem[max_refs]; /* contains cross-reference information */
  142. xref_pointer xmem_end = xmem+max_refs-1;
  143. xref_pointer xref_ptr; /* the largest occupied position in |xmem| */
  144. sixteen_bits xref_switch,mod_xref_switch; /* either zero or |def_flag| */
  145. @ @d def_flag = 10240 /* must be strictly larger than |max_modules| */
  146. @d file_flag = 2*def_flag
  147. @d xref = equiv_or_xref
  148. @<Set init...@>=
  149. name_dir->xref=(ASCII *)xmem;
  150. xref_ptr=xmem; 
  151. xref_switch=0; 
  152. mod_xref_switch=0;
  153. xmem->num=0; /* cross-references to undefined modules */
  154. @ A new cross-reference for an identifier is formed by calling |new_xref|,
  155. which discards duplicate entries and ignores non-underlined references
  156. to one-letter identifiers or \cee's reserved words.
  157. If the user has sent the |no_xref| flag (the \.{-x} option of the command line),
  158. it is unnecessary to keep track of cross-references for identifers.
  159. If one were careful, one could probably make more changes around module
  160. 100 to avoid a lot of identifier looking up.
  161. @d append_xref(c) = if (xref_ptr==xmem_end) stat_overflow("cross-reference");
  162.   else (++xref_ptr)->num=c;
  163. @u new_xref(p)
  164. name_pointer p;
  165.   xref_pointer q; /* pointer to previous cross-reference */
  166.   sixteen_bits m, n; /* new and previous cross-reference value */
  167.   if (no_xref) return;
  168.   if ((reserved(p) || length(p)==1) && xref_switch==0) return;
  169.   m=module_count+xref_switch; xref_switch=0; q=(xref_pointer)p->xref;
  170.   if (q != xmem) {
  171.     n=q->num;
  172.     if (n==m || n==m+def_flag) return;
  173.     else if (m==n+def_flag) {
  174.  q->num=m; return;
  175.     }
  176.   append_xref(m); xref_ptr->xlink=q; p->xref=(ASCII *)xref_ptr;
  177. @ The cross-reference lists for module names are slightly different. Suppose
  178. that a module name is defined in modules $m_1$, \dots, $m_k$ and used in
  179. modules $n_1$, \dots, $n_l$. Then its list will contain $m_1+|def_flag|{}$,
  180. $m_k+|def_flag|{}$, \dots, $m_2+|def_flag|{}$, $n_l$, \dots, $n_1$, in
  181. this order.
  182. If the module is a file module (\.{@@(}), read |file_flag| for
  183. |def_flag|.
  184. Since no module should ever have both |file_flag| and |def_flag|, we
  185. check that.
  186.   After Phase II, however, the order will be
  187. $m_1+|def_flag|{}$, \dots, $m_k+|def_flag|{}$, $n_1$, \dots, $n_l$.
  188. @u new_mod_xref(p)
  189. name_pointer p;
  190.   xref_pointer q,r; /* pointers to previous cross-references */
  191.   q=(xref_pointer)p->xref; r=xmem;
  192.   if (q>xmem) {
  193.     if (mod_xref_switch==0) while (q->num>=def_flag) {
  194.       r=q; q=q->xlink;
  195.     }
  196.     else if (q->num>=def_flag) {
  197.       @<Make sure |mod_xref_switch| is consistent with |q->num|@>
  198.       r=q; q=q->xlink;
  199.     }
  200.   append_xref(module_count+mod_xref_switch);
  201.   xref_ptr->xlink=q; mod_xref_switch=0;
  202.   if (r==xmem) p->xref=(ASCII *)xref_ptr;
  203.   else r->xlink=xref_ptr;
  204. @ Consistency check
  205. @<Make sure |mod_xref_switch| is consistent with |q->num|@>=
  206.     if ((mod_xref_switch==def_flag && q->num >= file_flag) ||
  207.         (mod_xref_switch==file_flag && q->num < file_flag)) {
  208.       printf("\n! You can't use <"); print_id(p); 
  209.     printf("> both as a file and as a named module"); mark_harmless;
  210. @.You can't use <section name> both as a file...@>
  211. @ A third large area of memory is used for sixteen-bit `tokens', which appear
  212. in short lists similar to the strings of characters in |byte_mem|. Token lists
  213. are used to contain the result of \cee\ code translated into \TeX\ form;
  214. further details about them will be explained later. A |text_pointer| variable
  215. is an index into |tok_start|.
  216. @<Typed...@>=
  217. typedef sixteen_bits token;
  218. typedef token *token_pointer;
  219. typedef token_pointer *text_pointer;
  220. @ The first position of |tok_mem|
  221. that is unoccupied by replacement text is called |tok_ptr|, and the first
  222. unused location of |tok_start| is called |text_ptr|.
  223. Thus, we usually have |*text_ptr=tok_ptr|.
  224. @<Global...@>=
  225. token tok_mem[max_toks]; /* tokens */
  226. token_pointer tok_mem_end = tok_mem+max_toks-1; /* end of |tok_mem| */
  227. token_pointer tok_start[max_texts]; /* directory into |tok_mem| */
  228. token_pointer tok_ptr; /* first unused position in |tok_mem| */
  229. text_pointer text_ptr; /* first unused position in |tok_start| */
  230. text_pointer tok_start_end = tok_start+max_texts-1; /* end of |tok_start| */
  231. #ifdef STAT
  232. token_pointer max_tok_ptr; /* largest value of |tok_ptr| */
  233. text_pointer max_text_ptr; /* largest value of |text_ptr| */
  234. #endif STAT
  235. @ @<Set init...@>=
  236. tok_ptr=tok_mem+1; text_ptr=tok_start+1; tok_start[0]=tok_mem+1;
  237. tok_start[1]=tok_mem+1; /* |tok_start| is the empty token list,
  238.             and |*textptr==tok_mem+1==tok_ptr| */
  239. #ifdef STAT
  240. max_tok_ptr=tok_mem+1; max_text_ptr=tok_start+1;
  241. #endif STAT
  242. names_match(p,first,l,t)
  243. name_pointer p; /* points to the proposed match */
  244. ASCII *first; /* position of first character of string */
  245. int l; /* length of identifier */
  246. eight_bits t; /* desired ilk */
  247.   if (length(p)!=l) return 0;
  248.   if (p->ilk!=t && !(t==normal && reserved(p))) return 0;
  249.   return !strncmp(first,p->byte_start,l);
  250. init_p(p,t)
  251. name_pointer p;
  252. eight_bits t;
  253.   p->ilk=t; p->xref=(ASCII*)xmem;
  254. init_node(p)
  255. name_pointer p;
  256.   p->xref=(ASCII*)xmem;
  257. @ We have to get Ada's
  258. reserved words into the hash table, and the simplest way to do this is
  259. to insert them every time \.{CWEAVE} is run.  Since there are relatively
  260. few reserved words, we use an ad hoc function to simplify the code.
  261. @^reserved words@>
  262. There's not enough room to include \.{reserved.web}, since AWK can't open 
  263. enough files.
  264. We make do with \.{scraps.web}.
  265. @* Lexical scanning.
  266. Let us now consider the subroutines that read the \.{WEB} source file
  267. and break it into meaningful units. There are four such procedures:
  268. One simply skips to the next `\.{@@\ }' or `\.{@@*}' that begins a
  269. module; another passes over the \TeX\ text at the beginning of a
  270. module; the third passes over the \TeX\ text in a \cee\ comment;
  271. and the last, which is the most interesting, gets the next token of
  272. a \cee\ text.  They all use the pointers |limit| and |loc| into
  273. the line of input currently being studied.
  274. @ Control codes in \.{WEB}, which begin with `\.{@@}', are converted
  275. into a numeric code designed to simplify \.{CWEAVE}'s logic; for example,
  276. larger numbers are given to the control codes that denote more significant
  277. milestones, and the code of |new_module| should be the largest of
  278. all. Some of these numeric control codes take the place of ASCII
  279. control codes that will not otherwise appear in the output of the
  280. scanning routines.
  281. @^ASCII code@>
  282. @d ignore = 0 /* control code of no interest to \.{CWEAVE} */
  283. @d verbatim = @'2 /* extended ASCII alpha will not appear */
  284.          /* extended ASCII beta will not appear */
  285. @d begin_comment = @'10 /* ASCII tab mark will not appear */
  286. @d octal = @'14 /* ASCII carriage return will not appear */
  287. @d hex = @'15 /* ASCII form feed will not appear */
  288. @d switch_math_flag = @'175 /* this code will be intercepted without confusion */
  289. @d underline = @'176 /* this code will be intercepted without confusion */
  290. @d param = @'177 /* ASCII delete will not appear */
  291. /* identifier =200 or octal @'310 */
  292. @#/* following three must be conseccutive for indexing to work */
  293. @d xref_roman = (identifier+roman) /* control code for `\.{@@\^}' */
  294. @d xref_wildcard = (identifier+wildcard) /* control code for `\.{@@:}' */
  295. @d xref_typewriter = (identifier+typewriter) /* control code for `\.{@@.}' */
  296. @d TeX_string = @'356 /* control code for `\.{@@t}' */
  297. @d ascii_constant = @'357 /* control code for `\.{@@`}' */
  298. @d join = @'360 /* control code for `\.{@@\&}' */
  299. @d thin_space = @'361 /* control code for `\.{@@,}' */
  300. @d math_break = @'362 /* control code for `\.{@@\char'174}' */
  301. @d line_force = @'363 /* control code for `\.{@@/}' */
  302. @d line_break = @'364 /* control code for `\.{@@-}' */
  303. @d big_line_break = @'365 /* control code for `\.{@@\#}' */
  304. @d no_line_break = @'366 /* control code for `\.{@@+}' */
  305. @d pseudo_semi = @'367 /* control code for `\.{@@;}' */
  306. @d vertical_bar = @'370 /* The `\v' used to mark Ada text */
  307. @d trace = @'371 /* control code for `\.{@@0}', `\.{@@1}' and `\.{@@2}' */
  308. @d format = @'373 /* control code for `\.{@@f}' */
  309. @d definition = @'374 /* control code for `\.{@@d}' */
  310. @d begin_unnamed = @'375 /* control code for `\.{@@u}' */
  311. @d module_name = @'376 /* control code for `\.{@@<}' */
  312. @d new_module = @'377 /* control code for `\.{@@\ }' and `\.{@@*}' */
  313. @ Control codes are converted from ASCII to \.{CWEAVE}'s internal
  314. representation by means of the table |ccode|.
  315. @<Global...@>=
  316. eight_bits ccode[128]; /* meaning of a char following \.{@@} */
  317. @ @<Set ini...@>=
  318. {int c; for (c=0; c<=127; c++) ccode[c]=0;}
  319. ccode[' ']=ccode[tab_mark]=ccode['*']=new_module;
  320. ccode['-']=line_break;
  321. ccode['#']=big_line_break;
  322. ccode['=']=verbatim; 
  323. ccode['d']=ccode['D']=definition; 
  324. ccode['f']=ccode['F']=format;
  325. ccode['c']=ccode['C']=begin_unnamed; 
  326. ccode['u']=ccode['U']=begin_unnamed; 
  327. ccode['t']=ccode['T']=TeX_string;
  328. ccode['&']=join; 
  329. ccode['<']=ccode['(']=module_name;
  330. ccode['!']=underline; ccode['^']=xref_roman;
  331. ccode['$']=switch_math_flag;
  332. ccode[':']=xref_wildcard; 
  333. ccode['.']=xref_typewriter; 
  334. ccode[',']=thin_space;
  335. ccode['|']=math_break; 
  336. ccode['/']=line_force;
  337. ccode['+']=no_line_break; 
  338. ccode[';']=pseudo_semi;
  339. ccode['`']=ascii_constant;
  340. ccode['\'']=octal;
  341. ccode['"']=hex;
  342. @t\4@>@<Special control codes allowed only when debugging@>@;
  343. /*Now adjust for |at_sign|... if it is @@, we have no-op followed by quoting */
  344. /* ... but if it is other, say \#, then \#@@ replaces @@\#, and \#\# 
  345.     quotes itself*/
  346. ccode['@@']=ccode[at_sign];
  347. ccode[at_sign]=at_sign;
  348. @ If \.{CWEAVE} is compiled with debugging commands, one can write
  349. \.{@@2}, \.{@@1}, and \.{@@0} to turn tracing fully on, partly on,
  350. and off, respectively.
  351. @<Special control codes...@>=
  352. #ifdef DEBUG
  353. ccode['0']=ccode['1']=ccode['2']=trace;
  354. #endif DEBUG
  355. @ The |skip_limbo| routine is used on the first pass to skip through
  356. portions of the input that are not in any modules, i.e., that precede
  357. the first module. After this procedure has been called, the value of
  358. |input_has_ended| will tell whether or not a module has actually been found.
  359. @u skip_limbo() {
  360.   while(1) {
  361.     if (loc>limit && get_line()==0) return;
  362.     *(limit+1)=at_sign;
  363.     while (*loc!=at_sign) loc++; /* look for |at_sign|, then skip two chars */
  364.     if (loc++ <=limit) if (ccode[*loc++]==new_module) return;
  365. @ The |skip_TeX| routine is used on the first pass to skip through
  366. the \TeX\ code at the beginning of a module. It returns the next
  367. control code or `\v' found in the input. A |new_module| is
  368. assumed to exist at the very end of the file.
  369. @u unsigned skip_TeX() /* skip past pure \TeX\ code */
  370.   while (1) {
  371.     if (loc>limit && get_line()==0) return(new_module);
  372.     *(limit+1)=at_sign;
  373.     while (*loc!=at_sign && *loc!=vertical_char) loc++;
  374.     if (*loc++ ==vertical_char) return(vertical_bar);
  375.     if (loc<=limit) return(ccode[*(loc++)]);
  376. @* Inputting the next token.
  377. As stated above, \.{WEAVE}'s most interesting lexical scanning routine is the
  378. |get_next| function that inputs the next token of \cee\ input. However,
  379. |get_next| is not especially complicated.
  380. The result of |get_next| is either an ASCII code for some special character,
  381. or it is a special code representing a pair of characters (e.g., `\.{!=}'),
  382. or it is the numeric value computed by the |ccode|
  383. table, or it is one of the following special codes:
  384. \yskip\hang |identifier|: In this case the global variables |id_first| and
  385. |id_loc| will have been set to the beginning and ending-plus-one locations
  386. in the buffer, as required by the |id_lookup| routine.
  387. \yskip\hang |string|: The string will have been copied into the array
  388. |mod_text|; |id_first| and |id_loc| are set as above (now they are
  389. pointers into |mod_text|).
  390. \yskip\hang |constant|: The constant is copied into |mod_text|, with
  391. slight modifications; |id_first| and |id_loc| are set.
  392. \yskip\noindent Furthermore, some of the control codes cause
  393. |get_next| to take additional actions:
  394. \yskip\hang |xref_roman|, |xref_wildcard|, |xref_typewriter|, |TeX_string|,
  395. |verbatim|: The values of |id_first| and |id_loc| will have been set to
  396. the beginning and ending-plus-one locations in the buffer.
  397. \yskip\hang |module_name|: In this case the global variable |cur_module| will
  398. point to the |byte_start| entry for the module name that has just been scanned.
  399. \yskip\noindent If |get_next| sees `\.{@@!}'
  400. it sets |xref_switch| to |def_flag| and goes on to the next token.
  401. \yskip\noindent If |get_next| sees `\.{@@\$}'
  402. it sets |math_flag| to |!math_flag| and goes on to the next token.
  403. @<Global...@>=
  404. name_pointer cur_module; /* name of module just scanned */
  405. int math_flag;
  406. @ @<Include...@>=
  407. #include "ctype.h"
  408. @ As one might expect, |get_next| consists mostly of a big switch
  409. that branches to the various special cases that can arise.
  410. Get next takes one argument that determines whether |vertical_char| is a
  411. character or gets translated to a |vertical_bar|.
  412. (Normally, |vertical_char=='|'|.)
  413. If it does get translated, the following rules apply:
  414. \yskip\hang|'|'| as part of a string or as a noninitial character in a
  415. multicharacter token is not a |vertical_bar|.
  416. \yskip\hang An initial |"||"| is treated like a single |'|'|, and
  417. taken to be either a token itself or the initial |'|'| in a
  418. multicharacter token.
  419. @d vertical_char = @`|'
  420. @u eight_bits get_next(see_vertical) /* produces the next input token
  421.     char see_vertical;
  422.   eight_bits c; /* the current character */
  423.   while (1) {
  424.     if (loc>limit) {
  425.         if (get_line()==0) return(new_module);
  426.         else { return (@`\n'); }
  427.         }
  428.     c=*(loc++);
  429.     @<See a comment starting at |loc-1| and return |begin_comment|@>@;
  430.     if (see_vertical && c==vertical_char) { 
  431.     if (*loc==vertical_char && loc < limit) {
  432.         loc++;
  433.     } else {
  434.         return vertical_bar;
  435.     }
  436.     if (isdigit(c)) @<Get a constant@>@; /*spider*/
  437.     else if (isalpha(c) || c=='_') @<Get an identifier@>@;/*spider*/
  438.     else if (c=='\'' || c=='"') @<Get a string@>@;/*spider*/
  439.     else if (c==at_sign) @<Get control code and possible module name@>@;
  440.     else if (c==' ' || c==tab_mark) continue; /* ignore spaces and tabs */
  441.     mistake: @<Compress two-symbol operator@>@;
  442.     return(c);
  443. @ @<Set |next_control| to the first non-newline token@>=
  444. while ((next_control=get_next(0))==@`\n');
  445. @ @<Get an identifier@>= {/*spider*/
  446.   id_first=--loc;
  447.   while (isalpha(*++loc) || isdigit(*loc) || *loc=='_');
  448.   id_loc=loc; return(identifier);
  449. @ Notice that in this section and the next, |id_first| and |id_loc|
  450. are pointers into the array |mod_text|, not into |buffer|.
  451. @<Get a constant@>= {
  452.   id_first=id_loc=mod_text+1;
  453.   if (*(loc-1)=='.' && !isdigit(*loc)) goto mistake; /* not a constant */
  454.   *id_loc++=*(loc-1);
  455.     while (isdigit(*loc)) *id_loc++=*loc++;
  456.     if (*loc=='.') {
  457.     *id_loc++=*loc++;
  458.     while (isdigit(*loc)) *id_loc++=*loc++;
  459. #ifdef C_FLOATING_POINT
  460. /* no floating point --- it depends too much on C */
  461.     if (*loc=='e' || *loc=='E') { /* float constant */
  462.       *id_loc++='_'; loc++;
  463.       if (*loc=='+' || *loc=='-') *id_loc++=*loc++;
  464.       while (isdigit(*loc)) *id_loc++=*loc++;
  465.     }
  466. #endif C_FLOATING_POINT
  467.   return(constant);
  468. @ Here we do octals, which I should say more about later...
  469. @<Get an octal constant@>= {
  470.   id_first=id_loc=mod_text+1;
  471.   *id_loc++='~'; /* marks octal constant */
  472.   while ('0'<=*loc && *loc<'8') *id_loc++=*loc++;
  473.   return(constant);
  474. @ And hexes are even easier...
  475. @<Get a hex constant@>= {
  476.   id_first=id_loc=mod_text+1;
  477.   *id_loc++='^'; /* marks hex constant */
  478.   while (isxdigit(*loc)) {
  479.     *id_loc++=(islower(*loc)?toupper(*loc):*loc);
  480.     loc++;
  481.   return(constant);
  482. @ \cee\ strings and character constants, delimited by double and single
  483. quotes, respectively, can contain newlines or instances of their own
  484. delimiters if they are protected by a backslash.  We follow this
  485. convention, but do not allow the string to be longer than |longest_name|.
  486. @<Get a string@>= {/*spider*/
  487.   ASCII delim = c; /* what started the string */
  488.   id_first = mod_text+1;
  489.   id_loc = mod_text;
  490.   if (delim=='`' && *(loc-2)==at_sign) {
  491.     /* make string begin with |"@@`"| */
  492.     *++id_loc=at_sign; 
  493.     *++id_loc=at_sign;
  494.     /* this is hack for ascii constant */
  495. /* if it's not a single-character literal, it's a tick mark or an |at_sign| */
  496.   if ((delim=='\'' || delim == '`') && 
  497.         (loc+1>=limit || 
  498.             (*loc != '\\' && *loc!=at_sign && loc[1]!='\'')    || 
  499.             (*loc=='\\' && (loc+2>=limit||loc[2]!='\'')) ||
  500.             (*loc==at_sign && 
  501.                 (loc+2>=limit||loc[1]!=at_sign||loc[2]!='\''))
  502.       ) goto mistake;
  503.   *++id_loc=delim;
  504.   if (delim=='`') delim='\''; /* for |ascii_constant|s */
  505.   while (1) {
  506.     if (loc>=limit) {
  507.       if(*(limit-1)!='\\') {
  508.         err_print("! String didn't end"); loc=limit; break;
  509. @.String didn't end@>
  510.       }
  511.       if(get_line()==0) {
  512.         err_print("! Input ended in middle of string"); loc=buffer; break;
  513. @.Input ended in middle of string@>
  514.       }
  515.     }
  516.     if ((c=*loc++)==delim) {
  517.       if (++id_loc<=mod_text_end) *id_loc=c;
  518.       break;
  519.     }
  520.     if (c=='\\') if (loc>=limit) continue;
  521.       else if (++id_loc<=mod_text_end) {
  522.         *id_loc = '\\'; c=*loc++;
  523.       }
  524.     if (++id_loc<=mod_text_end) *id_loc=c;
  525.   if (id_loc>=mod_text_end) {
  526.     printf("\n! String too long: ");
  527. @.String too long@>
  528.     ASCII_write(mod_text+1,25);
  529.     printf("..."); mark_error;
  530.   id_loc++;
  531.   return(string);
  532. @ After an \.{@@} sign has been scanned, the next character tells us
  533. whether there is more work to do.
  534. @<Get control code and possible module name@>= {
  535.   c=*loc++;
  536.   switch(ccode[c]) {
  537.     case underline: xref_switch=def_flag; continue;
  538.     case switch_math_flag: math_flag=!math_flag; continue;
  539. #ifdef DEBUG
  540.     case trace: tracing=c-'0'; continue;
  541. #endif DEBUG
  542.     case xref_roman: case xref_wildcard: case xref_typewriter:
  543.     case TeX_string: 
  544.     @<Scan to the next \.{@@>}@>@;
  545.     case module_name: 
  546.     @<Scan the module name and make |cur_module| point to it@>@;
  547.     case verbatim: @<Scan a verbatim string@>@;
  548.     case ascii_constant: /* fake into looking like quoted char */
  549.         @<Get a string@>;
  550.     case octal: @<Get an octal constant@>;
  551.     case hex: @<Get a hex constant@>;
  552.     default: return(ccode[c]);
  553. @ The occurrence of a module name sets |xref_switch| to zero,
  554. because the module name might (for example) follow \&{int}.
  555. @<Scan the module name...@>= {
  556.   ASCII *k; /* pointer into |mod_text| */
  557.   cur_module_char=c; /* remember |'<'| or |'('| */
  558.   @<Put module name into |mod_text|@>;
  559.   if (k-mod_text>3 && strncmp(k-2,"...",3)==0) cur_module=prefix_lookup(mod_text+1,k-3);
  560.   else cur_module=mod_lookup(mod_text+1,k);
  561.   xref_switch=0; return(module_name);
  562. @ @<Global...@>=ASCII cur_module_char;
  563. @ Module names are placed into the |mod_text| array with consecutive spaces,
  564. tabs, and carriage-returns replaced by single spaces. There will be no
  565. spaces at the beginning or the end. (We set |mod_text[0]=' '| to facilitate
  566. this, since the |mod_lookup| routine uses |mod_text[1]| as the first
  567. character of the name.)
  568. @<Set init...@>=mod_text[0]=' ';
  569. @ @<Put module name...@>=
  570. k=mod_text;
  571. while (1) {
  572.   if (loc>limit && get_line()==0) {
  573.     err_print("! Input ended in section name");
  574. @.Input ended in section name@>
  575.     loc=buffer+1; break;
  576.   c=*loc;
  577.   @<If end of name, |break|@>;
  578.   loc++; if (k<mod_text_end) k++;
  579.   if (c==' ' || c==tab_mark) {
  580.     c=' '; if (*(k-1)==' ') k--;
  581. *k=c;
  582. if (k>=mod_text_end) {
  583.   printf("\n! Section name too long: ");
  584. @.Section name too long@>
  585.   ASCII_write(mod_text+1,25);
  586.   printf("..."); mark_harmless;
  587. if (*k==' ' && k>mod_text) k--;
  588. @ @<If end of name,...@>=
  589. if (c==at_sign) {
  590.   c=*(loc+1);
  591.   if (c=='>') {
  592.     loc+=2; break;
  593.   if (ccode[c]==new_module) {
  594.     err_print("! Section name didn't end"); break;
  595. @.Section name didn't end@>
  596.   *(++k)=at_sign; loc++; /* now |c==*loc| again */
  597. @ @<Scan to the next...@>= {
  598.   c=ccode[*(loc-1)]; id_first=loc; *(limit+1)=at_sign;
  599.   while (*loc!=at_sign) loc++;
  600.   id_loc=loc;
  601.   if (loc++>limit) {
  602.     err_print("! Control text didn't end"); loc=limit; return(c);
  603. @.Control text didn't end@>
  604.   if (*loc++!='>') err_print("! Control codes are forbidden in control text");
  605. @.Control codes are forbidden...@>
  606.   return(c);
  607. @ At the present point in the program we
  608. have |*(loc-1)=verbatim|; we set |id_first| to the beginning
  609. of the string itself, and |id_loc| to its ending-plus-one location in the
  610. buffer.  We also set |loc| to the position just after the ending delimiter.
  611. @<Scan a verbatim string@>= {
  612.   id_first=loc++; *(limit+1)=at_sign; *(limit+2)='>';
  613.   while (*loc!=at_sign || *(loc+1)!='>') loc++;
  614.   if (loc>=limit) err_print("! Verbatim string didn't end");
  615. @.Verbatim string didn't end@>
  616.   id_loc=loc; loc+=2;
  617.   return (verbatim);
  618. @* Phase one processing.
  619. We now have accumulated enough subroutines to make it possible to carry out
  620. \.{WEAVE}'s first pass over the source file. If everything works right,
  621. both phase one and phase two of \.{WEAVE} will assign the same numbers to
  622. modules, and these numbers will agree with what \.{TANGLE} does.
  623. The global variable |next_control| often contains the most recent output of
  624. |get_next|; in interesting cases, this will be the control code that
  625. ended a module or part of a module.
  626. @<Global...@>=
  627. eight_bits next_control; /* control code waiting to be acting upon */
  628. @ The overall processing strategy in phase one has the following
  629. straightforward outline.
  630. @u phase_one() {
  631. phase=1; reset_input(); module_count=0;
  632. skip_limbo(); change_exists=0;
  633. while (!input_has_ended)
  634.   @<Store cross-reference data for the current module@>;
  635. changed_module[module_count]=change_exists;
  636.   /* the index changes if anything does */
  637. phase=2; /* prepare for second phase */
  638. @<Print error messages about unused or undefined module names@>;
  639. @ @<Store cross-reference data...@>=
  640.   if (++module_count==max_modules) stat_overflow("section number");
  641.   changed_module[module_count]=0; /* it will become 1 if any line changes */
  642.   if (*(loc-1)=='*') {
  643.     printf("*%d",module_count);
  644.     update_terminal; /* print a progress report */
  645.   @<Store cross-references in the \TeX\ part of a module@>;
  646.   @<Store cross-references in the definition part of a module@>;
  647.   @<Store cross-references in the \cee\ part of a module@>;
  648.   if (changed_module[module_count]) change_exists=1;
  649. @ The |C_xref| subroutine stores references to identifiers in
  650. \cee\ text material beginning with the current value of |next_control|
  651. and continuing until |next_control| is `\.\{' or `\v', or until the next
  652. ``milestone'' is passed (i.e., |next_control>=format|). If
  653. |next_control>=format| when |C_xref| is called, nothing will happen;
  654. but if |next_control="|"| upon entry, the procedure assumes that this is
  655. the `\v' preceding \cee\ text that is to be processed.
  656. The program uses the fact that our internal code numbers satisfy
  657. the relations |xref_roman=identifier+roman| and |xref_wildcard=identifier
  658. +wildcard| and |xref_typewriter=identifier+typewriter| and |normal=0|.
  659. @u C_xref(see_v) /* makes cross-references for \cee\ identifiers */
  660.     char see_v;
  661.   name_pointer p; /* a referenced name */
  662.   while (next_control<format) {
  663.     if (next_control>=identifier && next_control<=xref_typewriter) {
  664.       p=id_lookup(id_first, id_loc,next_control-identifier); new_xref(p);
  665.     }
  666.     next_control=get_next(see_v);
  667.     if (next_control==vertical_bar || next_control==begin_comment) return;
  668. @ The |outer_xref| subroutine is like |C_xref| but it begins
  669. with |next_control!=vertical_bar| and ends with |next_control>=format|. Thus, it
  670. handles \cee\ text with embedded comments.
  671. @u outer_xref() /* extension of |C_xref| */
  672.   int bal; /* brace level in comment */
  673.   while (next_control<format)
  674.     if (next_control!=begin_comment) C_xref(0);
  675.     else {
  676.       bal=copy_comment(1); next_control=vertical_bar;
  677.       while (bal>0) {
  678.  C_xref(1);
  679.  if (next_control==vertical_bar) bal=copy_comment(bal);
  680.  else bal=0; /* an error message will occur in phase two */
  681.       }
  682.     }
  683. @ In the \TeX\ part of a module, cross-reference entries are made only for
  684. the identifiers in \cee\ texts enclosed in \pb, or for control texts
  685. enclosed in \.{@@\^}$\,\ldots\,$\.{@@>} or \.{@@.}$\,\ldots\,$\.{@@>}
  686. or \.{@@:}$\,\ldots\,$\.{@@>}.
  687. @<Store cross-references in the \T...@>=
  688. while (1) {
  689.   switch (next_control=skip_TeX()) {
  690.     case underline: xref_switch=def_flag; continue;
  691. #ifdef DEBUG
  692.     case trace: tracing=next_control-'0'; continue;
  693. #endif DEBUG
  694.     case vertical_bar: C_xref(1); break;
  695.     case xref_roman: case xref_wildcard: 
  696.     case xref_typewriter: case module_name:
  697.       loc-=2; next_control=get_next(1); /* scan to \.{@@>} */
  698.       if (next_control!=module_name) {
  699. /* |printf ("\nweave debugging: new xref: ");| */
  700. /* |{char *p; for (p=id_first;p<id_loc;p++) putchar(*p);}| */
  701. /* |putchar('\n');|
  702.         new_xref(id_lookup(id_first, id_loc,next_control-identifier));
  703.       break;
  704.   if (next_control>=format) break;
  705. @ During the definition and \cee\ parts of a module, cross-references
  706. are made for all identifiers except reserved words; however, the
  707. identifiers in a format definition are referenced even if they are
  708. reserved. The \TeX\ code in comments is, of course, ignored, except for
  709. \cee\ portions enclosed in \pb; the text of a module name is skipped
  710. entirely, even if it contains \pb\ constructions.
  711. The variables |lhs| and |rhs| point to the respective identifiers involved
  712. in a format definition.
  713. @<Global...@>=
  714. name_pointer lhs, rhs; /* pointers to |byte_start| for format identifiers */
  715. @ When we get to the following code we have |next_control>=format|.
  716. @<Store cross-references in the d...@>=
  717. while (next_control<=definition) { /* |format| or |definition| */
  718.   xref_switch=def_flag; /* implied \.{@@!} */
  719.   if (next_control==definition) next_control=get_next(1);
  720.   else @<Process a format definition@>;
  721.   outer_xref();
  722. @ Error messages for improper format definitions will be issued in phase
  723. two. Our job in phase one is to define the |ilk| of a properly formatted
  724. identifier, and to fool the |new_xref| routine into thinking that the
  725. identifier on the right-hand side of the format definition is not a
  726. reserved word.
  727. @<Process a form...@>= {
  728.   next_control=get_next(1);
  729.   if (next_control==identifier) {
  730.     lhs=id_lookup(id_first, id_loc,normal); lhs->ilk=normal; new_xref(lhs);
  731.     next_control=get_next(1);
  732.     if (next_control==identifier) {
  733.       rhs=id_lookup(id_first, id_loc,normal);
  734.       lhs->ilk=rhs->ilk; rhs->ilk=normal; new_xref(rhs);
  735.       rhs->ilk=lhs->ilk; next_control=get_next(1);
  736.     }
  737. @ Finally, when the \TeX\ and definition parts have been treated, we have
  738. |next_control>=begin_unnamed|.
  739. @<Store cross-references in the \cee...@>=
  740. if (next_control<=module_name) {  /* |begin_unnamed| or |module_name| */
  741.   if (next_control==begin_unnamed) mod_xref_switch=0;
  742.   else mod_xref_switch=(cur_module_char=='<' ? def_flag: file_flag);
  743.   do {
  744.     if (next_control==module_name && cur_module!=NULL) new_mod_xref(cur_module);
  745.     next_control=get_next(1); outer_xref();
  746.   } while ( next_control<=module_name);
  747. @ After phase one has looked at everything, we want to check that each
  748. module name was both defined and used.  The variable |cur_xref| will point
  749. to cross-references for the current module name of interest.
  750. @<Global...@>=
  751. xref_pointer cur_xref; /* temporary cross-reference pointer */
  752. @ The following recursive procedure
  753. walks through the tree of module names and prints out anomalies.
  754. @^recursion@>
  755. @u mod_check(p) name_pointer p; /* print anomalies in subtree |p| */
  756.   int level; /* 0: use 1: definition 2: file definition */
  757.   if (p) {
  758.     mod_check(p->llink);
  759.     cur_xref=(xref_pointer)p->xref;
  760.     level=(cur_xref->num)/def_flag;
  761.     if (level==0) {
  762.       printf("\n! Never defined: <"); print_id(p); putchar('>'); mark_harmless;
  763. @.Never defined: <section name>@>
  764.     }
  765.     while (cur_xref->num >=def_flag) {
  766.     if ((cur_xref->num)/def_flag != level) {
  767.           printf("\n! You can't use <"); print_id(p); 
  768.           printf("> both as a file and as a named module"); mark_harmless;
  769. @.You can't use <section name> both as a file...@>
  770.     cur_xref=cur_xref->xlink;
  771.     }
  772.     if (cur_xref==xmem && level<2) {
  773.       printf("\n! Never used: <"); print_id(p); putchar('>'); mark_harmless;
  774. @.Never used: <section name>@>
  775.     }
  776.     else if (cur_xref!=xmem && level==2) {
  777.       printf("\n! You can't use file module ("); print_id(p);
  778.     putchar(')'); mark_harmless; 
  779. @.You can't use file module (file name)@>
  780.     }
  781.     mod_check(p->rlink);
  782. @ @<Print error messages about un...@>=mod_check(root)
  783. @* Low-level output routines.
  784. The \TeX\ output is supposed to appear in lines at most |line_length|
  785. characters long, so we place it into an output buffer. During the output
  786. process, |out_line| will hold the current line number of the line about to
  787. be output.
  788. @<Global...@>=
  789. ASCII out_buf[line_length+1]; /* assembled characters */
  790. ASCII *out_ptr; /* just after last character in |out_buf| */
  791. ASCII *out_buf_end = out_buf+line_length; /* end of |out_buf| */
  792. int out_line; /* number of next line to be output */
  793. @ The |flush_buffer| routine empties the buffer up to a given breakpoint,
  794. and moves any remaining characters to the beginning of the next line.
  795. If the |per_cent| parameter is 1 a |'%'| is appended to the line
  796. that is being output; in this case the breakpoint |b| should be strictly
  797. less than |out_buf_end|. If the |per_cent| parameter is |0|,
  798. trailing blanks are suppressed.
  799. The characters emptied from the buffer form a new line of output.
  800. The same caveat that applies to |ASCII_write| applies to |c_line_write|.
  801. @d c_line_write(c) = fflush(tex_file),write(fileno(tex_file),out_buf+1,c)@;
  802. @d tex_putxchar(c) = putc(xchr[c],tex_file)@;
  803. @d tex_new_line = putc('\n',tex_file)@;
  804. @d tex_printf(c) = fprintf(tex_file,c)@;
  805. @u flush_buffer(b,per_cent)
  806. ASCII *b;
  807. boolean per_cent; /* outputs from |out_buf+1| to |b|,where |b<=out_ptr| */
  808.   ASCII *j; j=b; /* pointer into |out_buffer| */
  809.   if (! per_cent) /* remove trailing blanks */
  810.     while (j>out_buf && *j==' ') j--;
  811.   c_line_write(j-out_buf);
  812.   if (per_cent) tex_putxchar('%');
  813.   tex_new_line; out_line++;
  814.   if (b<out_ptr) strncpy(out_buf+1,b+1,out_ptr-b);
  815.   out_ptr-=b-out_buf;
  816. @ When we are copying \TeX\ source material, we retain line breaks
  817. that occur in the input, except that an empty line is not
  818. output when the \TeX\ source line was nonempty. For example, a line
  819. of the \TeX\ file that contains only an index cross-reference entry
  820. will not be copied. The |finish_line| routine is called just before
  821. |get_line| inputs a new line, and just after a line break token has
  822. been emitted during the output of translated \cee\ text.
  823. @u finish_line() /* do this at the end of a line */
  824.   ASCII *k; /* pointer into |buffer| */
  825.   if (out_ptr>out_buf) flush_buffer(out_ptr,0);
  826.   else {
  827.     for (k=buffer; k<=limit; k++)
  828.       if (*k!=' ' && *k!=tab_mark) return;
  829.     flush_buffer(out_buf,0);
  830. @ In particular, the |finish_line| procedure is called near the very
  831. beginning of phase two. We initialize the output variables in a slightly
  832. tricky way so that the first line of the output file will be a command
  833. to read in the macro file.
  834. @<Set init...@>=
  835. out_ptr=out_buf+1; out_line=1; 
  836. @<Set |out_ptr| and do a |tex_printf| to read the macros@> 
  837. @ When we wish to append one character |c| to the output buffer, we write
  838. `|out(c)|'; this will cause the buffer to be emptied if it was already
  839. full.  If we want to append more than one character at once, we say
  840. |out_str(s)|, where |s| is a string containing the characters,
  841. or |out_str_del(s,t)|, where |s| and |t| point to the same array of
  842. characters; characters from |s| to |t-1|, inclusive, are output.
  843. A line break will occur at a space or after a single-nonletter
  844. \TeX\ control sequence.
  845. @d out(c) = {if (out_ptr>=out_buf_end) break_out(); *(++out_ptr)=c;}
  846. @u out_str_del(s,t) /* output characters from |s| to |t-1| */
  847. ASCII *s, *t;
  848.   while (s<t) out(*s++);
  849. out_str(s) /* output characters from |s| to end of string */
  850. ASCII *s;
  851.   while (*s) out(*s++);
  852. @ The |break_out| routine is called just before the output buffer is about
  853. to overflow. To make this routine a little faster, we initialize position
  854. 0 of the output buffer to `\.\\'; this character isn't really output.
  855. @<Set init...@>=
  856. out_buf[0]='\\';
  857. @ A long line is broken at a blank space or just before a backslash that isn't
  858. preceded by another backslash. In the latter case, a |'%'| is output at
  859. the break.
  860. @u break_out() /* finds a way to break the output line */
  861.   ASCII *k=out_ptr; /* pointer into |out_buf| */
  862.   while (1) {
  863.     if (k==out_buf) @<Print warning message, break the line, |return|@>;
  864.     if (*k==' ') {
  865.       flush_buffer(k,0); return;
  866.     }
  867.     if (*(k--)=='\\' && *k!='\\') { /* we've decreased |k| */
  868.       flush_buffer(k,1); return;
  869.     }
  870. @ We get to this module only in unusual cases that the entire output line
  871. consists of a string of backslashes followed by a string of nonblank
  872. non-backslashes. In such cases it is almost always safe to break the
  873. line by putting a |'%'| just before the last character.
  874. @<Print warning message...@>=
  875.   printf("\n! Line had to be broken (output l. %d):\n",out_line);
  876. @.Line had to be broken@>
  877.   ASCII_write(out_buf+1, out_ptr-out_buf-1);
  878.   new_line; mark_harmless;
  879.   flush_buffer(out_ptr-1,1); return;
  880. @ Here is a macro that outputs a module number in decimal notation.
  881. The number to be converted by |out_mod| is known to be less than
  882. |def_flag|, so it cannot have more than five decimal digits.  If
  883. the module is changed, we output `\.{\\*}' just after the number.
  884. @u out_mod(n) sixteen_bits n;
  885.   ASCII s[6];
  886.   sprintf(s,"%d",n); out_str(s);
  887.   if(changed_module[n]) out_str ("\\*");
  888. @ The |out_name| procedure is used to output an identifier or index
  889. entry, enclosing it in braces.
  890. @u out_name(p) name_pointer p; {
  891.   ASCII *k, *k_end=(p+1)->byte_start; /* pointers into |byte_mem| */
  892.   out('{');
  893.   for (k=p->byte_start; k<k_end; k++) {
  894.     if (*k=='$') {out('\\'); out('D'); out('O'); out(' ');}
  895.     else if (*k=='&') {out('\\'); out('a'); out('m'); out('p');}
  896.     else {
  897.   if (*k=='_' || *k=='%' || *k=='#' || *k=='^' || *k=='{' || *k=='}') 
  898.         out('\\');
  899.       out(*k);
  900.   out('}');
  901. @* Routines that copy \TeX\ material.
  902. During phase two, we use the subroutines |copy_limbo|, |copy_TeX|, and
  903. |copy_comment| in place of the analogous |skip_limbo|, |skip_TeX|, and
  904. |skip_comment| that were used in phase one.
  905. The |copy_limbo| routine, for example, takes \TeX\ material that is not
  906. part of any module and transcribes it almost verbatim to the output file.
  907. No `\.{@@}' signs should occur in such material except in `\.{@@@@}'
  908. pairs; such pairs are replaced by singletons.
  909. @u copy_limbo()
  910.   ASCII c;
  911.   while (1) {
  912.     if (loc>limit && (finish_line(), get_line()==0)) return;
  913.     *(limit+1)=at_sign;
  914.     while (*loc!=at_sign) out(*(loc++));
  915.     if (loc++<=limit) {
  916.       c=*loc++;
  917.       if (ccode[c]==new_module) break;
  918.       if (c!='z' && c!='Z') {
  919.         out(at_sign);
  920.         if (c!=at_sign) err_print("! Double @@ required outside of sections");
  921. @.Double \AT! required...@>
  922.       }
  923.     }
  924. @ The |copy_TeX| routine processes the \TeX\ code at the beginning of a
  925. module; for example, the words you are now reading were copied in this
  926. way. It returns the next control code or `\v' found in the input.
  927. We don't copy spaces or tab marks into the beginning of a line. This
  928. makes the test for empty lines in |finish_line| work.
  929. @<Global...@>= eight_bits next_control; /* control code found */
  930. @ @u eight_bits copy_TeX()
  931.   ASCII c; /* current character being copied */
  932.   while (1) {
  933.     if (loc>limit && (finish_line(), get_line()==0)) return(new_module);
  934.     *(limit+1)=at_sign;
  935.     while ((c=*(loc++))!=vertical_char && c!=at_sign) {
  936.       out(c);
  937.       if (out_ptr==out_buf+1 && (c==' ' || c==tab_mark)) out_ptr--;
  938.     }
  939.     if (c==vertical_char) return(vertical_bar);
  940.     if (loc<=limit) return(ccode[*(loc++)]);
  941. @ The |copy_comment| function issues a warning if more braces are opened than
  942. closed, and in the case of a more serious error it supplies enough
  943. braces to keep \TeX\ from complaining about unbalanced braces.
  944. Instead of copying the \TeX\ material
  945. into the output buffer, this function copies it into the token memory.
  946. The abbreviation |app_tok(t)| is used to append token |t| to the current
  947. token list, and it also makes sure that it is possible to append at least
  948. one further token without overflow.
  949. Copies to end and then follows end of comment with a right brace.
  950. @d app_tok(c) = {if (tok_ptr+2>tok_mem_end) stat_overflow("token"); *(tok_ptr++)=c;}
  951. copy_comment(bal) /* copies \TeX\ code in comments */
  952. int bal; /* brace balance */
  953.   ASCII c; /* current character being copied */
  954.   while (1) {
  955.     if (loc>limit) 
  956.     if (comments_end_with_newline) {
  957.       loc++; if(bal==1) {if (phase==2) app_tok('}'); return(0);}
  958.       else {
  959.         err_print("! Braces don't balance in comment");
  960. @.Braces don't balance in comment@>
  961.         @<Clear |bal| and |return|@>;
  962.     } else {
  963.         if (get_line()==0) {
  964.         err_print("! Input ended in mid-comment");
  965. @.Input ended in mid-comment@>
  966.             loc=buffer+1; @<Clear |bal| and |return|@>;
  967.     c=*(loc++);
  968.     if (c==vertical_char) return(bal);
  969.     @<Check for end of comment@>;
  970.     if (phase==2) app_tok(c);
  971.     @<Copy special things when |c==at_sign, '\\', '{', '}'|; |return| at end@>;
  972. @ @<Copy special things when |c==at_sign...@>=
  973. if (c==at_sign) {
  974.   if (*(loc++)!=at_sign) {
  975.     err_print("! Illegal use of @@ in comment");
  976. @.Illegal use of \AT!...@>
  977.     loc-=2; if (phase==2) tok_ptr--; @<Clear |bal|...@>;
  978. else if (c=='\\' && *loc!=at_sign && phase==2) app_tok(*(loc++))@;
  979. else if (c=='{') bal++;
  980. else if (c=='}') bal--;
  981. @ When the comment has terminated abruptly due to an error, we output
  982. enough right braces to keep \TeX\ happy.
  983. @<Clear |bal|...@>=
  984. app_tok(' '); /* this is done in case the previous character was `\.\\' */
  985. while (bal-- >0) app_tok('}');
  986. /* |if (see_end_of_line) next_control=end_of_line;| */
  987. return(0);
  988. @* Parsing.
  989. The most intricate part of \.{WEAVE} is its mechanism for converting
  990. \cee-like code into \TeX\ code, and we might as well plunge into this
  991. aspect of the program now. A ``bottom up'' approach is used to parse the
  992. \cee-like material, since \.{WEAVE} must deal with fragmentary
  993. constructions whose overall ``part of speech'' is not known.
  994. At the lowest level, the input is represented as a sequence of entities
  995. that we shall call {\it scraps}, where each scrap of information consists
  996. of two parts, its {\it category} and its {\it translation}. The category
  997. is essentially a syntactic class, and the translation is a token list that
  998. represents \TeX\ code. Rules of syntax and semantics tell us how to
  999. combine adjacent scraps into larger ones, and if we are lucky an entire
  1000. \cee\ text that starts out as hundreds of small scraps will join
  1001. together into one gigantic scrap whose translation is the desired \TeX\
  1002. code. If we are unlucky, we will be left with several scraps that don't
  1003. combine; their translations will simply be output, one by one.
  1004. The combination rules are given as context-sensitive productions that are
  1005. applied from left to right. Suppose that we are currently working on the
  1006. sequence of scraps $s_1\,s_2\ldots s_n$. We try first to find the longest
  1007. production that applies to an initial substring $s_1\,s_2\ldots\,$; but if
  1008. no such productions exist, we find to find the longest production
  1009. applicable to the next substring $s_2\,s_3\ldots\,$; and if that fails, we
  1010. try to match $s_3\,s_4\ldots\,$, etc.
  1011. A production applies if the category codes have a given pattern. For
  1012. example, one of the productions is
  1013. $$open\ math\ semi\ \RA\ open\ math$$
  1014. and it means that three consecutive scraps whose respective categories are
  1015. |open|, |math|, and |semi| are con\-verted to two scraps whose categories
  1016. are |open| and |math|. This production also has an associated rule that
  1017. tells how to combine the translation parts:
  1018. $$\eqalign{O_2&=O_1\cr
  1019. M_2&=M_1\,S\,\.{\\,}\,\hbox{|opt|\thinspace\tt5}\cr}$$
  1020. This means that the |open| scrap has not changed, while the new |math| scrap
  1021. has a translation $M_2$ composed of the translation $M_1$ of the original
  1022. |math| scrap followed by the translation |S| of the |semi| scrap followed
  1023. by `\.{\\,}' followed by `|opt|' followed by `\.5'. (In the \TeX\ file,
  1024. this will specify an additional thin space after the semicolon, followed
  1025. by an optional line break with penalty 50.) Translation rules use subscripts
  1026. to distinguish between translations of scraps whose categories have the
  1027. same initial letter; these subscripts are assigned from left to right.
  1028. $\.{WEAVE}$ also has the production rule
  1029. $$\hbox{|semi|$\;\RA\;$|terminator|}$$
  1030. (meaning that a semicolon can terminate a \cee\ statement). Since
  1031. productions are applied from left to right, this rule will be activated
  1032. only if the |semi| is not preceded by scraps that match other productions;
  1033. in particular, a |semi| that is preceded by `|open| |math|' will have
  1034. disappeared because of the production above, and such semicolons do not
  1035. act as statement terminators.
  1036. The translation rule corresponding to $\hbox{|semi|$\;\RA\;$|terminator|}$ is
  1037. $$T=S$$
  1038. but we shall not mention translation rules in the common case that the
  1039. translation of the new scrap on the right-hand side is simply the
  1040. concatenation of the disappearing scraps on the left-hand side.
  1041. @ The token lists for translated \TeX\ output contain some special control
  1042. symbols as well as ordinary characters. These control symbols are
  1043. interpreted by \.{WEAVE} before they are written to the output file.
  1044. \yskip\hang |break_space| denotes an optional line break or an en space;
  1045. \yskip\hang |force| denotes a line break;
  1046. \yskip\hang |big_force| denotes a line break with additional vertical space;
  1047. \yskip\hang |opt| denotes an optional line break (with the continuation
  1048. line indented two ems with respect to the normal starting position)---this
  1049. code is followed by an integer |n|, and the break will occur with penalty
  1050. $10n$;
  1051. \yskip\hang |backup| denotes a backspace of one em;
  1052. \yskip\hang |cancel| obliterates any |break_space| or |force| or |big_force|
  1053. tokens that immediately precede or follow it and also cancels any
  1054. |backup| tokens that follow it;
  1055. \yskip\hang |indent| causes future lines to be indented one more em;
  1056. \yskip\hang |outdent| causes future lines to be indented one less em.
  1057. \yskip\noindent All of these tokens are removed from the \TeX\ output that
  1058. comes from \cee\ text between \pb\ signs; |break_space| and |force| and
  1059. |big_force| become single spaces in this mode. The translation of other
  1060. \cee\ texts results in \TeX\ control sequences \.{\\1}, \.{\\2},
  1061. \.{\\3}, \.{\\4}, \.{\\5}, \.{\\6}, \.{\\7} corresponding respectively to
  1062. |indent|, |outdent|, |opt|, |backup|, |break_space|, |force|, and
  1063. |big_force|. However, a sequence of consecutive `\.\ ', |break_space|,
  1064. |force|, and/or |big_force| tokens is first replaced by a single token
  1065. (the maximum of the given ones).
  1066. The tokens |math_rel| and |math_bin| will be translated into
  1067. \.{\\mathrel\{} and \.{\\mathbin\{}, respectively.
  1068. Also |math_op| to \.{\\mathop\{}.
  1069. Other control sequences in the \TeX\ output will be `\.{\\\\\{}$\,\ldots\,$\.\}'
  1070. surrounding identifiers, `\.{\\\&\{}$\,\ldots\,$\.\}' surrounding
  1071. reserved words, `\.{\\.\{}$\,\ldots\,$\.\}' surrounding strings,
  1072. `\.{\\cee\{}$\,\ldots\,$\.\}$\,$|force|' surrounding comments, and
  1073. `\.{\\X$n$:}$\,\ldots\,$\.{\\X}' surrounding module names, where
  1074. |n| is the module number.
  1075. @d math_bin = @'205  /* should these be octal or decimal? */
  1076. @d math_rel = @'206
  1077. @d math_op = @'207
  1078. @d big_cancel = @'210 /* like |cancel|, also overrides spaces */
  1079. @d cancel = @'211 /* overrides |backup|, |break_space|, |force|, |big_force| */
  1080. @d indent = cancel+1 /* one more tab (\.{\\1}) */
  1081. @d outdent = cancel+2 /* one less tab (\.{\\2}) */
  1082. @d opt = cancel+3 /* optional break in mid-statement (\.{\\3}) */
  1083. @d backup = cancel+4 /* stick out one unit to the left (\.{\\4}) */
  1084. @d break_space = cancel+5 /* optional break between statements (\.{\\5}) */
  1085. @d force = cancel+6 /* forced break between statements (\.{\\6}) */
  1086. @d big_force = cancel+7 /* forced break with additional space (\.{\\7}) */
  1087. @d end_translation = big_force+1 /* special sentinel token at end of list */
  1088. @ Here is a table of all the productions. The reader can best get a feel for
  1089. @^productions, table of@>
  1090. how they work by trying them out by hand on small examples; no amount of
  1091. explanation will be as effective as watching the rules in action.
  1092. Parsing can also be watched by debugging with `\.{@@2}'.
  1093. @i grammar.web
  1094. @* Implementing the productions.
  1095. More specifically, a scrap is a structure consisting of a category
  1096. |cat| and a |text_pointer| |trans|, which points to the translation in
  1097. |tok_start|.  When \cee\ text is to be processed with the grammar above,
  1098. we form an array |scrap_info| containing the initial scraps.
  1099. Our production rules have the nice property that the right-hand side is never
  1100. longer than the left-hand side. Therefore it is convenient to use sequential
  1101. allocation for the current sequence of scraps. Five pointers are used to
  1102. manage the parsing:
  1103. \yskip\hang |pp| is a pointer into |scrap_info|.  We will try to match
  1104. the category codes |pp->cat@,(pp+1)->cat|$\,\ldots\,$ to the left-hand sides
  1105. of productions.
  1106. \yskip\hang |scrap_base|, |lo_ptr|, |hi_ptr|, and |scrap_ptr| are such that
  1107. the current sequence of scraps appears in positions |scrap_base| through
  1108. |lo_ptr| and |hi_ptr| through |scrap_ptr|, inclusive, in the |cat| and
  1109. |trans| arrays. Scraps located between |scrap_base| and |lo_ptr| have
  1110. been examined, while those in positions |>=hi_ptr| have not yet been
  1111. looked at by the parsing process.
  1112. \yskip\noindent Initially |scrap_ptr| is set to the position of the final
  1113. scrap to be parsed, and it doesn't change its value. The parsing process
  1114. makes sure that |lo_ptr>=pp+3|, since productions have as many as four terms,
  1115. by moving scraps from |hi_ptr| to |lo_ptr|. If there are
  1116. fewer than |pp+3| scraps left, the positions up to |pp+3| are filled with
  1117. blanks that will not match in any productions. Parsing stops when
  1118. |pp=lo_ptr+1| and |hi_ptr=scrap_ptr+1|.
  1119. Since the |scrap| structure will later be used for other purposes, we
  1120. declare its second element as unions.
  1121. @<Type...@>=
  1122. typedef struct {
  1123.   eight_bits cat;
  1124.   eight_bits mathness;
  1125.   union {
  1126.     text_pointer Trans;
  1127.     ===> @<Rest of |trans_plus| union@>@;
  1128.   } trans_plus;
  1129. } scrap;
  1130. typedef scrap *scrap_pointer;
  1131. @ @d trans = trans_plus.Trans /* translation texts of scraps */
  1132. @d no_math = 2
  1133. @d yes_math = 1
  1134. @d maybe_math = 0
  1135. @d left_math(A) = ((A)->mathness %4)
  1136. @d right_math(A) = (((A)->mathness/4)%4)
  1137. @d make_math(LM,RM) = ((eight_bits) (LM+4*(RM)))
  1138. @<Global...@>=
  1139. scrap scrap_info[max_scraps]; /* memory array for scraps */
  1140. scrap_pointer scrap_info_end=scrap_info+max_scraps -1; /* end of |scrap_info| */
  1141. scrap_pointer pp; /* current position for reducing productions */
  1142. scrap_pointer scrap_base; /* beginning of the current scrap sequence */
  1143. scrap_pointer scrap_ptr; /* ending of the current scrap sequence */
  1144. scrap_pointer lo_ptr; /* last scrap that has been examined */
  1145. scrap_pointer hi_ptr; /* first scrap that has not been examined */
  1146. #ifdef STAT
  1147. scrap_pointer max_scr_ptr; /* largest value assumed by |scrap_ptr| */
  1148. #endif STAT
  1149. @ @<Set init...@>=
  1150. scrap_base=scrap_info+1;
  1151. #ifdef STAT
  1152. max_scr_ptr=
  1153. #endif STAT
  1154. scrap_ptr=scrap_info;
  1155. @ Token lists in |@!tok_mem| are composed of the following kinds of
  1156. items for \TeX\ output.
  1157. \yskip\item{$\bullet$}ASCII codes and special codes like |force| and
  1158. |math_rel| represent themselves;
  1159. \item{$\bullet$}|id_flag+p| represents \.{\\\\\{{\rm identifier $p$}\}};
  1160. \item{$\bullet$}|res_flag+p| represents \.{\\\&\{{\rm identifier $p$}\}};
  1161. \item{$\bullet$}|mod_flag+p| represents module name |p|;
  1162. \item{$\bullet$}|tok_flag+p| represents token list number |p|;
  1163. \item{$\bullet$}|inner_tok_flag+p| represents token list number |p|, to be
  1164. translated without line-break controls.
  1165. @d id_flag = 10240 /* signifies an identifier */
  1166. @d res_flag = 2*id_flag /* signifies a reserved word */
  1167. @d mod_flag = 3*id_flag /* signifies a module name */
  1168. @d tok_flag = 4*id_flag /* signifies a token list */
  1169. @d inner_tok_flag = 5*id_flag /* signifies a token list in `\pb' */
  1170. #ifdef DEBUG
  1171. print_text(p) /* prints a token list */
  1172. text_pointer p;
  1173.   token_pointer j; /* index into |tok_mem| */
  1174.   sixteen_bits r; /* remainder of token after the flag has been stripped off */
  1175.   if (p>=text_ptr) printf("BAD");
  1176.   else for (j=*p; j<*(p+1); j++) {
  1177.     r=*j%id_flag;
  1178.     switch (*j/id_flag) {
  1179.       case 1: printf("\\{"); print_id((name_dir+r)); printf("}"); break;
  1180.  /* |id_flag| */
  1181.       case 2: printf("\&{"); print_id((name_dir+r)); printf("}"); break;
  1182.  /* |res_flag| */
  1183.       case 3: printf("<"); print_id((name_dir+r)); printf(">"); break;
  1184.         /* |mod_flag| */
  1185.       case 4: printf("[[%d]]",r); break; /* |tok_flag| */
  1186.       case 5: printf("|[[%d]]|",r); break; /* |inner_tok_flag| */
  1187.       default: @<Print token |r| in symbolic form@>;
  1188.     }
  1189. #endif DEBUG
  1190. @ @<Print token |r|...@>=
  1191. switch (r) {
  1192.   case math_bin: printf("\\mathbin{"); break;
  1193.   case math_op: printf("\\mathop{"); break;
  1194.   case math_rel: printf("\\mathrel{"); break;
  1195.   case big_cancel: printf("[ccancel]"); break;
  1196.   case cancel: printf("[cancel]"); break;
  1197.   case indent: printf("[indent]"); break;
  1198.   case outdent: printf("[outdent]"); break;
  1199.   case backup: printf("[backup]"); break;
  1200.   case opt: printf("[opt]"); break;
  1201.   case break_space: printf("[break]"); break;
  1202.   case force: printf("[force]"); break;
  1203.   case big_force: printf("[fforce]"); break;
  1204.   case end_translation: printf("[quit]"); break;
  1205.   default: putxchar(r);
  1206. @ The production rules listed above are embedded directly into the \.{WEAVE}
  1207. program, since it is easier to do this than to write an interpretive system
  1208. that would handle production systems in general. Several macros are defined
  1209. here so that the program for each production is fairly short.
  1210. All of our productions conform to the general notion that some |k|
  1211. consecutive scraps starting at some position |j| are to be replaced by a
  1212. single scrap of some category |c| whose translations is composed from the
  1213. translations of the disappearing scraps. After this production has been
  1214. applied, the production pointer |pp| should change by an amount |d|. Such
  1215. a production can be represented by the quadruple |(j,k,c,d)|. For example,
  1216. the production `|simp@,math| $\RA$ |math|' would be represented by
  1217. `|(pp,2,math,-1)|'; in this case the pointer |pp| should decrease by 1
  1218. after the production has been applied, because some productions with
  1219. |math| in their second positions might now match, but no productions have
  1220. |math| in the third or fourth position of their left-hand sides. Note that
  1221. the value of |d| is determined by the whole collection of productions, not
  1222. by an individual one. Consider the further example
  1223. `|var_head@,math@,colon| $\RA$ |var_head@,intro|', which is represented by
  1224. `|(pp+1,2,intro,+1)|'; the $+1$ here is deduced by looking at the
  1225. grammar and seeing that no matches could possibly occur at positions |<=pp|
  1226. after this production has been applied. The determination of |d| has been
  1227. done by hand in each case, based on the full set of productions but not on
  1228. the grammar of \cee\ or on the rules for constructing the initial
  1229. scraps.
  1230. We also attach a serial number of each production, so that additional
  1231. information is available when debugging. For example, the program below
  1232. contains the statement `|reduce(pp+1,2,intro,+1,52)|' when it implements
  1233. the production just mentioned.
  1234. Before calling |reduce|, the program should have appended the tokens of
  1235. the new translation to the |tok_mem| array. We commonly want to append
  1236. copies of several existing translations, and macros are defined to
  1237. simplify these common cases. For example, |small_app2(pp)| will append the
  1238. translations of two consecutive scraps, |trans[pp]| and |trans[pp+1]|, to
  1239. the current token list. If the entire new translation is formed in this
  1240. way, we write `|squash(j,k,c,d)|' instead of `|reduce(j,k,c,d)|'. For
  1241. example, `|squash(pp,2,math,-1)|' is an abbreviation for `|small_app2(pp);
  1242. reduce(pp,2,math,-1)|'.
  1243. The code below is an exact translation of the production rules into
  1244. \cee, using such macros, and the reader should have no difficulty
  1245. understanding the format by comparing the code with the symbolic
  1246. productions as they were listed earlier.
  1247. @d app2(a) = app1(a);app1(a+1)@;
  1248. @d app3(a) = app2(a);app1(a+2)@;
  1249. @d app4(a) = app3(a);app1(a+3)@;
  1250. @d small_app(a) = *(tok_ptr++)=a@;
  1251. @d small_app1(a) = *(tok_ptr++)=tok_flag+(a)->trans-tok_start@;
  1252. @<Global...@>=
  1253. int init_mathness, last_mathness;
  1254. @ @u app_str(s)
  1255. ASCII *s;
  1256.   while (*s) small_app(*(s++));
  1257. app(a)
  1258. token a;
  1259.  if (a==' ' || a>=big_cancel && a<=big_force) /* non-math token */ {
  1260.   if (last_mathness==maybe_math) init_mathness=no_math;
  1261.   else if (last_mathness==yes_math) small_app('$');
  1262.   last_mathness=no_math;
  1263.  else {
  1264.   if (last_mathness==maybe_math) init_mathness=yes_math;
  1265.   else if (last_mathness==no_math) small_app('$');
  1266.   last_mathness=last_mathness=yes_math;
  1267.  small_app(a);
  1268. app1(a)
  1269. scrap_pointer a;
  1270.   switch (left_math(a)) { /* left boundary */
  1271.   case (no_math):
  1272.     if (last_mathness==maybe_math) init_mathness=no_math;
  1273.     if (last_mathness==yes_math) small_app('$');
  1274.     last_mathness = right_math(a); /* right boundary */
  1275.     break;
  1276.   case (yes_math):
  1277.     if (last_mathness==maybe_math) init_mathness=yes_math;
  1278.     else if (last_mathness==no_math) small_app('$');
  1279.     last_mathness = right_math(a); /* right boundary */
  1280.     break;
  1281.   case (maybe_math): /* no changes */
  1282.     break;
  1283.   small_app(tok_flag+(a)->trans-tok_start);
  1284. @ Let us consider the big switch for productions now, before looking
  1285. at its context. We want to design the program so that this switch
  1286. works, so we might as well not keep ourselves in suspense about exactly what
  1287. code needs to be provided with a proper environment.
  1288. @<Match a production at |pp|, or increase |pp| if there is no match@>= {
  1289.     /* |ignore_scrap| becomes part of the grammar */
  1290.   @<Test for all of the productions@>@;
  1291.   pp++; /* if no match was found, we move to the right */
  1292. @ It may be that during phase two we discover from some arrangement
  1293. of the scraps that an identifier should be treated as a defining instance,
  1294. meaning its index entry should be underlined.
  1295. Since we're in phase two, the identifier is buried inside some scrap,
  1296. which may contain other things as well.
  1297. Using Spider to {\em star} a scrap causes the first identifier in that 
  1298. scrap's translation to get an underlined index entry.
  1299. The starring generates a call to |make_underlined|, which
  1300. finds the first identifier with |first_id| and then underlines it
  1301. with |underline_xref|.
  1302. @<Definition of |first_id|@>@;
  1303. make_underlined(p) 
  1304.     /* underline the entry for the first identifier in |p->trans| */
  1305. scrap_pointer p;
  1306.   sixteen_bits tok_value; /* a token: 
  1307.             the name of this identifier, plus its flag */
  1308.   /* Assume |p->trans < text_ptr| */
  1309.   /* attempt to set |tok_value| to the first identifier in |p->trans| */
  1310.   tok_value = first_id(p->trans);
  1311.   if (tok_value==0) {
  1312. #ifdef DEBUG
  1313.     if (tracing>0) {
  1314.     printf("\n! I couldn't find an identifier to underline.");
  1315.     mark_harmless;
  1316.     }
  1317. #endif DEBUG
  1318.     return;
  1319.   if (tok_value<id_flag || tok_value>=res_flag)
  1320.     fatal("", "! Internal error in first_id");
  1321. @.Internal error in first_id@>
  1322.   /* don't underline identifiers of length 1, even if starred --- force
  1323.      the user to use |"@@!"| */
  1324.   if (length(tok_value-id_flag+name_dir)>1)
  1325.     underline_xref(tok_value-id_flag+name_dir);
  1326. @ |first_id| finds the first identifier in a translation.
  1327. It is indefatigable.
  1328. It returns a |token| value, or zero if it can't find an identifier.
  1329. @<Definition of |first_id|@>=
  1330. sixteen_bits first_id(p)
  1331.     text_pointer p;
  1332.   token_pointer tp; /* used to search for the first identifier */
  1333.   sixteen_bits r; /* remainder after modding out by |id_flag| */
  1334.   sixteen_bits the_id; /* the id we find, or zero otherwise */
  1335.   for (tp=*p; tp<*(p+1); tp++) {    
  1336.     r=*tp%id_flag;
  1337.     switch (*tp/id_flag) {
  1338.       case 1:  /* |id_flag| --- found it */
  1339.     return *tp;
  1340.     break;
  1341.       case 2: /* |res_flag| */
  1342.       case 3: /* |mod_flag| */
  1343.         goto next;
  1344.     break;
  1345.       case 4: /* |tok_flag| */
  1346.       case 5: /* |inner_tok_flag| */
  1347.     /* search the inner list */
  1348.         if ((the_id = first_id(tok_start+r))!=0) return the_id;
  1349.         goto next;
  1350.     break;
  1351.       default: 
  1352.        goto next;
  1353.     break;
  1354.     }
  1355.     next: continue;
  1356.   return 0;
  1357. @ We cannot use |new_xref| to underline a cross-reference at this point
  1358. because this would just make a new cross-reference at the end of the list.
  1359. We actually have to search through the list for the existing
  1360. cross-reference.
  1361. @u underline_xref(p)
  1362. name_pointer p;
  1363.   xref_pointer q=(xref_pointer)p->xref; 
  1364.           /* pointer to cross-reference being examined */
  1365.   xref_pointer r; /* temporary pointer for permuting cross-references */
  1366.   sixteen_bits m; /* cross-reference value to be installed */
  1367.   sixteen_bits n; /* cross-reference value being examined */
  1368.   if (no_xref) return;
  1369.   xref_switch=def_flag;
  1370.   m=module_count+xref_switch;
  1371.   while (q != xmem) {
  1372.     n=q->num;
  1373.     if (n==m) return;
  1374.     else if (m==n+def_flag) {
  1375.  q->num=m; return;
  1376.     }
  1377.     else if (n>=def_flag && n<m) break;
  1378.     q=q->xlink;
  1379.   @<Insert new cross-reference at |q|, not at beginning of list@>;
  1380. @ We get to this module only when the identifier is one letter long,
  1381. so it didn't get a non-underlined entry during phase one.  But it may
  1382. have got some explicitly underlined entries in later modules, so in order
  1383. to preserve the numerical order of the entries in the index, we have
  1384. to insert the new cross-reference not at the beginning of the list
  1385. (namely, at |p->xref|), but rather right before |q|.
  1386. @<Insert new cross-reference at |q|...@>=
  1387.   append_xref(0); /* this number doesn't matter */
  1388.   xref_ptr->xlink=(xref_pointer)p->xref; 
  1389.   p->xref=(ASCII*)xref_ptr;
  1390.   r=xref_ptr;
  1391.   while (r->xlink!=q) {r->num=r->xlink->num; r=r->xlink;}
  1392.   r->num=m; /* everything from |q| on is left undisturbed */
  1393. @ The `|freeze_text|' macro is used to give official status to a token list.
  1394. Before saying |freeze_text|, items are appended to the current token list,
  1395. and we know that the eventual number of this token list will be the current
  1396. value of |text_ptr|. But no list of that number really exists as yet,
  1397. because no ending point for the current list has been
  1398. stored in the |tok_start| array. After saying |freeze_text|, the
  1399. old current token list becomes legitimate, and its number is the current
  1400. value of |text_ptr-1| since |text_ptr| has been increased. The new
  1401. current token list is empty and ready to be appended to.
  1402. Note that |freeze_text| does not check to see that |text_ptr| hasn't gotten
  1403. too large, since it is assumed that this test was done beforehand.
  1404. @d freeze_text = *(++text_ptr)=tok_ptr@;
  1405. @ @u reduce(j,k,c,d,n)
  1406. scrap_pointer j;
  1407. eight_bits c;
  1408. short k, d, n;
  1409.   scrap_pointer i, i1; /* pointers into scrap memory */
  1410.   j->cat=c; j->trans=text_ptr;
  1411.   j->mathness=make_math(init_mathness,last_mathness);
  1412.   freeze_text;
  1413.   if (k>1) {
  1414.     for (i=j+k, i1=j+1; i<=lo_ptr; i++, i1++) {
  1415.       i1->cat=i->cat; i1->trans=i->trans;
  1416.       i1->mathness=i->mathness;
  1417.     }
  1418.     lo_ptr=lo_ptr-k+1;
  1419.   @<Change |pp| to $\max(|scrap_base|,|pp+d|)$@>;
  1420. #ifdef DEBUG
  1421.   @<Print a snapshot of the scrap list if debugging @>;
  1422. #endif DEBUG
  1423.   pp--; /* we next say |pp++| */
  1424. @ @<Change |pp| to $\max...@>=
  1425. if (pp+d>=scrap_base) pp=pp+d;
  1426. else pp=scrap_base;
  1427. @ The `|squash|' 
  1428. procedure takes advantage of the simplification that occurs when |k=1|.
  1429. {\bf `|squash|' isn't used in Spidery \.{WEB}.}
  1430. @u squash(j,k,c,d,n)
  1431. scrap_pointer j;
  1432. eight_bits c;
  1433. short k, d, n;
  1434.   scrap_pointer i; /* pointers into scrap memory */
  1435.   if (k==1) {
  1436.     j->cat=c; @<Change |pp|...@>;
  1437. #ifdef DEBUG
  1438.     @<Print a snapshot...@>;
  1439. #endif DEBUG
  1440.     pp--; /* we next say |pp++| */
  1441.     return;
  1442.   for (i=j; i<j+k; i++) app1(i);
  1443.   reduce(j,k,c,d,n);
  1444. @ Here now is the code that applies productions as long as possible. It
  1445. requires two local labels (|found| and |done|), as well as a local
  1446. variable (|i|).
  1447. @<Reduce the scraps using the productions until no more rules apply@>=
  1448. while (1) {
  1449.   @<Make sure the entries |pp| through |pp+highestposoverall-1| 
  1450.         of |cat| are defined@>;
  1451.   if (tok_ptr+8>tok_mem_end || text_ptr+4>tok_start_end) {
  1452. #ifdef STAT
  1453.     if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
  1454.     if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
  1455. #endif STAT
  1456.     stat_overflow("token/text");
  1457.   if (pp>lo_ptr) break;
  1458.   init_mathness=last_mathness=maybe_math;
  1459.   @<Match a production...@>;
  1460. @ If we get to the end of the scrap list, category codes equal to zero are
  1461. stored, since zero does not match anything in a production.
  1462. @<Make sure the entries...@>=
  1463. if (lo_ptr<pp+highestposoverall-1) {
  1464.   while (hi_ptr<=scrap_ptr && lo_ptr!=pp+highestposoverall-1) {
  1465.     (++lo_ptr)->cat=hi_ptr->cat; lo_ptr->mathness=(hi_ptr)->mathness;
  1466.     lo_ptr->trans=(hi_ptr++)->trans;
  1467.   for (i=lo_ptr+1;i<=pp+highestposoverall-1;i++) i->cat=0;
  1468. @ If \.{WEAVE} is being run in debugging mode, the production numbers and
  1469. current stack categories will be printed out when |tracing| is set to 2;
  1470. a sequence of two or more irreducible scraps will be printed out when
  1471. |tracing| is set to 1.
  1472. @<Global...@>=
  1473. #ifdef DEBUG
  1474. int tracing; /* can be used to show parsing details */
  1475. #endif DEBUG
  1476. @ @<Print a snapshot...@>= {
  1477.   scrap_pointer k; /* pointer into |scrap_info| */
  1478.   if (tracing==2) {
  1479.     printf("\n%d:",n);
  1480.     for (k=scrap_base; k<=lo_ptr; k++) {
  1481.       if (k==pp) putxchar('*'); else putxchar(' ');
  1482.       if (left_math(k) ==  yes_math) putchar('+');
  1483.       else if (left_math(k) ==  no_math) putchar('-');
  1484.       print_cat(k->cat);
  1485.       if (right_math(k)==  yes_math) putchar('+');
  1486.       else if (right_math(k) ==  no_math) putchar('-');
  1487.     }
  1488.     if (hi_ptr<=scrap_ptr) printf("..."); /* indicate that more is coming */
  1489. @ The |translate| function assumes that scraps have been stored in
  1490. positions |scrap_base| through |scrap_ptr| of |cat| and |trans|. It
  1491. appends a |terminator| scrap and begins to apply productions as much as
  1492. possible. The result is a token list containing the translation of
  1493. the given sequence of scraps.
  1494. After calling |translate|, we will have |text_ptr+3<=max_texts| and
  1495. |tok_ptr+6<=max_toks|, so it will be possible to create up to three token
  1496. lists with up to six tokens without checking for overflow. Before calling
  1497. |translate|, we should have |text_ptr<max_texts| and |scrap_ptr<max_scraps|,
  1498. since |translate| might add a new text and a new scrap before it checks
  1499. for overflow.
  1500. @u text_pointer translate() /* converts a sequence of scraps */
  1501.   scrap_pointer i, /* index into |cat| */
  1502.   j; /* runs through final scraps */
  1503.   pp=scrap_base; lo_ptr=pp-1; hi_ptr=pp;
  1504.   @<If tracing, print an indication of where we are@>;
  1505.   @<Reduce the scraps...@>;
  1506.   @<Combine the irreducible scraps that remain@>;
  1507. @ If the initial sequence of scraps does not reduce to a single scrap,
  1508. we concatenate the translations of all remaining scraps, separated by
  1509. blank spaces, with dollar signs
  1510. placed according to the |mathness| of the scraps.
  1511. @<Combine the irreducible...@>= {
  1512.   @<If semi-tracing, show the irreducible scraps@>;
  1513.   for (j=scrap_base; j<=lo_ptr; j++) {
  1514.     if (j!=scrap_base) small_app(' ');
  1515.     if ((left_math(j) == yes_math) && math_flag==0) small_app('$');
  1516.     if ((left_math(j) == no_math) && math_flag==1) {
  1517.     small_app(' '); small_app('$');}
  1518.     small_app1(j);
  1519.     if ((right_math(j) == yes_math) && math_flag==0) small_app('$');
  1520.     if ((right_math(j) == no_math) && math_flag==1) {small_app('$');
  1521.     small_app(' ');}
  1522.     if (tok_ptr+6>tok_mem_end) stat_overflow("token");
  1523.   freeze_text; return(text_ptr-1);
  1524. @ @<If semi-tracing, show the irreducible scraps@>=
  1525. #ifdef DEBUG
  1526. if (lo_ptr>scrap_base && tracing==1) {
  1527.   printf("\nIrreducible scrap sequence in section %d:",module_count);
  1528.   mark_harmless;
  1529.   for (j=scrap_base; j<=lo_ptr; j++) {
  1530.     printf(" "); print_cat(j->cat);
  1531. #endif DEBUG
  1532. @ @<If tracing,...@>=
  1533. #ifdef DEBUG
  1534. if (tracing==2) {
  1535.   printf("\nTracing after l. %d:\n",cur_line); mark_harmless;
  1536.   if (loc>buffer+50) {
  1537.     printf("...");
  1538.     ASCII_write(loc-51,51);
  1539.   else ASCII_write(buffer+1,loc-buffer);
  1540. #endif DEBUG
  1541. @* Initializing the scraps.
  1542. If we are going to use the powerful production mechanism just developed, we
  1543. must get the scraps set up in the first place, given a \cee\ text.
  1544. The raw input is converted into scraps according to the following table,
  1545. which gives category codes followed by the translations. Sometimes a single
  1546. item of input produces more than one scrap.
  1547. \def\stars {\.{---}}%
  1548. A comment in the input will be combined with the preceding
  1549. |omega| or |semi| scrap, or with the following |terminator| scrap, if
  1550. possible; otherwise it will be inserted as a separate |terminator| scrap.
  1551. An additional ``comment'' is effectively appended at the end of the
  1552. \PASCAL\ text, just before translation begins; this consists of a |cancel|
  1553. token in the case of \PASCAL\ text in \pb, otherwise it consists of a
  1554. |force| token.
  1555. From this table it is evident that \.{WEAVE} will parse a lot of non-\PASCAL\
  1556. programs. For example, the reserved words `\.{for}' and `\.{array}' are
  1557. treated in an identical way by \.{WEAVE} from a syntactic standpoint,
  1558. and semantically they are equivalent except that a forced line break occurs
  1559. just before `\&{for}'; \PASCAL\ programmers may well be surprised at this
  1560. similarity. The idea is to keep \.{WEAVE}'s rules as simple as possible,
  1561. consistent with doing a reasonable job on syntactically correct \PASCAL\
  1562. programs. The production rules below have been formulated in the same
  1563. spirit of ``almost anything goes.''
  1564. A table
  1565. of the initial scraps corresponding to \cee\ tokens appeared above in the
  1566. section on parsing; our goal now is to implement that table. We shall do this
  1567. by implementing a subroutine called |C_parse| that is analogous to the
  1568. |C_xref| routine used during phase one.
  1569. Like |C_xref|, the |C_parse| procedure starts with the current
  1570. value of |next_control| and it uses the operation |next_control=get_next|
  1571. repeatedly to read \cee\ text until encountering the next `\v' or
  1572. `\.\{' (begin comment symbol) , or until |next_control>=format|. The
  1573. scraps corresponding to what
  1574. it reads are appended into the |cat| and |trans| arrays, and |scrap_ptr|
  1575. is advanced.
  1576. |C_parse| should never be called with |next_control| equal to
  1577. |begin_comment|, because the
  1578. upper routines should be screening those out.
  1579. @u C_parse(see_v) /* creates scraps from \cee\ tokens */
  1580.     char see_v;
  1581.   name_pointer p; /* identifier designator */
  1582.   while (next_control<format) {
  1583.     @<Append the scrap appropriate to |next_control|@>;
  1584.     next_control=get_next(see_v);
  1585.     if (next_control==vertical_bar || next_control==begin_comment) return;
  1586. @ The following macro is used to append a scrap whose tokens have just
  1587. been appended:
  1588. @d app_scrap(c,M) = (++scrap_ptr)->cat=c; scrap_ptr->trans=text_ptr;
  1589. scrap_ptr->mathness=make_math(M,M);
  1590. freeze_text;
  1591. @ @<Append the scr...@>=
  1592. @<Make sure that there is room for at least four more scraps, six more
  1593. tokens, and four more texts@>;
  1594. switch (next_control) {
  1595.     @<Cases for ordinary tokens@>@;
  1596.   case string: case constant: case verbatim: @<Append a string or constant@>;
  1597.     break;
  1598.   case @`\n': @<Append a newline scrap@>; break;
  1599.   case identifier: @<Append an identifier scrap@>; break;
  1600.   case TeX_string: @<Append a \TeX\ string scrap@>; break;
  1601.   case ignore: case vertical_bar: 
  1602.     break;
  1603. case xref_roman: case xref_wildcard: case xref_typewriter: 
  1604.     break;
  1605.   case thin_space: app_str("\\,"); app_scrap(SP_ignore_scrap,yes_math); break;
  1606.   case math_break:
  1607.  small_app(opt); app_str("0"); app_scrap(SP_ignore_scrap,yes_math); break;
  1608.   case line_break:
  1609.      app_str("\\0"); app_scrap(SP_ignore_scrap,yes_math); break;
  1610.   case line_force:
  1611.  small_app(force); app_scrap(SP_ignore_scrap,no_math); break;
  1612.   case big_line_break:
  1613.  small_app(big_force); app_scrap(SP_ignore_scrap,no_math); break;
  1614.   case no_line_break:
  1615.  small_app(big_cancel); small_app(' '); small_app(big_cancel);
  1616.     app_scrap(SP_ignore_scrap,no_math); break;
  1617.   case pseudo_semi: 
  1618. @<Append a |pseudo_semi| scrap@>
  1619. break; 
  1620.   case join: app_str("\\J"); app_scrap(SP_ignore_scrap,no_math); break;
  1621.   default: small_app(next_control); app_scrap(SP_ignore_scrap,no_math); break;
  1622. @ Since we haven't yet figured out how to compute the room required
  1623. by looking at the productions, let's be paranoid.
  1624. @d SCRAP_SLACK = 50
  1625. @d TOK_SLACK = 50
  1626. @d TEXT_SLACK = 50
  1627. @<Make sure that there is room for at least four...@>=
  1628. if (scrap_ptr+SCRAP_SLACK>scrap_info_end || tok_ptr+TOK_SLACK>tok_mem_end ||
  1629.   text_ptr+TEXT_SLACK>tok_start_end) {
  1630. #ifdef STAT
  1631.   if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
  1632.   if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
  1633.   if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
  1634. #endif STAT
  1635.   stat_overflow("scrap/token/text");
  1636. @ Some nonstandard ASCII characters may have entered \.{WEAVE} by means of
  1637. standard ones. They are converted to \TeX\ control sequences so that it is
  1638. possible to keep \.{WEAVE} from stepping beyond standard ASCII.
  1639. @ The following code must use |app_tok| instead of |small_app| in order to
  1640. protect against overflow. Note that |tok_ptr+1<=max_toks| after |app_tok|
  1641. has been used, so another |small_app| is legitimate before testing again.
  1642. Many of the special characters in a string must be prefixed by `\.\\' so that
  1643. \TeX\ will print them properly.
  1644. @^special string characters@>
  1645. @<Append a string or...@>=
  1646. if (next_control==constant) app_str("\\O{");
  1647. @.\\O@>
  1648. else if (next_control==string) app_str("\\.{");
  1649. @.\\.@>
  1650. else app_str("\\={");
  1651. @.\\=@>
  1652. while (id_first<id_loc) {
  1653.   if (*id_first==at_sign) {
  1654.     if (*(id_first+1)==at_sign) id_first++;
  1655.     else err_print("! Double at_sign should be used in strings");
  1656. @.Double at_sign should be used...@>
  1657.   @<Cause \TeX's special characters to be preceded with |'\\'|@>@;
  1658.   app_tok(*id_first++);
  1659. small_app('}'); 
  1660. @<Do the |app_scrap| for a string or constant@>@;
  1661. @ @<Cause \TeX's special characters to be preceded with |'\\'|@>=
  1662. switch (*id_first) {
  1663.     case ' ':case '\\':
  1664.     case '%':case '$': case '^':case '`':
  1665.     case '#':
  1666.     case '{': case '}':  case '~': case '&': case '_': 
  1667.     small_app('\\'); break;
  1668. @ @<Append a \TeX\ string scrap@>=
  1669. app_str("\\hbox{"); while (id_first<id_loc) app_tok(*id_first++);
  1670. small_app('}');
  1671. @<Do the |app_scrap| for a string or constant@>@;
  1672. @ When the `\v' that introduces \cee\ text is sensed, a call on
  1673. |C_translate| will return a pointer to the \TeX\ translation of
  1674. that text. If scraps exist in |scrap_info|, they are
  1675. unaffected by this translation process.
  1676. @u text_pointer C_translate()
  1677.   text_pointer p; /* points to the translation */
  1678.   scrap_pointer save_base; /* holds original value of |scrap_base| */
  1679.   save_base=scrap_base; scrap_base=scrap_ptr+1;
  1680.   C_parse(1); /* get the scraps together */
  1681.   if (next_control!=vertical_bar) err_print("! Missing vertical_bar after C text");
  1682. @.Missing vertical_bar...@>
  1683.   app_tok(cancel); app_scrap(SP_ignore_scrap,no_math);
  1684.  /* place a |cancel| token as a final ``comment'' */
  1685.   p=translate(); /* make the translation */
  1686. #ifdef STAT
  1687.  if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
  1688. #endif STAT
  1689.   scrap_ptr=scrap_base-1; scrap_base=save_base; /* scrap the scraps */
  1690.   return(p);
  1691. @ The |outer_parse| routine is to |C_parse| as |outer_xref|
  1692. is to |C_xref|: it constructs a sequence of scraps for \cee\ text
  1693. until |next_control>=format|. Thus, it takes care of embedded comments.
  1694. It will also do annotation duty.
  1695. @u outer_parse() /* makes scraps from \cee\ tokens and comments */
  1696.   int bal; /* brace level in comment */
  1697.   text_pointer p, q; /* partial comments */
  1698.   while (next_control<format) {
  1699.     if (next_control==begin_comment) {
  1700.       @<Make sure that there is room for at least seven more
  1701.         tokens, three more texts, and one more scrap@>; /* spider */
  1702.       @<Copy comment, including embedded program text@>;
  1703.     }
  1704.     else {
  1705.        C_parse(0);
  1706.     }
  1707. @ @<Copy comment, including embedded program text@>=
  1708.       small_app(break_space); app_str("\\C{");
  1709. @.\\cee@>
  1710.       bal=copy_comment(1); next_control=vertical_bar;
  1711.       while (bal>0) {
  1712.  p=text_ptr; freeze_text; q=C_translate();
  1713.          /* at this point we have |tok_ptr+6<=max_toks| */ /* spider */
  1714.         small_app(tok_flag+p-tok_start); small_app(inner_tok_flag+q-tok_start);
  1715.         if (next_control==vertical_bar) bal=copy_comment(bal);
  1716.         else bal=0; /* an error has been reported */
  1717.       }
  1718.       small_app(force); 
  1719.       app_scrap(SP_ignore_scrap,no_math);
  1720.          /* the full comment becomes a scrap */
  1721. @ @<Make sure that there is room for at least seven more...@>=
  1722. if (tok_ptr+TOK_SLACK>tok_mem_end || text_ptr+TEXT_SLACK>tok_start_end
  1723.   || scrap_ptr+SCRAP_SLACK>scrap_info_end) {
  1724. #ifdef STAT
  1725.   if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
  1726.   if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
  1727.   if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
  1728. #endif STAT
  1729.   stat_overflow("token/text/scrap");
  1730. @i scraps.web
  1731. @* Output of tokens.
  1732. So far our programs have only built up multi-layered token lists in
  1733. \.{WEAVE}'s internal memory; we have to figure out how to get them into
  1734. the desired final form. The job of converting token lists to characters in
  1735. the \TeX\ output file is not difficult, although it is an implicitly
  1736. recursive process. Three main considerations had to be kept in mind when
  1737. this part of \.{WEAVE} was designed:  (a) There are two modes of output,
  1738. |outer| mode that translates tokens like |force| into line-breaking
  1739. control sequences, and |inner| mode that ignores them except that blank
  1740. spaces take the place of line breaks. (b) The |cancel| instruction applies
  1741. to adjacent token or tokens that are output, and this cuts across levels
  1742. of recursion since `|cancel|' occurs at the beginning or end of a token
  1743. list on one level. (c) The \TeX\ output file will be semi-readable if line
  1744. breaks are inserted after the result of tokens like |break_space| and
  1745. |force|.  (d) The final line break should be suppressed, and there should
  1746. be no |force| token output immediately after `\.{\\Y\\P}'.
  1747. @ The output process uses a stack to keep track of what is going on at
  1748. different ``levels'' as the token lists are being written out. Entries on
  1749. this stack have three parts:
  1750. \yskip\hang |end_field| is the |tok_mem| location where the token list of a
  1751. particular level will end;
  1752. \yskip\hang |tok_field| is the |tok_mem| location from which the next token
  1753. on a particular level will be read;
  1754. \yskip\hang |mode_field| is the current mode, either |inner| or |outer|.
  1755. \yskip\noindent The current values of these quantities are referred to
  1756. quite frequently, so they are stored in a separate place instead of in the
  1757. |stack| array. We call the current values |cur_end|, |cur_tok|, and
  1758. |cur_mode|.
  1759. The global variable |stack_ptr| tells how many levels of output are
  1760. currently in progress. The end of output occurs when an |end_translation|
  1761. token is found, so the stack is never empty except when we first begin the
  1762. output process.
  1763. @d inner = 0 /* value of |mode| for \cee\ texts within \TeX\ texts */
  1764. @d outer = 1 /* value of |mode| for \cee\ texts in modules */
  1765. @<Typed...@>= typedef int mode;
  1766. typedef struct {
  1767.   token_pointer end_field; /* ending location of token list */
  1768.   token_pointer tok_field; /* present location within token list */
  1769.   boolean mode_field; /* interpretation of control tokens */
  1770. } output_state;
  1771. typedef output_state *stack_pointer;
  1772. @ @d cur_end = cur_state.end_field /* current ending location in |tok_mem| */
  1773. @d cur_tok = cur_state.tok_field /* location of next output token in |tok_mem| */
  1774. @d cur_mode = cur_state.mode_field /* current mode of interpretation */
  1775. @d init_stack = stack_ptr=stack;cur_mode=outer /* initialize the stack */
  1776. @<Global...@>=
  1777. output_state cur_state; /* |cur_end|, |cur_tok|, |cur_mode| */
  1778. output_state stack[stack_size]; /* info for non-current levels */
  1779. stack_pointer stack_ptr; /* first unused location in the output state stack */
  1780. stack_pointer stack_end=stack+stack_size-1; /* end of |stack| */
  1781. #ifdef STAT
  1782. stack_pointer max_stack_ptr; /* largest value assumed by |stack_ptr| */
  1783. #endif STAT
  1784. @ @<Set init...@>=
  1785. #ifdef STAT
  1786. max_stack_ptr=stack;
  1787. #endif STAT
  1788. @ To insert token-list |p| into the output, the |push_level| subroutine
  1789. is called; it saves the old level of output and gets a new one going.
  1790. The value of |cur_mode| is not changed.
  1791. @u push_level(p) /* suspends the current level */
  1792. text_pointer p;
  1793.   if (stack_ptr==stack_end) stat_overflow("stack");
  1794.   if (stack_ptr>stack) { /* save current state */
  1795.     stack_ptr->end_field=cur_end;
  1796.     stack_ptr->tok_field=cur_tok;
  1797.     stack_ptr->mode_field=cur_mode;
  1798.   stack_ptr++;
  1799. #ifdef STAT
  1800.   if (stack_ptr>max_stack_ptr) max_stack_ptr=stack_ptr;
  1801. #endif STAT
  1802.   cur_tok=*p; cur_end=*(p+1);
  1803. @ Conversely, the |pop_level| routine restores the conditions that were in
  1804. force when the current level was begun. This subroutine will never be
  1805. called when |stack_ptr=1|.
  1806. @u pop_level()
  1807.   cur_end=(--stack_ptr)->end_field;
  1808.   cur_tok=stack_ptr->tok_field; cur_mode=stack_ptr->mode_field;
  1809. @ The |get_output| function returns the next byte of output that is not a
  1810. reference to a token list. It returns the values |identifier| or |res_word|
  1811. or |mod_name| if the next token is to be an identifier (typeset in
  1812. italics), a reserved word (typeset in boldface) or a module name (typeset
  1813. by a complex routine that might generate additional levels of output).
  1814. In these cases |cur_name| points to the identifier or module name in
  1815. question.
  1816. @<Global...@>=
  1817. name_pointer cur_name;
  1818. @ @d res_word = 0201 /* returned by |get_output| for reserved words */
  1819. @d mod_name = 0200 /* returned by |get_output| for module names */
  1820. @u eight_bits get_output() /* returns the next token of output */
  1821.   sixteen_bits a; /* current item read from |tok_mem| */
  1822.   restart: while (cur_tok==cur_end) pop_level();
  1823.   a=*(cur_tok++);
  1824.   if (a>=0400) {
  1825.     cur_name=a % id_flag + name_dir;
  1826.     switch (a / id_flag) {
  1827.       case 2: return(res_word); /* |a==res_flag+cur_name| */
  1828.       case 3: return(mod_name); /* |a==mod_flag+cur_name| */
  1829.       case 4: push_level(a % id_flag + tok_start); goto restart;
  1830.  /* |a==tok_flag+cur_name| */
  1831.       case 5: push_level(a % id_flag + tok_start); cur_mode=inner; goto restart;
  1832.    /* |a==inner_tok_flag+cur_name| */
  1833.       default: return(identifier); /* |a==id_flag+cur_name| */
  1834.     }
  1835.   return(a);
  1836. @ The real work associated with token output is done by |make_output|.
  1837. This procedure appends an |end_translation| token to the current token list,
  1838. and then it repeatedly calls |get_output| and feeds characters to the output
  1839. buffer until reaching the |end_translation| sentinel. It is possible for
  1840. |make_output| to be called recursively, since a module name may include
  1841. embedded \cee\ text; however, the depth of recursion never exceeds one
  1842. level, since module names cannot be inside of module names.
  1843. A procedure called |output_C| does the scanning, translation, and
  1844. output of \cee\ text within `\pb' brackets, and this procedure uses
  1845. |make_output| to output the current token list. Thus, the recursive call
  1846. of |make_output| actually occurs when |make_output| calls |output_C|
  1847. while outputting the name of a module.
  1848. @^recursion@>
  1849. output_C() /* outputs the current token list */
  1850.   token_pointer save_tok_ptr;
  1851.   text_pointer save_text_ptr;
  1852.   sixteen_bits save_next_control; /* values to be restored */
  1853.   text_pointer p; /* translation of the \cee\ text */
  1854.   save_tok_ptr=tok_ptr; save_text_ptr=text_ptr;
  1855.   save_next_control=next_control; next_control=vertical_bar; p=C_translate();
  1856.   small_app(p-tok_start+inner_tok_flag);
  1857.   make_output(); /* output the list */
  1858. #ifdef STAT
  1859.   if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
  1860.   if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
  1861. #endif STAT
  1862.   text_ptr=save_text_ptr; tok_ptr=save_tok_ptr; /* forget the tokens */
  1863.   next_control=save_next_control; /* restore |next_control| to original state */
  1864. @ Here is \.{WEAVE}'s major output handler.
  1865. @u make_output() /* outputs the equivalents of tokens */
  1866.   eight_bits a, /* current output byte */
  1867.   b; /* next output byte */
  1868.   int c; /* count of |indent| and |outdent| tokens */
  1869.   ASCII *k, *k_limit; /* indices into |byte_mem| */
  1870.   ASCII *j; /* index into |buffer| */
  1871.   ASCII delim; /* first and last character of string being copied */
  1872.   ASCII *save_loc, *save_limit; /* |loc| and |limit| to be restored */
  1873.   name_pointer cur_mod_name; /* name of module being output */
  1874.   boolean save_mode; /* value of |cur_mode| before a sequence of breaks */
  1875.   small_app(end_translation); /* append a sentinel */
  1876.   freeze_text; push_level(text_ptr-1);
  1877.   while (1) {
  1878.     a=get_output();
  1879.     reswitch: switch(a) {
  1880.       case end_translation: return;
  1881.       case identifier: case res_word: @<Output an identifier@>; break;
  1882.       case mod_name: @<Output a module name@>; break;
  1883.       case math_bin: case math_rel: case math_op:
  1884.  @<Output a \.{\\math} operator@>; break;
  1885.       case cancel: c=0; while ((a=get_output())>=indent && a<=big_force) {
  1886.    if (a==indent) c++; if (a==outdent) c--;
  1887.         }
  1888.         @<Output saved |indent| or |outdent| tokens@>;
  1889.         goto reswitch;
  1890.       case big_cancel: c=0;
  1891.  while (((a=get_output())>=indent || a==' ') && a<=big_force) {
  1892.    if (a==indent) c++; if (a==outdent) c--;
  1893.         }
  1894.  @<Output saved...@>;
  1895.  goto reswitch;
  1896.       case indent: case outdent: case opt: case backup: case break_space:
  1897.       case force: case big_force: @<Output a control,
  1898.         look ahead in case of line breaks, possibly |goto reswitch|@>; break;
  1899.       default: out(a); /* otherwise |a| is an ASCII character */
  1900.     }
  1901. @ An identifier of length one does not have to be enclosed in braces, and it
  1902. looks slightly better if set in a math-italic font instead of a (slightly
  1903. narrower) text-italic font. Thus we output `\.{\\\char'174a}' but
  1904. `\.{\\\\\{aa\}}'.
  1905. @<Output an identifier@>=
  1906. out('\\');
  1907. if (a==identifier)
  1908.   if (length(cur_name)==1) out('|')@;
  1909. @.\\|@>
  1910.   else out('\\')@;
  1911. @.\\\\@>
  1912. else out('&')@; /* |a==res_word| */
  1913. @.\\\&@>
  1914. if (length(cur_name)==1) out((cur_name->byte_start)[0])@;
  1915. else out_name(cur_name);
  1916. @ @<Output a \....@>=
  1917. if (a==math_bin) out_str("\\mathbin{");
  1918. else if (a==math_rel) out_str("\\mathrel{");
  1919. else out_str("\\mathop{");
  1920. @ The current mode does not affect the behavior of \.{WEAVE}'s output routine
  1921. except when we are outputting control tokens.
  1922. @<Output a control...@>=
  1923. if (a<break_space) {
  1924.   if (cur_mode==outer) {
  1925.     out('\\'); out(a-cancel+'0');
  1926.     if (a==opt) out(get_output()); /* |opt| is followed by a digit */
  1927.     }
  1928.   else if (a==opt) b=get_output(); /* ignore digit following |opt| */
  1929. else @<Look ahead for strongest line break, |goto reswitch|@>@;
  1930. @ If several of the tokens |break_space|, |force|, |big_force| occur in a
  1931. row, possibly mixed with blank spaces (which are ignored),
  1932. the largest one is used. A line break also occurs in the output file,
  1933. except at the very end of the translation. The very first line break
  1934. is suppressed (i.e., a line break that follows `\.{\\Y\\P}').
  1935. @<Look ahead for st...@>= {
  1936.   b=a; save_mode=cur_mode; c=0;
  1937.   while (1) {
  1938.     a=get_output();
  1939.     if (a==cancel || a==big_cancel) {
  1940.       @<Output saved |indent| or |outdent| tokens@>;
  1941.       goto reswitch; /* |cancel| overrides everything */
  1942.     }
  1943.     if ((a!=' ' && a<indent) || a==backup || a>big_force) {
  1944.       if (save_mode==outer) {
  1945.  if (out_ptr>out_buf+3 && strncmp(out_ptr-3,"\\Y\\P",4)==0)
  1946.    goto reswitch;
  1947.         @<Output saved |indent| or |outdent| tokens@>;
  1948.         out('\\'); out(b-cancel+'0');
  1949.         if (a!=end_translation) finish_line();
  1950.       }
  1951.       else if (a!=end_translation && cur_mode==inner) out(' ');
  1952.       goto reswitch;
  1953.     }
  1954.     if (a==indent) c++;
  1955.     else if (a==outdent) c--;
  1956.     else if (a>b) b=a; /* if |a==' '| we have |a<b| */
  1957. @ @<Output saved...@>=
  1958.   for (;c>0;c--) out_str("\\1");
  1959.   for (;c<0;c++) out_str("\\2");
  1960. @ The remaining part of |make_output| is somewhat more complicated. When we
  1961. output a module name, we may need to enter the parsing and translation
  1962. routines, since the name may contain \cee\ code embedded in
  1963. \pb\ constructions. This \cee\ code is placed at the end of the active
  1964. input buffer and the translation process uses the end of the active
  1965. |tok_mem| area.
  1966. @<Output a module name@>= {
  1967.   boolean is_file;
  1968.   cur_xref=(xref_pointer)cur_name->xref;
  1969.   is_file = cur_xref->num >= file_flag;
  1970.   out_str((is_file? "\\XF":"\\X"));
  1971. @.\\X@>
  1972.   if (cur_xref->num>=def_flag) {
  1973.     out_mod(cur_xref->num-(is_file ? file_flag : def_flag));
  1974.     if (phase==3) {
  1975.       cur_xref=cur_xref->xlink;
  1976.       while (cur_xref->num>=def_flag) {
  1977.  out_str(", ");
  1978.         out_mod(cur_xref->num-(is_file ? file_flag : def_flag));
  1979.       cur_xref=cur_xref->xlink;
  1980.       }
  1981.     }
  1982.   else out('0'); /* output the module number, or zero if it was undefined */
  1983.   out(':'); @<Output the text of the module name@>;
  1984.   out_str((is_file? "\\XF":"\\X"));
  1985. @ @<Output the text...@>=
  1986. k=cur_name->byte_start; k_limit=(cur_name+1)->byte_start;
  1987. cur_mod_name=cur_name;
  1988. while (k<k_limit) {
  1989.   b=*(k++);
  1990.   if (b==at_sign) @<Skip next character, give error if not `\.{@@}'@>@;
  1991.   if (b!=vertical_char) out(b)@;
  1992.   else {
  1993.     @<Copy the \cee\ text into the |buffer| array@>@;
  1994.     save_loc=loc; save_limit=limit; loc=limit+2; limit=j+1;
  1995.     *limit=vertical_char; output_C();
  1996.     loc=save_loc; limit=save_limit;
  1997. @ @<Skip next char...@>=
  1998. if (*k++!=at_sign) {
  1999.   printf("\n! Illegal control code in section name: <");
  2000. @.Illegal control code...@>
  2001.   print_id(cur_mod_name); printf("> "); mark_error;
  2002. @ The \cee\ text enclosed in \pb\ should not contain `\v' characters,
  2003. except within strings. We put a `\v' at the front of the buffer, so that an
  2004. error message that displays the whole buffer will look a little bit sensible.
  2005. The variable |delim| is zero outside of strings, otherwise it
  2006. equals the delimiter that began the string being copied.
  2007. @<Copy the \cee\ text into...@>=
  2008. j=limit+1; *j=vertical_char; delim=0;
  2009. while (1) {
  2010.   if (k>=k_limit) {
  2011.     printf("\n! C text in section name didn't end: <");
  2012. @.C text...didn't end@>
  2013.     print_id(cur_mod_name); printf("> "); mark_error; break;
  2014.   b=*(k++);
  2015.   if (b==at_sign) @<Copy a control code into the buffer@>@;
  2016.   else {
  2017.     if (b=='\'' || b=='"')
  2018.       if (delim==0) delim=b;
  2019.       else if (delim==b) delim=0;
  2020.     if (b!=vertical_char || delim!=0) {
  2021.       if (j>buffer+long_buf_size-3) stat_overflow("buffer");
  2022.       *(++j)=b;
  2023.     }
  2024.     else break;
  2025. @ @<Copy a control code into the buffer@>= {
  2026.   if (j>buffer+long_buf_size-4) stat_overflow("buffer");
  2027.   *(++j)=at_sign; *(++j)=*(k++);
  2028. @* Phase two processing.
  2029. We have assembled enough pieces of the puzzle in order to be ready to specify
  2030. the processing in \.{WEAVE}'s main pass over the source file. Phase two
  2031. is analogous to phase one, except that more work is involved because we must
  2032. actually output the \TeX\ material instead of merely looking at the
  2033. \.{WEB} specifications.
  2034. @u phase_two() {
  2035. reset_input(); printf("\nWriting the output file...");
  2036. module_count=0; copy_limbo();
  2037. math_flag=0;
  2038. finish_line(); flush_buffer(out_buf,0); /* insert a blank line, it looks nice */
  2039. while (!input_has_ended) @<Translate the current module@>;
  2040. @ The output file will contain the control sequence \.{\\Y} between non-null
  2041. sections of a module, e.g., between the \TeX\ and definition parts if both
  2042. are nonempty. This puts a little white space between the parts when they are
  2043. printed. However, we don't want \.{\\Y} to occur between two definitions
  2044. within a single module. The variables |out_line| or |out_ptr| will
  2045. change if a section is non-null, so the following macros `|save_position|'
  2046. and `|emit_space_if_needed|' are able to handle the situation:
  2047. @d save_position = save_line=out_line; save_place=out_ptr@;
  2048. @d emit_space_if_needed = if (save_line!=out_line || save_place!=out_ptr)
  2049.   out_str("\\Y");
  2050. @.\\Y@>
  2051. @<Global...@>=
  2052. int save_line; /* former value of |out_line| */
  2053. ASCII *save_place; /* former value of |out_ptr| */
  2054. @ @<Translate the current module@>= {
  2055.   module_count++;
  2056.   @<Output the code for the beginning of a new module@>;
  2057.   save_position;
  2058.   @<Translate the \TeX\ part of the current module@>;
  2059.   @<Translate the definition part of the current module@>;
  2060.   @<Translate the \cee\ part of the current module@>;
  2061.   @<Show cross-references to this module@>;
  2062.   @<Output the code for the end of a module@>;
  2063. @ Modules beginning with the \.{WEB} control sequence `\.{@@\ }' start in the
  2064. output with the \TeX\ control sequence `\.{\\M}', followed by the module
  2065. number. Similarly, `\.{@@*}' modules lead to the control sequence `\.{\\N}'.
  2066. If this is a changed module, we put \.{*} just before the module number.
  2067. @<Output the code for the beginning...@>=
  2068. if (*(loc-1)!='*') out_str("\\M");
  2069. @.\\M@>
  2070. else {
  2071.   out_str("\\N");
  2072. @.\\N@>
  2073.   printf("*%d",module_count); update_terminal; /* print a progress report */
  2074. out_mod(module_count); out_str(". ");
  2075. @ In the \TeX\ part of a module, we simply copy the source text, except that
  2076. index entries are not copied and \cee\ text within \pb\ is translated.
  2077. @<Translate the \T...@>= do {
  2078.   next_control=copy_TeX();
  2079.   switch (next_control) {
  2080.     case vertical_bar: /* surround vertical bar with \.{\\CD...\\DC} */
  2081.     out_str("\\CD{}"); 
  2082.     init_stack; output_C(); 
  2083.     out_str("\\DC{}"); 
  2084.     break;
  2085.     case at_sign: out(at_sign); break;
  2086.     case octal: @<Translate an octal constant appearing in \TeX\ text@>; break;
  2087.     case hex: @<Translate a hex constant appearing in \TeX\ text@>; break;
  2088.     case TeX_string: case xref_roman: case xref_wildcard: case xref_typewriter:
  2089.     case module_name: loc-=2; next_control=get_next(1); /* skip to \.{@@>} */
  2090.       if (next_control==TeX_string)
  2091.         err_print("! TeX string should be in C text only"); break;
  2092. @.TeX string should be...@>
  2093.     case thin_space: case math_break:
  2094.     case line_break: case big_line_break: case no_line_break: case join:
  2095.     case pseudo_semi: err_print("! You can't do that in TeX text"); break;
  2096. @.You can't do that...@>
  2097. } while (next_control<format);
  2098. @ @<Translate an octal constant appearing in \TeX\ text@>= {
  2099. out_str("\\O{\\~");
  2100.   while ('0'<=*loc && *loc<'8') out(*loc++);
  2101. out('}');
  2102. @ @<Translate a hex constant appearing in \TeX\ text@>= {
  2103. out_str("\\O{\\^");
  2104.   while (isxdigit(*loc)) {
  2105.     out(islower(*loc) ? toupper(*loc):*loc);
  2106.     loc++;
  2107. out('}');
  2108. @ When we get to the following code we have |next_control>=format|, and
  2109. the token memory is in its initial empty state.
  2110. @<Translate the d...@>=
  2111. if (next_control<=definition) { /* definition part non-empty */
  2112.   emit_space_if_needed; save_position;
  2113. while (next_control<=definition) { /* |format| or |definition| */
  2114.   init_stack;
  2115.   if (next_control==definition) @<Start a macro definition@>@;
  2116.   else @<Start a format definition@>;
  2117.   outer_parse(); finish_C();
  2118. @ The |finish_C| procedure outputs the translation of the current
  2119. scraps, preceded by the control sequence `\.{\\P}' and followed by the
  2120. control sequence `\.{\\par}'. It also restores the token and scrap
  2121. memories to their initial empty state.
  2122. A |force| token is appended to the current scraps before translation
  2123. takes place, so that the translation will normally end with \.{\\6} or
  2124. \.{\\7} (the \TeX\ macros for |force| and |big_force|). This \.{\\6} or
  2125. \.{\\7} is replaced by the concluding \.{\\par} or by \.{\\Y\\par}.
  2126. @u finish_C() /* finishes a definition or a \cee\ part */
  2127.   text_pointer p; /* translation of the scraps */
  2128.   out_str("\\P"); app_tok(force); app_scrap(SP_ignore_scrap,no_math);
  2129.   p=translate();
  2130. @.\\P@>
  2131.   small_app(p-tok_start+tok_flag); make_output(); /* output the list */
  2132.   if (out_ptr>out_buf+1)
  2133.     if (*(out_ptr-1)=='\\')
  2134. @.\\6@>
  2135. @.\\7@>
  2136. @.\\Y@>
  2137.       if (*out_ptr=='6') out_ptr-=2; /* suppress ordinary force?! */
  2138.       else if (*out_ptr=='7') *out_ptr='Y';
  2139.   out_str("\\par"); finish_line();
  2140. #ifdef STAT
  2141.   if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
  2142.   if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
  2143.   if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
  2144. #endif STAT
  2145.   tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info;
  2146.     /* forget the tokens and the scraps */
  2147. @<Start a macro...@>= {
  2148.   small_app(backup); app_str("\\D"); /* this will produce `\&{define}' */
  2149. @.\\D@>
  2150. @<Set |next_control| to the first non-newline token@>@;
  2151.   if (next_control!=identifier)
  2152.     err_print("! Improper macro definition");
  2153. @.Improper macro definition@>
  2154.   else {
  2155.     small_app('$'); 
  2156.     small_app(id_flag+id_lookup(id_first, id_loc,normal)-name_dir);
  2157.     @<Scan the parameter list (if any), 
  2158.     and set |next_control| to the non-newline 
  2159.     token following the parameter list@>;
  2160.     if (next_control==@`=') {
  2161.         small_app('\\'); small_app('S'); /* equivalence sign */
  2162.     @<Set |next_control| to the first non-newline token@>@;
  2163.     } else {
  2164.     err_print ("! Equals sign required in macro definition");
  2165. @.Equals sign required...@>
  2166.     }
  2167. punt_the_definition:
  2168.     small_app('$'); small_app(break_space);
  2169.     app_scrap(SP_ignore_scrap,no_math); 
  2170.         /* scrap won't take part in the parsing */
  2171. @ @<Quit scanning the macro definition@>=goto punt_the_definition;
  2172. @ @<Scan the parameter list (if any), 
  2173.     and set |next_control| to the non-newline 
  2174.     token following the parameter list@>=
  2175. @<Set |next_control| to the first non-newline token@>@;
  2176. if (next_control==@`(') {
  2177.     small_app(@`(');
  2178.     do {
  2179.         @<Set |next_control| to the first non-newline token@>@;
  2180.         if (next_control==identifier) {
  2181.                 small_app(id_flag+id_lookup(id_first, id_loc,normal)-name_dir);
  2182.         @<Set |next_control| to the first non-newline token@>@;
  2183.         } else {
  2184.         err_print("! Improper macro definition"); 
  2185.         @<Quit scanning the macro definition@>;
  2186.         }
  2187.         if (next_control==@`,' || next_control==@`)') 
  2188.         small_app(next_control);
  2189.     } while (next_control==@`,');
  2190.     if (next_control != @`)') {
  2191.       err_print("! Macro parameter list must end with )");
  2192.       @<Quit scanning the macro definition@>;
  2193.     @<Set |next_control| to the first non-newline token@>@;
  2194.          /* first token following parameter list */
  2195. @ @<Start a format...@>= {
  2196.   app_str("\\F"); app_scrap(SP_ignore_scrap,no_math);
  2197.       /* this will produce `\&{format}' */
  2198. @.\\F@>
  2199. @<Set |next_control| to the first non-newline token@>@;
  2200. /* claim at this point |scrap_ptr==scrap_info+1| */
  2201.   if (scrap_ptr!=scrap_info+1) {
  2202.     err_print("! This can't happen -- bad scrap_ptr in format definition");
  2203.     printf("\n\tscrap_ptr-scrap_info==%d\n",scrap_ptr-scrap_info);
  2204.   if (next_control==identifier) {
  2205.     small_app(id_flag+id_lookup(id_first, id_loc,normal)-name_dir);
  2206.     app_str(" ");
  2207.     app_scrap(SP_ignore_scrap,no_math); /*spider*/
  2208.  /* this is syntactically separate from what follows */
  2209.     @<Set |next_control| to the first non-newline token@>@;
  2210.     if (next_control==identifier) {
  2211.       small_app(id_flag+id_lookup(id_first, id_loc,normal)-name_dir);
  2212.       small_app(@`\n');
  2213.       app_scrap(SP_ignore_scrap,no_math);
  2214.       @<Set |next_control| to the first non-newline token@>@;
  2215.     }
  2216.   /* if everything went well, we appended two scraps */
  2217.   if (scrap_ptr!=scrap_info+3) err_print("! Improper format definition");
  2218. @.Improper format definition@>
  2219. @ Finally, when the \TeX\ and definition parts have been treated, we have
  2220. |next_control>=begin_unnamed|. We will make the global variable |this_module|
  2221. point to the current module name, if it has a name.
  2222. @<Global...@>=
  2223. name_pointer this_module; /* the current module name, or zero */
  2224. @ @<Translate the \cee...@>=
  2225. this_module=name_dir;
  2226. if (next_control<=module_name) {
  2227.   emit_space_if_needed; init_stack;
  2228.   if (next_control==begin_unnamed) next_control=get_next(0);
  2229.   else {
  2230.     this_module=cur_module;
  2231.     @<Check that |=| follows this module name, and
  2232.       emit the scraps to start the module definition@>;
  2233.   while  (next_control<=module_name) {
  2234.     outer_parse();
  2235.     @<Emit the scrap for a module name if present@>;
  2236.   finish_C();
  2237. @ @<Check that |=|...@>=
  2238. do next_control=get_next(0);
  2239.   while (next_control=='+'); /* allow optional `\.{+=}' */
  2240. if (next_control!='=')
  2241.   err_print("! You need an = sign after the section name");
  2242. @.You need an = sign...@>
  2243.   else next_control=get_next(0);
  2244. if (out_ptr>out_buf+1 && *out_ptr=='Y' && *(out_ptr-1)=='\\') small_app(backup);
  2245.     /* the module name will be flush left */
  2246. @.\\Y@>
  2247. small_app(mod_flag+this_module-name_dir);
  2248. cur_xref=(xref_pointer)this_module->xref;
  2249. app_str("${}");
  2250. if (cur_xref->num%def_flag!=module_count) {
  2251.   app_str("+"); /*module name is multiply defined*/
  2252.   this_module=name_dir; /*so we won't give cross-reference info here*/
  2253. app_str("\\S"); /* output an equivalence sign */
  2254. @.\\S@>
  2255. app_str("{}$");
  2256. small_app(force); 
  2257. @<Call |app_scrap| for a module definition@>
  2258. /* this forces a line break unless `\.{@@+}' follows */
  2259. @ @<Emit the scrap...@>=
  2260. if (next_control<module_name) {
  2261.   err_print("! You can't do that in C text");
  2262. @.You can"t do that...@>
  2263.   next_control=get_next(1);
  2264. else if (next_control==module_name) {
  2265.   if (cur_module_char!='<') {
  2266.   err_print("! You can't use a file like a module");
  2267. @.You can't use a file like a module@>
  2268.   next_control=get_next(1);
  2269.   } else {
  2270.     small_app(mod_flag+cur_module-name_dir); 
  2271.     @<Call |app_scrap| for a module use@>
  2272.     next_control=get_next(1);
  2273. @ Cross references relating to a named module are given after the module ends.
  2274. @<Show cross...@>=
  2275. if (this_module>name_dir) {
  2276.   @<Rearrange the list pointed to by |cur_xref|@>;
  2277.   footnote(((((xref_pointer)this_module->xref)->num >= file_flag) 
  2278.         ? file_flag : def_flag)); 
  2279.   footnote(0);
  2280. @ To rearrange the order of the linked list of cross-references, we need
  2281. four more variables that point to cross-reference entries.  We'll end up
  2282. with a list pointed to by |cur_xref|.
  2283. @<Global...@>=
  2284. xref_pointer next_xref, this_xref, first_xref, mid_xref;
  2285.   /* pointer variables for rearranging a list */
  2286. @ We want to rearrange the cross-reference list so that all the entries with
  2287. |def_flag| come first, in ascending order; then come all the other
  2288. entries, in ascending order.  There may be no entries in either one or both
  2289. of these categories.
  2290. @<Rearrange the list...@>=
  2291.   first_xref=(xref_pointer)this_module->xref;
  2292.   this_xref=first_xref->xlink; /* bypass current module number */
  2293.   if (this_xref->num>def_flag) {
  2294.     mid_xref=this_xref; cur_xref=0; /* this value doesn't matter */
  2295.   do {
  2296.     next_xref=this_xref->xlink; this_xref->xlink=cur_xref;
  2297.     cur_xref=this_xref; this_xref=next_xref;
  2298.   } while (this_xref->num>def_flag);
  2299.   first_xref->xlink=cur_xref;
  2300. else mid_xref=xmem; /* first list null */
  2301. cur_xref=xmem;
  2302. while (this_xref!=xmem) {
  2303.   next_xref=this_xref->xlink; this_xref->xlink=cur_xref;
  2304.   cur_xref=this_xref; this_xref=next_xref;
  2305. if (mid_xref>xmem) mid_xref->xlink=cur_xref;
  2306. else first_xref->xlink=cur_xref;
  2307. cur_xref=first_xref->xlink;
  2308. @ The |footnote| procedure gives cross-reference information about
  2309. multiply defined module names (if the |flag| parameter is |def_flag|), or about
  2310. the uses of a module name (if the |flag| parameter is zero). It assumes that
  2311. |cur_xref| points to the first cross-reference entry of interest, and it
  2312. leaves |cur_xref| pointing to the first element not printed.  Typical outputs:
  2313. `\.{\\A\ section 101.}'; `\.{\\U\ sections 370 and 1009.}';
  2314. `\.{\\A\ sections 8, 27\\*, and 64.}'.
  2315. @u footnote(flag) /* outputs module cross-references */
  2316. sixteen_bits flag;
  2317.   xref_pointer q; /* cross-reference pointer variable */
  2318.   if (cur_xref->num<=flag) return;
  2319.   finish_line(); out('\\');
  2320. @.\\A@>
  2321. @.\\U@>
  2322.   if (flag==0) out('U')@;@+else out('A');
  2323.   out_str(" section");
  2324.   @<Output all the module numbers on the reference list |cur_xref|@>;
  2325.   out('.');
  2326. @ The following code distinguishes three cases, according as the number
  2327. of cross-references is one, two, or more than two. Variable |q| points
  2328. to the first cross-reference, and the last link is a zero.
  2329. @<Output all the module numbers...@>=
  2330. q=cur_xref; if (q->xlink->num>flag) out('s'); /* plural */
  2331. out('~');
  2332. while (1) {
  2333.   out_mod(cur_xref->num-flag);
  2334.   cur_xref=cur_xref->xlink; /* point to the next cross-reference to output */
  2335.   if (cur_xref->num<=flag) break;
  2336.   if (cur_xref->xlink->num>flag || cur_xref!=q->xlink) out(',');
  2337.     /* not the last of two */
  2338.   out(' ');
  2339.   if (cur_xref->xlink->num<=flag) out_str("and~"); /* the last */
  2340. @ @<Output the code for the end of a module@>=
  2341. out_str("\\fi"); finish_line();
  2342. @.\\fi@>
  2343. flush_buffer(out_buf,0); /* insert a blank line, it looks nice */
  2344. @* Phase three processing.
  2345. We are nearly finished! \.{WEAVE}'s only remaining task is to write out the
  2346. index, after sorting the identifiers and index entries.
  2347. If the user has set the |no_xref| flag (the |-x| option on the command line),
  2348. just finish off the page, omitting the index, module name list, and table of
  2349. contents.
  2350. @<Glob...@>=
  2351. extern int no_xref;
  2352. @ @u phase_three() {
  2353. if (no_xref) {
  2354.   finish_line();
  2355.   out_str("\\vfill\\end");
  2356.   finish_line();
  2357. else {
  2358.   phase=3; printf("\nWriting the index...");
  2359.   if (change_exists) {
  2360.     finish_line(); @<Tell about changed modules@>;
  2361.   finish_line(); out_str("\\inx"); finish_line();
  2362. @.\\inx@>
  2363.   @<Do the first pass of sorting@>;
  2364.   @<Sort and output the index@>;
  2365.   out_str("\\fin"); finish_line();
  2366. @.\\fin@>
  2367.   @<Output all the module names@>;
  2368.   out_str("\\con"); finish_line();
  2369. @.\\con@>
  2370. printf("Done.");
  2371. check_complete(); /* was all of the change file used? */
  2372. @ Just before the index comes a list of all the changed modules, including
  2373. the index module itself.
  2374. @<Global...@>=
  2375. sixteen_bits k_module; /* runs through the modules */
  2376. @ @<Tell about changed modules@>= {
  2377.   /* remember that the index is already marked as changed */
  2378.   k_module=0;
  2379.   while (!changed_module[++k_module]);
  2380.   out_str("\\ch ");
  2381.   out_mod(k_module);
  2382.   while (1) {
  2383.     while (!changed_module[++k_module]);
  2384.     out_str(", "); out_mod(k_module);
  2385.     if (k_module==module_count) break;
  2386.   out('.');
  2387. @ A left-to-right radix sorting method is used, since this makes it easy to
  2388. adjust the collating sequence and since the running time will be at worst
  2389. proportional to the total length of all entries in the index. We put the
  2390. identifiers into 102 different lists based on their first characters.
  2391. (Uppercase letters are put into the same list as the corresponding lowercase
  2392. letters, since we want to have `$t<\\{TeX}<\&{to}$'.) The
  2393. list for character |c| begins at location |bucket[c]| and continues through
  2394. the |blink| array.
  2395. @<Global...@>=
  2396. name_pointer bucket[128];
  2397. name_pointer next_name; /* successor of |cur_name| when sorting */
  2398. hash_pointer h; /* index into |hash| */
  2399. name_pointer blink[max_names]; /* links in the buckets */
  2400. @ To begin the sorting, we go through all the hash lists and put each entry
  2401. having a nonempty cross-reference list into the proper bucket.
  2402. @<Do the first pass...@>= {
  2403. int c;
  2404. for (c=0; c<=127; c++) bucket[c]=NULL;
  2405. for (h=hash; h<=hash_end; h++) {
  2406.   next_name=*h;
  2407.   while (next_name) {
  2408.     cur_name=next_name; next_name=cur_name->link;
  2409.     if (((xref_pointer)cur_name->xref)!=xmem) {
  2410.       c=(cur_name->byte_start)[0];
  2411.       if (c<='Z' && c>='A') c=c+040;
  2412.       blink[cur_name-name_dir]=bucket[c]; bucket[c]=cur_name;
  2413.     }
  2414. @ During the sorting phase we shall use the |cat| and |trans| arrays from
  2415. \.{WEAVE}'s parsing algorithm and rename them |depth| and |head|. They now
  2416. represent a stack of identifier lists for all the index entries that have
  2417. not yet been output. The variable |sort_ptr| tells how many such lists are
  2418. present; the lists are output in reverse order (first |sort_ptr|, then
  2419. |sort_ptr-1|, etc.). The |j|th list starts at |head[j]|, and if the first
  2420. |k| characters of all entries on this list are known to be equal we have
  2421. |depth[j]=k|.
  2422. @ @<Rest of |trans_plus| union@>=
  2423. name_pointer Head;
  2424. @d depth = cat /* reclaims memory that is no longer needed for parsing */
  2425. @d head = trans_plus.Head /* ditto */
  2426. @d sort_pointer = scrap_pointer /* ditto */
  2427. @d sort_ptr = scrap_ptr /* ditto */
  2428. @d max_sorts = max_scraps /* ditto */
  2429. @<Global...@>=
  2430. eight_bits cur_depth; /* depth of current buckets */
  2431. ASCII *cur_byte; /* index into |byte_mem| */
  2432. sixteen_bits cur_val; /* current cross-reference number */
  2433. #ifdef STAT
  2434. sort_pointer max_sort_ptr; /* largest value of |sort_ptr| */
  2435. #endif STAT
  2436. @ @<Set init...@>=
  2437. #ifdef STAT
  2438. max_sort_ptr=scrap_info;
  2439. #endif STAT
  2440. @ The desired alphabetic order is specified by the |collate| array; namely,
  2441. |collate[0]<collate[1]<@t$\cdots$@><collate[100]|.
  2442. @<Global...@>=
  2443. ASCII collate[102]; /* collation order */
  2444. @ We use the order $\hbox{null}<\.\ <\hbox{other characters}<\.\_<
  2445. \.A=\.a<\cdots<\.Z=\.z<\.0<\cdots<\.9.$
  2446. @<Set init...@>=
  2447. collate[0]=0; strcpy(collate+1," \1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\
  2448. \20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\
  2449. !\42#$%&'()*+,-./:;<=>?@@[\\]^`{|}~_\
  2450. abcdefghijklmnopqrstuvwxyz0123456789");
  2451. @ Procedure |unbucket| goes through the buckets and adds nonempty lists
  2452. to the stack, using the collating sequence specified in the |collate| array.
  2453. The parameter to |unbucket| tells the current depth in the buckets.
  2454. Any two sequences that agree in their first 255 character positions are
  2455. regarded as identical.
  2456. @d infinity = 255 /* $\infty$ (approximately) */
  2457. @u unbucket(d) /* empties buckets having depth |d| */
  2458. eight_bits d;
  2459.   ASCII c;  /* index into |bucket| */
  2460.   for (c=100; c>= 0; c--) if (bucket[collate[c]]) {
  2461.     if (sort_ptr>=scrap_info_end) stat_overflow("sorting");
  2462.     sort_ptr++;
  2463. #ifdef STAT
  2464.     if (sort_ptr>max_sort_ptr) max_sort_ptr=sort_ptr;
  2465. #endif STAT
  2466.     if (c==0) sort_ptr->depth=infinity;
  2467.     else sort_ptr->depth=d;
  2468.     sort_ptr->head=bucket[collate[c]]; bucket[collate[c]]=NULL;
  2469. @ @<Sort and output...@>=
  2470. sort_ptr=scrap_info; unbucket(1);
  2471. while (sort_ptr>scrap_info) {
  2472.   cur_depth=sort_ptr->depth;
  2473.   if (blink[sort_ptr->head-name_dir]==0 || cur_depth==infinity)
  2474.     @<Output index entries for the list at |sort_ptr|@>@;
  2475.   else @<Split the list at |sort_ptr| into further lists@>;
  2476. @ @<Split the list...@>= {
  2477.   ASCII c;
  2478.   next_name=sort_ptr->head;
  2479.   do {
  2480.     cur_name=next_name; next_name=blink[cur_name-name_dir];
  2481.     cur_byte=cur_name->byte_start+cur_depth;
  2482.     if (cur_byte==(cur_name+1)->byte_start) c=0; /* hit end of the name */
  2483.     else {
  2484.       c=*cur_byte;
  2485.       if (c<='Z' && c>='A') c=c+040;
  2486.     }
  2487.   blink[cur_name-name_dir]=bucket[c]; bucket[c]=cur_name;
  2488.   } while (next_name);
  2489.   --sort_ptr; unbucket(cur_depth+1);
  2490. @ @<Output index...@>= {
  2491.   cur_name=sort_ptr->head;
  2492.   do {
  2493.     out_str("\\:");
  2494. @.\\:@>
  2495.     @<Output the name at |cur_name|@>;
  2496.     @<Output the cross-references at |cur_name|@>;
  2497.     cur_name=blink[cur_name-name_dir];
  2498.   } while (cur_name);
  2499.   --sort_ptr;
  2500. @ @<Output the name...@>=
  2501. switch (cur_name->ilk) {
  2502.   case normal: if (length(cur_name)==1) out_str("\\|");
  2503.     else out_str("\\\\"); break;
  2504. @.\\|@>
  2505. @.\\\\@>
  2506.   case roman: break;
  2507.   case wildcard: out_str("\\9"); break;
  2508. @.\\9@>
  2509.   case typewriter: out_str("\\."); break;
  2510. @.\\.@>
  2511.   default: out_str("\\&");
  2512. @.\\\&@>
  2513. out_name(cur_name);
  2514. @ Section numbers that are to be underlined are enclosed in
  2515. `\.{\\[}$\,\ldots\,$\.]'.
  2516. @<Output the cross-references...@>=
  2517. @<Invert the cross-reference list at |cur_name|, making |cur_xref| the head@>;
  2518.   out_str(", "); cur_val=cur_xref->num;
  2519.   if (cur_val<def_flag) out_mod(cur_val);
  2520.   else {out_str("\\["); out_mod(cur_val%def_flag); out(']');}
  2521. @.\\[@>
  2522.   cur_xref=cur_xref->xlink;
  2523. } while (cur_xref!=xmem);
  2524. out('.'); finish_line();
  2525. @ List inversion is best thought of as popping elements off one stack and
  2526. pushing them onto another. In this case |cur_xref| will be the head of
  2527. the stack that we push things onto.
  2528. @<Invert the cross-reference list at |cur_name|, making |cur_xref| the head@>=
  2529. this_xref=(xref_pointer)cur_name->xref; cur_xref=xmem;
  2530.   next_xref=this_xref->xlink; this_xref->xlink=cur_xref;
  2531.   cur_xref=this_xref; this_xref=next_xref;
  2532. } while (this_xref!=xmem);
  2533. @ The following recursive procedure walks through the tree of module names and
  2534. prints them.
  2535. @^recursion@>
  2536. @u mod_print(p) /* print all module names in subtree |p| */
  2537. name_pointer p;
  2538.   boolean is_file;
  2539.   if (p) {
  2540.     mod_print(p->llink); 
  2541.     cur_xref=(xref_pointer)p->xref;
  2542.     is_file=((cur_xref->num)>=file_flag);
  2543.     if ((is_file && do_file)||(!is_file && !do_file)) { /* C has no xor */
  2544.         out_str("\\:");
  2545. @.\\:@>
  2546.         tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info; init_stack;
  2547.         small_app(p-name_dir+mod_flag); make_output();
  2548.         footnote(0); /* |cur_xref| was set by |make_output| */
  2549.         finish_line();
  2550.     }
  2551.     mod_print(p->rlink);
  2552. @ Here we list files, then modules.
  2553. @<Global...@>=boolean do_file;
  2554. @ @<Output all the module names@>=
  2555. do_file=(1==1);
  2556. mod_print(root);
  2557. do_file=(1==0);
  2558. mod_print(root);
  2559. @ @<Print statistics about memory usage@>=
  2560. printf(
  2561. "\nMemory usage statistics: %d of %d names, %d of %d cross-references,\n",
  2562.   name_ptr-name_dir, name_dir_end-name_dir,
  2563.   xref_ptr-xmem, xmem_end-xmem);
  2564. printf("\t %d of %d bytes;",byte_ptr-byte_mem,byte_mem_end-byte_mem);
  2565. printf("\nParsing required %d of %d(%d) scraps, %d of %d(%d) texts,\n",
  2566.   max_scr_ptr-scrap_info, max_scraps, max_scraps-SCRAP_SLACK,
  2567.   max_text_ptr-tok_start, max_texts, max_texts-TEXT_SLACK
  2568. printf("\t %d of %d(%d) tokens, %d of %d levels;\n",
  2569.   max_tok_ptr-tok_mem, max_toks, max_toks-TOK_SLACK,
  2570.   max_stack_ptr-stack, stack_end-stack
  2571. printf("\nSorting required %d levels\n", max_sort_ptr-scrap_info);
  2572. stat_overflow(s)
  2573.    char *s;
  2574.   printf("\n! Sorry, capacity exceeded: %s",s);
  2575. #ifdef STAT
  2576.   @<Print statistics about memory usage@>;
  2577. #endif STAT
  2578.   history=fatal_message; wrap_up();
  2579. @* Index.
  2580. If you have read and understood the code for Phase III above, you know what
  2581. is in this index and how it got here. All modules in which an identifier is
  2582. used are listed with that identifier, except that reserved words are
  2583. indexed only when they appear in format definitions, and the appearances
  2584. of identifiers in module names are not indexed. Underlined entries
  2585. correspond to where the identifier was declared. Error messages, control
  2586. sequences put into the output, and a few
  2587. other things like ``recursion'' are indexed here too.
  2588.