summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/cwebdir/ctwill-w2c.ch
diff options
context:
space:
mode:
authorAndreas Scherer <andreas_tex@freenet.de>2021-05-03 13:03:46 +0000
committerAndreas Scherer <andreas_tex@freenet.de>2021-05-03 13:03:46 +0000
commit60712e2174bfaa66828692206c37af9b20d9fc9a (patch)
tree3e9284ecd37b56a42a67118bb5aa94482e07112b /Build/source/texk/web2c/cwebdir/ctwill-w2c.ch
parentd3de05fb9dda5d710a51f3ad2097d67d8452a166 (diff)
[CWEB] New release 4.3.1.
This release is almost the same as CWEB 4.3 of 2021-04-16, but * it fixes the indexing bug in CWEAVE/CTWILL that got retracted * it extracts and collects all additions made in CTWILL, so that the section numbers of CWEAVE are retained up to ยง272 and new material is described in the (first) appendix, including the CTWILL user manual * it provides fully revised and (hopefully) corrected mini-indexes for CTWILL, if it is processed by itself (to be published in package 'knuth-pdf' on CTAN) git-svn-id: svn://tug.org/texlive/trunk@59061 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/cwebdir/ctwill-w2c.ch')
-rw-r--r--Build/source/texk/web2c/cwebdir/ctwill-w2c.ch1418
1 files changed, 713 insertions, 705 deletions
diff --git a/Build/source/texk/web2c/cwebdir/ctwill-w2c.ch b/Build/source/texk/web2c/cwebdir/ctwill-w2c.ch
index 777c3c28484..f194af2c139 100644
--- a/Build/source/texk/web2c/cwebdir/ctwill-w2c.ch
+++ b/Build/source/texk/web2c/cwebdir/ctwill-w2c.ch
@@ -31,12 +31,13 @@
@y
% Here is TeX material that gets inserted after \input ctwimac
\def\contentspagenumber{0} % default page number for table of contents
+\datethis % Put timestamp before section 1
@z
@x
-\def\title{CWEAVE (Version 4.2)}
+\def\title{CWEAVE (Version 4.3)}
@y
-\def\title{CTWILL (Version 4.2 [\TeX~Live])}
+\def\title{CTWILL (Version 4.3 [\TeX~Live])}
@z
@x
@@ -46,9 +47,9 @@
@z
@x
- \centerline{(Version 4.2)}
+ \centerline{(Version 4.3)}
@y
- \centerline{(Version 4.2 [\TeX~Live])}
+ \centerline{(Version 4.3 [\TeX~Live])}
@z
@x
@@ -75,7 +76,7 @@ Crusius, and others who have contributed improvements.
The ``banner line'' defined here should be changed whenever \.{CWEAVE}
is modified.
-@d banner "This is CWEAVE (Version 4.2)"
+@d banner "This is CWEAVE (Version 4.3)"
@y
This is the \.{CTWILL} program by D. E. Knuth, based
on \.{CWEAVE} by Silvio Levy and D.~E. Knuth. It is also based on
@@ -91,180 +92,19 @@ were made only to maintain compatibility with \.{CWEAVE}. Further information
can be found in Knuth's article ``Mini-indexes for literate programs,''
reprinted in {\sl Digital Typography\/} (1999), 225--245.
+A kind of ``user manual'' for \.{CTWILL} can be found in the appendix
+{\bf 272.~Mogrify \.{CWEAVE} into \.{CTWILL}} and beyond, together
+with additional material specific to \.{CTWILL}. % FIXME
+Until then, \.{CWEAVE}'s sequence of sections will be preserved.
+
The ``banner line'' defined here should be changed whenever \.{CTWILL} is
modified. The version number parallels the corresponding version of \.{CWEAVE}.
-@d banner "This is CTWILL, Version 4.2"
+@d banner "This is CTWILL, Version 4.3"
/* will be extended by the \TeX~Live |versionstring| */
@z
@x
-@<Predeclaration of procedures@>
-@y
-@<Predeclaration of procedures@>
-
-@ Here is a sort of user manual for \.{CTWILL}---which is exactly like
-\.{CWEAVE} except that it produces much better documentation, for which you
-must work harder. As with \.{CWEAVE}, input comes from a source file
-\.{foo.w} and from an optional (but now almost mandatory) change file
-\.{foo.ch}; output goes to \.{foo.tex}, \.{foo.idx}, and \.{foo.scn}.
-Unlike \.{CWEAVE}, there is an additional output file, \.{foo.aux},
-which records all nonexternal definitions. The \.{.aux} file also
-serves as an input file on subsequent runs. You should run \.{CTWILL}
-twice, once to prime the pump and once to get decent answers.
-
-Moreover, you must run the output twice through \TeX. (This double duplicity
-suggested the original name \.{TWILL}.) After `\.{tex} \.{foo}' you
-will have output that looks like final pages except that the entries
-of mini-indexes won't be alphabetized. \TeX\ will say `This is the first
-pass', and it will produce a weird file called \.{foo.ref}. Say
-$$\.{refsort < foo.ref > foo.sref}$$
-and then another `\.{tex} \.{foo}' will produce alphabetized output.
-While \TeX\ runs it emits messages filled with numeric data, indicating how
-much space is consumed by each program section. If you can decipher these
-numbers (see \.{ctwimac.tex}), you can use them to fine-tune the page
-layout. You might be tempted to do fine tuning by editing \.{foo.tex}
-directly, but it's better to incorporate all changes into \.{foo.ch}.
-
-The mini-indexes list identifiers that are used but not defined on
-each two-page spread. At the end of each section, \.{CTWILL} gives
-\TeX\ a list of identifiers used in that section and information
-about where they are defined. The macros in \.{ctwimac.tex} figure out
-which identifiers should go in each mini-index, based on how the pages
-break. (Yes, those macros are pretty hairy.)
-
-The information that \.{CTWILL} concocts from \.{foo.w} is not always
-correct. Sometimes you'll use an identifier that you don't want
-indexed; for example, your exposition might talk about |f(x)| when you
-don't mean to refer to program variables |f| or |x|. Sometimes you'll
-use an identifier that's defined in a header file, unknown to
-\.{CTWILL}. Sometimes you'll define a single identifier in several
-different places, and \.{CTWILL} won't know which definition to choose.
-But all is not lost. \.{CTWILL} guesses right most of the time, and you can
-give it the necessary hints in other places via your change file.
-
-If you think it's easy to write a completely automatic system that doesn't
-make \.{CTWILL}'s mistakes and doesn't depend so much on change files,
-please do so.
-
-\.{CTWILL} uses a very simple method to generate mini-index info. By
-understanding this method, you will understand how to fix it when things
-go wrong. Every identifier has a current ``meaning,'' consisting of its
-abstract type and the number of the section in which it was most recently
-defined. For example, if your \Cee\ program says `|char *s|' in section~3,
-the meaning of~|s| gets changed to `\&{char} $*$, \S3' while \.{CTWILL}
-is processing that section. If you refer to~|s| in section~10, and if
-|s|~hasn't been redefined in the meantime, and if section~10 doesn't
-wind up on the same two-page spread as section~3, the mini-index generated
-by section~10 will say ``|s|: \&{char}~$*$, \S3.''
-
-The current meaning of every identifier is initially `\.{\\uninitialized}'.
-Then \.{CTWILL} reads the \.{.aux} file for your job, if any; this
-\.{.aux} file contains all definitions of new meanings in the previous
-run, so it tells \.{CTWILL} about definitions that will be occurring
-in the future. If all identifiers have a unique definition, they will
-have a unique and appropriate meaning in the mini-indexes.
-
-But some identifiers, like parameters to procedures, may be defined
-several times. Others may not be defined at all, because they are
-defined elsewhere and mentioned in header files included by the \Cee\
-preprocessor. To solve this problem, \.{CTWILL} provides mechanisms by which
-the current meaning of an identifier can be temporarily or permanently
-changed.
-
-For example, the operation
-$$\.{@@\$s \{FOO\}3 \\\&\{char\} \$*\$@@>}$$
-changes the current meaning of |s| to the \TeX\ output of `\.{\\\&\{char\}}
-\.{\$*\$}' in section~3 of program {\sc FOO}. All entries in the \.{.aux}
-file are expressed in the form of this \.{@@\$} operator; therefore you
-can use a text editor to paste such entries into a \.{.ch} file, whenever
-you want to tell \.{CTWILL} about definitions that are out of order
-or from other programs.
-
-Before reading the \.{.aux} file, \.{CTWILL} actually looks for a file
-called \.{system.bux}, which will be read if present. And after
-\.{foo.aux}, a third possibility is \.{foo.bux}. The general
-convention is to put definitions of system procedures such as |printf|
-into \.{system.bux}, and to put definitions found in specifically
-foo-ish header files into \.{foo.bux}. Like the \.{.aux}
-files, \.{.bux} files should contain only \.{@@\$} specifications;
-this rule corresponds to the fact that `bux' is the plural of `\$'.
-The \.{.bux} files may also contain \.{@@i} includes.
-
-A companion operation \.{@@\%} signifies that all \.{@@\$}
-specifications from the present point to the beginning of the next
-section will define {\it temporary\/} meanings instead of permanent
-ones. Temporary meanings are placed into the
-mini-index of the current section; the permanent (current) meaning of
-the identifier will not be changed, nor will it appear in the
-mini-index of the section. If several temporary meanings are assigned
-to the same identifier in a section, all will appear in the mini-index.
-Each \.{@@\%} toggles the temporary/permanent convention; thus, after
-an even number of \.{@@\%} operations in a section, meanings specified
-by \.{@@\$} are permanent.
-
-The operation \.{@@-} followed by an identifier followed by \.{@@>}
-specifies that the identifier should not generate a mini-index entry
-in the current section (unless, of course, a temporary meaning is assigned).
-
-If \.{@@-foo@@>} appears in a section where a new permanent meaning is
-later defined by the semantics of~\Cee, the current meaning of \\{foo}
-will not be redefined; moreover, this current meaning, which may have
-been changed by \.{@@\$foo ...@@>}, will also be written to the
-\.{.aux} file. Therefore you can control what \.{CTWILL} outputs; you
-can keep it from repeatedly contaminating the \.{.aux} file with
-things you don't like.
-
-The meaning specified by \.{@@\$...@@>} generally has four components:
-an identifier (followed by space), a program name (enclosed in braces),
-a section number (followed by space), and a \TeX\ part. The \TeX\ part
-must have fewer than 50 characters. If the \TeX\ part starts
-with `\.=', the mini-index entry will contain an equals sign instead
-of a colon; for example,
-$$\.{@@\$buf\_size \{PROG\}10 =\\T\{200\}@@>}$$
-generates either `$\\{buf\_size}=200$, \S10' or
-`$\\{buf\_size}=200$, {\sc PROG}\S10', depending on whether
-`{\sc PROG}' is or isn't the title of the current program. If the
-\TeX\ part is `\.{\\zip}', the mini-index entry will contain neither
-colon nor equals, just a comma. The program name and section number
-can also be replaced by a string. For example,
-$$\.{@@\$printf "<stdio.h>" \\zip@@>}$$
-will generate a mini-index entry like `\\{printf}, \.{<stdio.h>}.'.
-
-A special ``proofmode'' is provided so that you can check \.{CTWILL}'s
-conclusions about cross-references. Run \.{CTWILL} with the
-flag \.{+P}, and \TeX\ will produce a specially formatted document
-({\it without\/} mini-indexes)
-in which you can check that your specifications are correct.
-You should always do this before generating mini-indexes, because
-mini-indexes can mask errors if page breaks are favorable but the
-errors might reveal themselves later after your program has changed.
-The proofmode output is much easier to check than the mini-indexes themselves.
-
-The control code \.{@@r} or \.{@@R} causes \.{CTWILL} to emit
-the \TeX\ macro `\.{\\shortpage}' just before starting the next
-section of the program. This causes the section to appear at the top of
-a right-hand page, if it would ordinarily have appeared near the bottom
-of a left-hand page and split across the pages. (The \.{\\shortpage} macro
-is fragile and should be used only in cases where it will not mess up
-the output; insert it only when fine-tuning a set of pages.) If the
-next section is a starred section, the behavior is slightly different
-(but still fragile): The starred section will either be postponed to
-a left-hand page, if it normally would begin on a right-hand page,
-or vice versa. In other words, \.{@@r@@*} inverts the left/right logic.
-
-\.{CTANGLE} does not recognize the operations \.{@@\$}, \.{@@\%}, \.{@@-},
-and \.{@@r}, which are unique to \.{CTWILL}. But that is no problem,
-since you use them only in change files set up for book publishing,
-which are quite different from the change files you set up for tangling.
-
-(End of user manual. We now resume the program for \.{CWEAVE}, with occasional
-outbursts of new code.)
-
-@d max_tex_chars 50 /* limit on the \TeX\ part of a meaning */
-@z
-
-@x
program=cweave;
@y
program=ctwill;
@@ -292,126 +132,16 @@ turned on during the first phase---NOT!
@z
@x
-static sixteen_bits xref_switch,section_xref_switch; /* either zero or |def_flag| */
+@d append_xref(c) if (xref_ptr==xmem_end) overflow("cross-reference");
@y
-static sixteen_bits xref_switch,section_xref_switch; /* either zero or |def_flag| */
-
-@ \.{CTWILL} also has special data structures to keep track of current
-and temporary meanings. These structures were not designed for maximum
-efficiency; they were designed to be easily grafted into \.{CWEAVE}'s
-existing code without major surgery.
-
-@d max_meanings 100 /* max temporary meanings per section */
-@d max_titles 100 /* max distinct program or header names in meanings */
-
-@<Type...@>=
-typedef struct {
- name_pointer id; /* identifier whose meaning is being recorded */
- sixteen_bits prog_no; /* title of program or header in which defined */
- sixteen_bits sec_no; /* section number in which defined */
- char tex_part[max_tex_chars]; /* \TeX\ part of meaning */
-} meaning_struct;
-
-@ @<Private...@>=
-struct perm_meaning {
- meaning_struct perm; /* current meaning of an identifier */
- int stamp; /* last section number in which further output suppressed */
- struct perm_meaning *link; /* another meaning to output in this section */
-} cur_meaning[max_names]; /* the current ``permanent'' meanings */
-static struct perm_meaning *top_usage; /* first meaning to output in this section */
-static meaning_struct temp_meaning_stack[max_meanings]; /* the current ``temporary'' meanings */
-static meaning_struct *temp_meaning_ptr; /* first available slot in |temp_meaning_stack| */
-static meaning_struct *max_temp_meaning_ptr; /* its maximum value so far */
-static name_pointer title_code[max_titles]; /* program names seen so far */
-static name_pointer *title_code_ptr; /* first available slot in |title_code| */
-static char ministring_buf[max_tex_chars]; /* \TeX\ code being generated */
-static char *ministring_ptr; /* first available slot in |ministring_buf| */
-static boolean ms_mode; /* are we outputting to |ministring_buf|? */
-
-@ @<Set init...@>=
-max_temp_meaning_ptr=temp_meaning_stack;
-title_code_ptr=title_code;
-ms_mode=false;
-
-@ Here's a routine that converts a program title from the buffer
-into an internal number for the |prog_no| field of a meaning.
-It advances |loc| past the title found.
-
-@c static sixteen_bits title_lookup(void)
-{
- char *first,*last; /* boundaries */
- int balance; /* excess of left over right */
- register name_pointer *p;
- first=loc;
- if (*loc=='"') {
- while (++loc<=limit && *loc!='"') if (*loc=='\\') loc++;
- } else if (*loc=='{') {
- balance=1;
- while (++loc<=limit) {
- if (*loc=='}' && --balance==0) break;
- if (*loc=='{') balance++;
- }
- } else err_print(_("! Title should be enclosed in braces or doublequotes"));
- last=++loc;
- if (last>limit) err_print(_("! Title name didn't end"));
- if (title_code_ptr==&title_code[max_titles]) overflow(_("titles"));
- *title_code_ptr=id_lookup(first,last,title);
- for (p=title_code;;p++) if (*p==*title_code_ptr) break;
- if (p==title_code_ptr) title_code_ptr++;
- return p-title_code;
-}
-
-@ @<Give a default title to the program, if necessary@>=
-if (title_code_ptr==title_code) { /* no \.{\\def\\title} found in limbo */
- char *saveloc=loc,*savelimit=limit;
- loc=limit+1; limit=loc;
- *limit++='{';
- memcpy(limit,tex_file_name,strlen(tex_file_name)-4);
- limit+=strlen(tex_file_name)-4;
- *limit++='}';
- title_lookup();
- loc=saveloc; limit=savelimit;
-}
-
-@ The |new_meaning| routine changes the current ``permanent meaning''
-when an identifier is redeclared. It gets the |tex_part| from
-|ministring_buf|.
-
-@c
-static void
-new_meaning(
- name_pointer p)
-{
- struct perm_meaning *q=p-name_dir+cur_meaning;
- ms_mode=false;
- if (q->stamp!=section_count) {
- if (*(ministring_ptr-1)==' ') ministring_ptr--;
- if (ministring_ptr>=&ministring_buf[max_tex_chars])
- strcpy(ministring_buf,"\\zip"); /* ignore |tex_part| if too long */
-@.\\zip@>
- else *ministring_ptr='\0';
- q->perm.prog_no=0; /* |q->perm.id=p| */
- q->perm.sec_no=section_count;
- strcpy(q->perm.tex_part,ministring_buf);
- }
- @<Write the new meaning to the \.{.aux} file@>;
-}
-
-@ @<Write the new meaning to the \.{.aux} file@>=
-{@+int n=q->perm.prog_no;
- fprintf(aux_file,"@@$%.*s %.*s",@|
- (int)((p+1)->byte_start-p->byte_start),p->byte_start,@|
- (int)((title_code[n]+1)->byte_start-title_code[n]->byte_start),
- title_code[n]->byte_start);
- if (*(title_code[n]->byte_start)=='{') fprintf(aux_file,"%d",q->perm.sec_no);
- fprintf(aux_file," %s@@>\n",q->perm.tex_part);
-}
+@d append_xref(c) if (xref_ptr==xmem_end) overflow(_("cross-reference"));
@z
@x
-@d append_xref(c) if (xref_ptr==xmem_end) overflow("cross-reference");
+@ Here are the three procedures needed to complete |id_lookup|:
@y
-@d append_xref(c) if (xref_ptr==xmem_end) overflow(_("cross-reference"));
+@ Here are the three procedures needed to complete |id_lookup|:
+@s perm_meaning int
@z
@x
@@ -439,15 +169,6 @@ int_loc=id_lookup("int",NULL,raw_int)-name_dir;
@z
@x
-id_lookup("make_pair",NULL,func_template);
-@y
-id_lookup("make_pair",NULL,func_template);
-
-@ @<Private...@>=
-static sixteen_bits int_loc, ext_loc; /* locations of special reserved words */
-@z
-
-@x
@d ord 0207 /* control code for `\.{@@'}' */
@d join 0210 /* control code for `\.{@@\&}' */
@d thin_space 0211 /* control code for `\.{@@,}' */
@@ -631,58 +352,7 @@ skip_restricted(void)
@y
@.Control codes are forbidden...@>
if (c==meaning && phase==2) @<Process a user-generated meaning@>@;
- else if (c==suppress && phase==2) @<Suppress mini-index entry@>;
- }
-}
-
-@ @<Suppress mini-index entry@>=
-{ char *first=id_first,*last=id_loc;
- while (xisspace(*first)) first++;
- while (xisspace(*(last-1))) last--;
- if (first<last) {
- struct perm_meaning *q=id_lookup(first,last,normal)-name_dir+cur_meaning;
- q->stamp=section_count; /* this is what actually suppresses output */
- }
-}
-
-@ @<Process a user-generated meaning@>=
-{ char *first=id_first;
- while (xisspace(*first)) first++;
- loc=first;
- while (xisalpha(*loc)||xisdigit(*loc)||*loc=='_') loc++;
- if (*loc++!=' ')
- err_print(_("! Identifier in meaning should be followed by space"));
- else { name_pointer p=id_lookup(first,loc-1,normal);
- sixteen_bits t; int n=0;
- t=title_lookup();
- if (*(loc-1)=='}')
- while (xisdigit(*loc)) n=10*n+(*loc++)-'0';
- if (*loc++!=' ')
- err_print(_("! Location in meaning should be followed by space"));
- else @<Digest the meaning of |p|, |t|, |n|@>;
- }
- loc=id_loc+2;
-}
-
-@ @<Digest...@>=
-{ meaning_struct *m;
- struct perm_meaning *q=p-name_dir+cur_meaning;
- if (temp_switch) {
- m=temp_meaning_ptr++;
- if (temp_meaning_ptr>max_temp_meaning_ptr) {
- if (temp_meaning_ptr>&temp_meaning_stack[max_meanings])
- overflow(_("temp meanings"));
- max_temp_meaning_ptr=temp_meaning_ptr;
- }
- } else m=&(q->perm);
- m->id=p;
- m->prog_no=t;
- m->sec_no=n;
- if (id_loc-loc>=max_tex_chars) strcpy(m->tex_part,"\\zip");
-@.\\zip@>
- else { char *q=m->tex_part;
- while (loc<id_loc) *q++=*loc++;
- *q='\0';
+ else if (c==suppress && phase==2) @<Suppress mini-index entry@>@;
@z
@x
@@ -695,7 +365,7 @@ skip_restricted(void)
skip_limbo(); change_exists=false;
@y
skip_limbo();
- @<Give a default title to the program, if necessary@>;
+ @<Give a default title to the program, if necessary@>@;
@z
@x
@@ -872,10 +542,10 @@ the section is changed, we output `\.{\\*}' just after the number.
@z
@x
-@d end_arg 62 /* \.{@@]} */
+@d attr_head 69 /* denotes beginning of attribute */
@y
-@d end_arg 62 /* \.{@@]} */
-@d title 63 /* program name or header name in a ``meaning'' */
+@d attr_head 69 /* denotes beginning of attribute */
+@d title 70 /* program name or header name in a ``meaning'' */
@z
@x
@@ -903,20 +573,25 @@ null_scrap.trans=&tok_start[0];
@c
static void
-print_text(@t\1\1@> /* prints a token list for debugging; not used in |main| */
+print_text( /* prints a token list for debugging; not used in |main| */
@y
@d inner_tok_flag 5*id_flag /* signifies a token list in `\pb' */
-@c
+@<Predecl...@>=
#if 0
-static void
-print_text(@t\1\1@> /* prints a token list for debugging; not used in |main| */
+static void print_text(text_pointer p);
+#endif
+
+@ @c
+#if 0
+@t\4\4@>static void
+print_text( /* prints a token list for debugging; not used in |main| */
@z
@x
update_terminal;
@y
- printf("|\n"); update_terminal;
+ puts("|"); update_terminal;
@z
@x
@@ -929,10 +604,6 @@ print_text(@t\1\1@> /* prints a token list for debugging; not used in |main| */
@x
@ @<Predecl...@>=@+static void print_text(text_pointer p);
@y
-@ @<Predecl...@>=
-#if 0
-static void print_text(text_pointer p);
-#endif
@z
@x
@@ -964,132 +635,9 @@ static token_pointer tok_loc; /* where the first identifier appears */
@z
@x
- r->num=m; /* everything from |q| on is left undisturbed */
-@y
- r->num=m; /* everything from |q| on is left undisturbed */
-
-@ \.{CTWILL} needs the following procedure, which appends tokens of a
-translated text until coming to |tok_loc|, then suppresses text that may
-appear between parentheses or brackets. The calling routine should set
-|ident_seen=false| first. (This is admittedly tricky.)
-
-@c boolean ident_seen;
-static boolean app_supp(
- text_pointer p)
-{ token_pointer j;
- text_pointer q;
- if (ident_seen && **p>=tok_flag) {
- q=**p-tok_flag+tok_start;
- if (**q=='(') {
- app('(');@+app('\\');@+app(',');@+app(')'); goto catch14;
- }
- if (**q=='[') {
- app('[');@+app('\\');@+app(',');@+app(']'); goto catch14;
- }
- }
- for (j=*p;j<*(p+1);j++) {
- if (*j<tok_flag) {
- if (*j==inserted) return false;
- if (j==tok_loc) ident_seen=true;
- else app(*j);
- } else if (*j>=inner_tok_flag) confusion(_("inner"));
- else if (app_supp(*j-tok_flag+tok_start)) goto catch14;;
- }
- return false;
-catch14: if (*(*(p+1)-1)=='9') return true; /* production 14 was used */
- else return false;
-}
-
-@ The trickiest part of \.{CTWILL} is the procedure |make_ministring(l)|,
-which tries to figure out a symbolic form of definition after
-|make_underlined(pp+l)| has been called. We rely heavily on the
-existing productions, which force the translated texts to have a
-structure that's decodable even though the underlying |cat| and |mathness|
-codes have disappeared.
-
-@c static void
-make_ministring(
- int l) /* 0, 1, or 2 */
-{
- text_pointer q,r;
- name_pointer cn;
- token t;
- int ast_count; /* asterisks preceding the expression */
- boolean non_ast_seen; /* have we seen a non-asterisk? */
- if (tok_loc<=operator_found) return;
- cn=((*tok_loc)%id_flag)+name_dir;
- @<Append the type of the declaree; |return| if it begins with \&{extern}@>;
- null_scrap.mathness=(((pp+l)->mathness)%4)*5; big_app1(&null_scrap);
- /* now we're ready for the mathness that follows (I think) */
- /* (without the mod 4 times 5, comments posed a problem) */
- /* (namely in cases like |int a(b,c)| followed by comment) */
- ident_seen=false;@+app_supp((pp+l)->trans);
- null_scrap.mathness=10; big_app1(&null_scrap);
- /* now |cur_mathness==no_math| */
- ms_mode=true; ministring_ptr=ministring_buf;
- if (l==2) *ministring_ptr++='=';
- make_output(); /* translate the current text into a ministring */
- tok_ptr=*(--text_ptr); /* delete that text */
- new_meaning(cn);
- cur_mathness=maybe_math; /* restore it */
-}
-
-@ Here we use the fact that a |decl_head| comes from |int_like| only in
-production~27, whose translation is fairly easy to recognize. (Well,
-production 28 has been added for \CPLUSPLUS/, but we hope that doesn't
-mess us up.) And we also use other similar facts.
-
-If an identifier is given an \&{extern} definition, we don't change
-its current meaning, but we do suppress mini-index entries to its
-current meaning in other sections.
-
-@<Append the type of the declaree; |return| if it begins with \&{extern}@>=
-if (l==0) { app(int_loc+res_flag); app(' '); cur_mathness=no_math; }
-else {
- q=(pp+l-1)->trans;
- ast_count=0;
- non_ast_seen=false;
- while (true) {
- if (*(q+1)==*q+1) {
- r=q;@+break; /* e.g. \&{struct}; we're doing production 45 or 46 */
- }
- if (**q<tok_flag) confusion(_("find type"));
- r=**q-tok_flag+tok_start;
- if ((t=*(*(q+1)-2))>=tok_flag && **(t-tok_flag+tok_start)=='*') {
- /* production 34 */
- if (!non_ast_seen) ast_count++; /* count immediately preceding |*|'s */
- } else non_ast_seen=true;
- if (*(*q+1)==' ' && *(q+1)==*q+2) break; /* production 27 */
- if (*(*q+1)=='{' && *(*q+2)=='}' && *(*q+3)=='$' && *(*q+4)==' '@|
- && *(q+1)==*q+5) break; /* production 27 in disguise */
- q=r;
- }
- while (**r>=tok_flag) {
- if (*(r+1)>*r+9 && *(*r+1)=='{' && *(*r+2)=='}' && *(*r+3)=='$' @|
- && *(*r+4)==indent) q=**r-tok_flag+tok_start; /* production 49 */
- r=**r-tok_flag+tok_start;
- }
- if (**r==ext_loc+res_flag) return; /* \&{extern} gives no definition */
- @<Append tokens for type |q|@>;
-}
-
-@ @<Append tokens for type |q|@>=
-cur_mathness=no_math; /* it was |maybe_math| */
-if (*(q+1)==*q+8 && *(*q+1)==' ' && *(*q+3)==' ') {
- app(**q);@+app(' ');@+app(*(*q+2)); /* production 46 */
-} else if ((t=*(*(q+1)-1))>=tok_flag && **(r=t-tok_flag+tok_start)=='\\'
- && *(*r+1)=='{') app(**q); /* |struct_like| identifier */
-else app((q-tok_start)+tok_flag);
-while (ast_count) {
- big_app('{');@+app('*');@+app('}');@+ast_count--;
-}
-
-@z
-
-@x
@<Cases for |exp|@>=
if (cat1==lbrace || cat1==int_like || cat1==decl) {
- make_underlined(pp); big_app1(pp); big_app(indent); app(indent);
+ make_underlined(pp); big_app(dindent); big_app1(pp);
reduce(pp,1,fn_decl,0,1);
}
@y
@@ -1097,16 +645,13 @@ if (cat1==lbrace || cat1==int_like || cat1==decl) {
if(cat1==lbrace || cat1==int_like || cat1==decl) {
make_underlined(pp);
make_ministring(0);
- big_app1(pp);
- if (indent_param_decl) {
- big_app(indent); app(indent);
- }
+ if (indent_param_decl) big_app(dindent); big_app1(pp);
reduce(pp,1,fn_decl,0,1);
}
@z
@x
- make_underlined (pp); squash(pp,2,tag,-1,7);
+ make_underlined (pp); squash(pp,2,tag,-1,7);
@y
make_underlined (pp);
if (tok_loc>operator_found) {
@@ -1123,10 +668,9 @@ if (cat1==comma) {
big_app2(pp); big_app(' '); reduce(pp,2,decl_head,-1,33);
}
else if (cat1==ubinop) {
- big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
- reduce(pp,2,decl_head,-1,34);
+ big_app1_insert(pp,'{'); big_app('}'); reduce(pp,2,decl_head,-1,34);
}
-else if (cat1==exp && cat2!=lpar && cat2!=exp && cat2!=cast) {
+else if (cat1==exp && cat2!=lpar && cat2!=lbrack && cat2!=exp && cat2!=cast) {
make_underlined(pp+1); squash(pp,2,decl_head,-1,35);
}
else if ((cat1==binop||cat1==colon) && cat2==exp && (cat3==comma ||
@@ -1134,7 +678,7 @@ else if ((cat1==binop||cat1==colon) && cat2==exp && (cat3==comma ||
squash(pp,3,decl_head,-1,36);
else if (cat1==cast) squash(pp,2,decl_head,-1,37);
else if (cat1==lbrace || cat1==int_like || cat1==decl) {
- big_app1(pp); big_app(indent); app(indent); reduce(pp,1,fn_decl,0,38);
+ big_app(dindent); big_app1(pp); reduce(pp,1,fn_decl,0,38);
}
else if (cat1==semi) squash(pp,2,decl,-1,39);
@y
@@ -1143,10 +687,10 @@ if (cat1==comma) {
big_app2(pp); big_app(' '); reduce(pp,2,decl_head,-1,33);
}
else if (cat1==ubinop) {
- big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ big_app1_insert(pp,'{'); big_app('}');
reduce(pp,2,decl_head,-1,34);
}
-else if (cat1==exp && cat2!=lpar && cat2!=exp && cat2!=cast) {
+else if (cat1==exp && cat2!=lpar && cat2!=lbrack && cat2!=exp && cat2!=cast) {
make_underlined(pp+1);
make_ministring(1);
squash(pp,2,decl_head,-1,35);
@@ -1156,10 +700,7 @@ else if ((cat1==binop||cat1==colon) && cat2==exp && (cat3==comma ||
squash(pp,3,decl_head,-1,36);
else if (cat1==cast) squash(pp,2,decl_head,-1,37);
else if (cat1==lbrace || cat1==int_like || cat1==decl) {
- big_app1(pp);
- if (indent_param_decl) {
- big_app(indent); app(indent);
- }
+ if (indent_param_decl) big_app(dindent); big_app1(pp);
reduce(pp,1,fn_decl,0,38);
}
else if (cat1==semi) squash(pp,2,decl,-1,39);
@@ -1168,24 +709,19 @@ else if (cat1==semi) squash(pp,2,decl,-1,39);
@x
@ @<Cases for |decl|@>=
if (cat1==decl) {
- big_app1(pp); big_app(force); big_app1(pp+1);
- reduce(pp,2,decl,-1,40);
+ big_app1_insert(pp,force); reduce(pp,2,decl,-1,40);
}
else if (cat1==stmt || cat1==function) {
- big_app1(pp); big_app(big_force);
- big_app1(pp+1); reduce(pp,2,cat1,-1,41);
+ big_app1_insert(pp,big_force); reduce(pp,2,cat1,-1,41);
}
@y
@ @<Cases for |decl|@>=
if (cat1==decl) {
- big_app1(pp); big_app(force); big_app1(pp+1);
- reduce(pp,2,decl,-1,40);
+ big_app1_insert(pp,force); reduce(pp,2,decl,-1,40);
}
else if (cat1==stmt || cat1==function) {
- big_app1(pp);
- if(order_decl_stmt) big_app(big_force);
- else big_app(force);
- big_app1(pp+1); reduce(pp,2,cat1,-1,41);
+ big_app1_insert(pp,order_decl_stmt ? big_force : force);
+ reduce(pp,2,cat1,-1,41);
}
@z
@@ -1199,7 +735,7 @@ else if (cat1==stmt || cat1==function) {
@x
@ @<Cases for |fn_decl|@>=
if (cat1==decl) {
- big_app1(pp); big_app(force); big_app1(pp+1); reduce(pp,2,fn_decl,0,51);
+ big_app1_insert(pp,force); reduce(pp,2,fn_decl,0,51);
}
else if (cat1==stmt) {
big_app1(pp); app(outdent); app(outdent); big_app(force);
@@ -1208,25 +744,31 @@ else if (cat1==stmt) {
@y
@ @<Cases for |fn_decl|@>=
if (cat1==decl) {
- big_app1(pp); big_app(force); big_app1(pp+1); reduce(pp,2,fn_decl,0,51);
+ big_app1_insert(pp,force); reduce(pp,2,fn_decl,0,51);
}
else if (cat1==stmt) {
big_app1(pp);
if (indent_param_decl) {
app(outdent); app(outdent);
}
- big_app(force);
- big_app1(pp+1); reduce(pp,2,function,-1,52);
+ big_app(force); big_app1(pp+1); reduce(pp,2,function,-1,52);
}
@z
@x
+ big_app1_insert(pp,dindent); reduce(pp,2,fn_decl,0,73);
+@y
+ big_app1(pp); if (indent_param_decl) big_app(dindent);
+ big_app1(pp+1); reduce(pp,2,fn_decl,0,73);
+@z
+
+@x
if (cat1==define_like) make_underlined(pp+2);
@y
-if (cat1==define_like) { /* \.{\#define} is analogous to \&{extern} */
+if (cat1==define_like) { /* \#\&{define} is analogous to \&{extern} */
make_underlined(pp+2);
if (tok_loc>operator_found) {
- /* no time to work out this case; I'll handle defines by brute force
+ /* no time to work out this case; I'll handle \&{define}s by brute force
in the \.{aux} file, since they usually don't go in mini-index */
}
}
@@ -1241,9 +783,9 @@ else squash(pp,1,exp,-2,122);
@z
@x
- big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,else_like,-2,102);
+ big_app1_insert(pp,' '); reduce(pp,2,else_like,-2,102);
@y
- big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,else_like,-2,123);
+ big_app1_insert(pp,' '); reduce(pp,2,else_like,-2,123);
@z
@x
@@ -1251,19 +793,18 @@ else squash(pp,1,exp,-2,122);
if ((cat1==int_like || cat1==cast) && (cat2==comma || cat2==semi))
squash(pp+1,1,exp,-1,115);
else if (cat1==int_like) {
- big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,typedef_like,0,116);
+ big_app1_insert(pp,' '); reduce(pp,2,typedef_like,0,116);
}
else if (cat1==exp && cat2!=lpar && cat2!=exp && cat2!=cast) {
make_underlined(pp+1); make_reserved(pp+1);
- big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,typedef_like,0,117);
+ big_app1_insert(pp,' '); reduce(pp,2,typedef_like,0,117);
}
else if (cat1==comma) {
big_app2(pp); big_app(' '); reduce(pp,2,typedef_like,0,118);
}
else if (cat1==semi) squash(pp,2,decl,-1,119);
else if (cat1==ubinop && (cat2==ubinop || cat2==cast)) {
- big_app('{'); big_app1(pp+1); big_app('}'); big_app1(pp+2);
- reduce(pp+1,2,cat2,0,120);
+ big_app('{'); big_app1_insert(pp+1,'}'); reduce(pp+1,2,cat2,0,120);
}
@y
@ Here \.{CTWILL} deviates from the normal productions introduced in
@@ -1343,7 +884,7 @@ if (cat1==decl_head) {
else app_scrap(p->ilk,maybe_math);
}
}
- @<Flag the usage of this identifier, for the mini-index@>;
+ @<Flag the usage of this identifier, for the mini-index@>@;
@z
@x
@@ -1353,11 +894,9 @@ if (cat1==decl_head) {
@z
@x
-to \.{\\PB}, if the user has invoked \.{CWEAVE} with the \.{+e} flag.
-Although \.{cwebmac} ignores \.{\\PB}, other macro packages
+to \.{\\PB}. Although \.{cwebmac} ignores \.{\\PB}, other macro packages
@y
-to \.{\\PB}, if the user has invoked \.{CTWILL} with the \.{+e} flag.
-Although \.{ctwimac} ignores \.{\\PB}, other macro packages
+to \.{\\PB}. Although \.{ctwimac} ignores \.{\\PB}, other macro packages
@z
@x
@@ -1407,45 +946,11 @@ reset_input(); if (show_progress) fputs(_("\nWriting the output file..."),stdout
section_count=0; format_visible=true; copy_limbo();
@y
temp_switch=false; temp_meaning_ptr=temp_meaning_stack;
-@<Read the \.{.aux} file, if present; then open it for output@>;
+@<Read the \.{.aux} file, if present; then open it for output@>@;
section_count=0; format_visible=true; right_start_switch=false; copy_limbo();
@z
@x
-while (!input_has_ended) @<Translate the current section@>@;
-}
-
-@y
-while (!input_has_ended) @<Translate the current section@>@;
-}
-
-@ @<Private...@>=
-static FILE *aux_file;
-static char aux_file_name[max_file_name_length]; /* name of \.{.aux} file */
-
-@ @<Read the \.{.aux} file, if present; then open it for output@>=
-memcpy(aux_file_name,tex_file_name,strlen(tex_file_name)-4);
-strcat(aux_file_name,".bux");
-include_depth=1; /* we simulate \.{@@i} */
-strcpy(cur_file_name,aux_file_name); /* first in, third out */
-if ((cur_file=fopen(cur_file_name,"r"))) { cur_line=0; include_depth++; }
-strcpy(aux_file_name+strlen(aux_file_name)-4,".aux");
-strcpy(cur_file_name,aux_file_name); /* second in, second out */
-if ((cur_file=fopen(cur_file_name,"r"))) { cur_line=0; include_depth++; }
-strcpy(cur_file_name,"system.bux"); /* third in, first out */
-if ((cur_file=fopen(cur_file_name,"r"))) cur_line=0;
-else include_depth--;
-if (include_depth) { /* at least one new file was opened */
- while (get_next()==meaning) ; /* new meaning is digested */
- if (include_depth) err_print(_("! Only @@$ is allowed in aux and bux files"));
- finish_line(); loc=buffer; /* now reading beginning of line 1 */
-}
-if ((aux_file=fopen(aux_file_name,"wb"))==NULL)
- fatal(_("! Cannot open aux output file "),aux_file_name);
-
-@z
-
-@x
static boolean group_found=false; /* has a starred section occurred? */
@ @<Translate the current section@>= {
@@ -1479,15 +984,15 @@ if (*(loc-1)!='*') {
@y
@.\\N@>
if (right_start_switch) {
- out_str("N"); right_start_switch=false;
+ out('N'); right_start_switch=false;
@.\\NN@>
}
@z
@x
-out_str("{");out_section(section_count); out_str("}");
+out('{'); out_section(section_count); out('}');
@y
-out_str("{");out_section(section_count); out_str("}");
+out('{'); out_section(section_count); out('}');
flush_buffer(out_ptr,false,false);
@z
@@ -1524,15 +1029,10 @@ flush_buffer(out_ptr,false,false);
}
@y
outer_parse();
- if (is_macro) @<Make ministring for a new macro@>;
+ if (is_macro) @<Make ministring for a new macro@>@;
finish_C(format_visible); format_visible=true;
doing_format=false;
}
-
-@ @<Private...@>=
-static boolean is_macro; /* it's a macro def, not a format def */
-static int def_diff; /* 0 iff the current macro has parameters */
-static name_pointer id_being_defined; /* the definee */
@z
@x
@@ -1551,13 +1051,13 @@ static name_pointer id_being_defined; /* the definee */
@x
@.Improper macro definition@>
else {
- app('$'); app_cur_id(false);
+ app_cur_id(false);
@y
@.Improper macro definition@>
else {
id_being_defined=id_lookup(id_first,id_loc,normal);
- app('$'); app_cur_id(false);
- def_diff=*loc-'(';
+ app_cur_id(false);
+ def_diff=(*loc!='(');
@z
@x
@@ -1570,22 +1070,6 @@ static name_pointer id_being_defined; /* the definee */
@ @<Start a format...@>= {
doing_format=true;
@y
-@ @<Make ministring for a new macro@>=
-{
- ms_mode=true; ministring_ptr=ministring_buf;
- *ministring_ptr++='=';
- if (def_diff) { /* parameterless */
- scrap_pointer s=scrap_ptr;
- text_pointer t;
- token_pointer j;
- while (s->cat==insert) s--;
- if ((s-1)->cat==dead && s->cat==exp && **(t=s->trans)=='\\'
- && *(*t+1)=='T') /* it's just a constant */
- for (j=*t;j<*(t+1);j++) *ministring_ptr++=*j;
- else out_str("macro");
- } else out_str("macro (\\,)");
- new_meaning(id_being_defined);
-}
@ @<Start a format...@>= {
doing_format=true;
@@ -1617,94 +1101,10 @@ flush_buffer(out_buf,false,false); /* insert a blank line, it looks nice */
@y
finish_line(); out_str("\\mini"); finish_line();
@.\\mini@>
-@<Output information about usage of id's defined in other sections@>;
+@<Output information about usage of id's defined in other sections@>@;
out_str("}\\FI"); finish_line();
@.\\FI@>
flush_buffer(out_buf,false,false); /* insert a blank line, it looks nice */
-
-@ The following code is performed for each identifier parsed during
-a section. Variable |top_usage| is always nonzero; it has the sentinel
-value~1 initially, then it points to each variable scheduled for
-possible citation. A variable is on this list if and only if its
-|link| field is nonzero. All variables mentioned in the section are
-placed on the list, unless they are reserved and their current
-\TeX\ meaning is uninitialized.
-
-@<Flag the usage of this identifier, for the mini-index@>=
-{ struct perm_meaning *q=p-name_dir+cur_meaning;
- if (!(abnormal(p)) || strcmp(q->perm.tex_part,"\\uninitialized")!=0)
- if (q->link==0) {
- q->link=top_usage;
- top_usage=q;
- }
-}
-
-@ @<Output information about usage of id's defined in other sections@>=
-{ struct perm_meaning *q;
- while (temp_meaning_ptr>temp_meaning_stack) {
- out_mini(--temp_meaning_ptr);
- q=temp_meaning_ptr->id-name_dir+cur_meaning;
- q->stamp=section_count; /* suppress output from ``permanent'' data */
- }
- while (top_usage!=usage_sentinel) {
- q=top_usage;
- top_usage=q->link;
- q->link=NULL;
- if (q->stamp!=section_count) out_mini(&(q->perm));
- }
-}
-
-@ @c static void
-out_mini(
- meaning_struct *m)
-{ char s[60];
- name_pointer cur_name=m->id;
- if (m->prog_no==0) { /* reference within current program */
- if (m->sec_no==section_count) return; /* defined in current section */
- sprintf(s,"\\[%d",m->sec_no);
- } else { name_pointer n=title_code[m->prog_no];
- if (*(n->byte_start)=='{')
- sprintf(s,"\\]%.*s%d",(int)((n+1)->byte_start-n->byte_start),n->byte_start,
- m->sec_no);
- else sprintf(s,"\\]%.*s",(int)((n+1)->byte_start-n->byte_start),n->byte_start);
- }
- out_str(s); out(' ');
- @<Mini-output the name at |cur_name|@>;
- out(' '); out_str(m->tex_part); finish_line();
-}
-
-@ @<Predec...@>=@+static void out_mini(meaning_struct *);
-
-@ @<Mini-output...@>=
-switch (cur_name->ilk) {
- case normal: case func_template: if (length(cur_name)==1) out_str("\\|");
- else {char *j;
- for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
- if (xislower(*j)) goto lowcase;
- out_str("\\."); break;
-lowcase: out_str("\\\\");
- }
- break;
-@.\\|@>
-@.\\.@>
-@.\\\\@>
- case roman: break;
- case wildcard: out_str("\\9"); break;
-@.\\9@>
- case typewriter: out_str("\\."); break;
-@.\\.@>
- case custom: {char *j; out_str("$\\");
- for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
- out(*j=='_'? 'x': *j=='$'? 'X': *j);
- out('$');
- goto name_done;
- }
- default: out_str("\\&");
-@.\\\&@>
-}
-out_name(cur_name,true);
-name_done:
-
@z
@x
@@ -1789,8 +1189,8 @@ the index section itself---NOT!
}
out('.');
}
-
@y
+@ No need to tell about changed sections.
@z
@x
@@ -1809,26 +1209,26 @@ rest of the job.
@z
@x
- case normal: case func_template: if (is_tiny(cur_name)) out_str("\\|");
+ case normal: case func_template:
@y
- case normal: if (is_tiny(cur_name)) out_str("\\|");
+ case normal:
@z
@x
case wildcard: out_str("\\9");@+ goto not_an_identifier;
@y
- case roman: out_str(" "); goto not_an_identifier;
- case wildcard: out_str("\\9"); goto not_an_identifier;
+ case roman: out_str(" ");@+ goto not_an_identifier;
+ case wildcard: out_str("\\9");@+ goto not_an_identifier;
@z
@x
case roman: not_an_identifier: out_name(cur_name,false); goto name_done;
- case custom: {char *j; out_str("$\\");
+ case custom:
+ out_str("$\\");
for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
out(*j=='_'? 'x': *j=='$'? 'X': *j);
out('$');
goto name_done;
- }
@y
not_an_identifier: out_name(cur_name,false); goto name_done;
case custom: out_str("\\$"); break;
@@ -1839,11 +1239,9 @@ not_an_identifier: out_name(cur_name,false); goto name_done;
out_name(cur_name,true);
@y
if (proofing) out_name(cur_name,true);
-else {
+else {@+char *j;
out('{');
- {char *j;
- for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++) out(*j);
- }
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++) out(*j);
out('}');
}
@z
@@ -1900,20 +1298,631 @@ else {
@x
@** Index.
@y
-@** Extensions to \.{CWEB}. The following sections introduce new or improved
-features that have been created by numerous contributors over the course of a
-quarter century.
+@q Section 272. @>
+@** Mogrify {\tentex CWEAVE} into {\tentex CTWILL}. The following sections
+introduce material that is specific to \.{CTWILL}.
+
+Care has been taken to keep the original section numbering of \.{CWEAVE}
+up to this point intact, so this new material should nicely integrate
+with the original ``\&{272.~Index}.''
+
+@q Section 2->273. @>
+@* {\tentex CTWILL} user manual.
+Here is a sort of user manual for \.{CTWILL}---which is exactly like
+\.{CWEAVE} except that it produces much better documentation, for which you
+must work harder. As with \.{CWEAVE}, input comes from a source file
+\.{foo.w} and from an optional (but now almost mandatory) change file
+\.{foo.ch}; output goes to \.{foo.tex}, \.{foo.idx}, and \.{foo.scn}.
+Unlike \.{CWEAVE}, there is an additional output file, \.{foo.aux},
+which records all nonexternal definitions. The \.{.aux} file also
+serves as an input file on subsequent runs. You should run \.{CTWILL}
+twice, once to prime the pump and once to get decent answers.
+
+Moreover, you must run the output twice through \TeX. (This double duplicity
+suggested the original name \.{TWILL}.) After `\.{tex} \.{foo}' you
+will have output that looks like final pages except that the entries
+of mini-indexes won't be alphabetized. \TeX\ will say `This is the first
+pass', and it will produce a weird file called \.{foo.ref}. Say
+$$\.{refsort < foo.ref > foo.sref}$$
+and then another `\.{tex} \.{foo}' will produce alphabetized output.
+While \TeX\ runs it emits messages filled with numeric data, indicating how
+much space is consumed by each program section. If you can decipher these
+numbers (see \.{ctwimac.tex}), you can use them to fine-tune the page
+layout. You might be tempted to do fine tuning by editing \.{foo.tex}
+directly, but it's better to incorporate all changes into \.{foo.ch}.
+
+The mini-indexes list identifiers that are used but not defined on
+each two-page spread. At the end of each section, \.{CTWILL} gives
+\TeX\ a list of identifiers used in that section and information
+about where they are defined. The macros in \.{ctwimac.tex} figure out
+which identifiers should go in each mini-index, based on how the pages
+break. (Yes, those macros are pretty hairy.)
+
+The information that \.{CTWILL} concocts from \.{foo.w} is not always
+correct. Sometimes you'll use an identifier that you don't want
+indexed; for example, your exposition might talk about |f(x)| when you
+don't mean to refer to program variables |f| or |x|. Sometimes you'll
+use an identifier that's defined in a header file, unknown to
+\.{CTWILL}. Sometimes you'll define a single identifier in several
+different places, and \.{CTWILL} won't know which definition to choose.
+But all is not lost. \.{CTWILL} guesses right most of the time, and you can
+give it the necessary hints in other places via your change file.
+
+If you think it's easy to write a completely automatic system that doesn't
+make \.{CTWILL}'s mistakes and doesn't depend so much on change files,
+please do so.
+
+\.{CTWILL} uses a very simple method to generate mini-index info. By
+understanding this method, you will understand how to fix it when things
+go wrong. Every identifier has a current ``meaning,'' consisting of its
+abstract type and the number of the section in which it was most recently
+defined. For example, if your \Cee\ program says `|char *s|' in section~3,
+the meaning of~|s| gets changed to `\&{char} $*$, \S3' while \.{CTWILL}
+is processing that section. If you refer to~|s| in section~10, and if
+|s|~hasn't been redefined in the meantime, and if section~10 doesn't
+wind up on the same two-page spread as section~3, the mini-index generated
+by section~10 will say ``|s|: \&{char}~$*$, \S3.''
+
+The current meaning of every identifier is initially `\.{\\uninitialized}'.
+Then \.{CTWILL} reads the \.{.aux} file for your job, if any; this
+\.{.aux} file contains all definitions of new meanings in the previous
+run, so it tells \.{CTWILL} about definitions that will be occurring
+in the future. If all identifiers have a unique definition, they will
+have a unique and appropriate meaning in the mini-indexes.
+
+But some identifiers, like parameters to procedures, may be defined
+several times. Others may not be defined at all, because they are
+defined elsewhere and mentioned in header files included by the \Cee\
+preprocessor. To solve this problem, \.{CTWILL} provides mechanisms by which
+the current meaning of an identifier can be temporarily or permanently
+changed.
+
+For example, the operation
+$$\.{@@\$s \{FOO\}3 \\\&\{char\} \$*\$@@>}$$
+changes the current meaning of |s| to the \TeX\ output of `\.{\\\&\{char\}}
+\.{\$*\$}' in section~3 of program {\sc FOO}. All entries in the \.{.aux}
+file are expressed in the form of this \.{@@\$} operator; therefore you
+can use a text editor to paste such entries into a \.{.ch} file, whenever
+you want to tell \.{CTWILL} about definitions that are out of order
+or from other programs.
+
+Before reading the \.{.aux} file, \.{CTWILL} actually looks for a file
+called \.{system.bux}, which will be read if present. And after
+\.{foo.aux}, a third possibility is \.{foo.bux}. The general
+convention is to put definitions of system procedures such as |printf|
+into \.{system.bux}, and to put definitions found in specifically
+foo-ish header files into \.{foo.bux}. Like the \.{.aux}
+files, \.{.bux} files should contain only \.{@@\$} specifications;
+this rule corresponds to the fact that `bux' is the plural of `\$'.
+The \.{.bux} files may also contain \.{@@i} includes.
+
+A companion operation \.{@@\%} signifies that all \.{@@\$}
+specifications from the present point to the beginning of the next
+section will define {\it temporary\/} meanings instead of permanent
+ones. Temporary meanings are placed into the
+mini-index of the current section; the permanent (current) meaning of
+the identifier will not be changed, nor will it appear in the
+mini-index of the section. If several temporary meanings are assigned
+to the same identifier in a section, all will appear in the mini-index.
+Each \.{@@\%} toggles the temporary/permanent convention; thus, after
+an even number of \.{@@\%} operations in a section, meanings specified
+by \.{@@\$} are permanent.
+
+The operation \.{@@-} followed by an identifier followed by \.{@@>}
+specifies that the identifier should not generate a mini-index entry
+in the current section (unless, of course, a temporary meaning is assigned).
+
+If \.{@@-foo@@>} appears in a section where a new permanent meaning is
+later defined by the semantics of~\Cee, the current meaning of \\{foo}
+will not be redefined; moreover, this current meaning, which may have
+been changed by \.{@@\$foo ...@@>}, will also be written to the
+\.{.aux} file. Therefore you can control what \.{CTWILL} outputs; you
+can keep it from repeatedly contaminating the \.{.aux} file with
+things you don't like.
+
+The meaning specified by \.{@@\$...@@>} generally has four components:
+an identifier (followed by space), a program name (enclosed in braces),
+a section number (followed by space), and a \TeX\ part. The \TeX\ part
+must have fewer than 50 characters. If the \TeX\ part starts
+with `\.=', the mini-index entry will contain an equals sign instead
+of a colon; for example,
+$$\.{@@\$buf\_size \{PROG\}10 =\\T\{200\}@@>}$$
+generates either `$\\{buf\_size}=200$, \S10' or
+`$\\{buf\_size}=200$, {\sc PROG}\S10', depending on whether
+`{\sc PROG}' is or isn't the title of the current program. If the
+\TeX\ part is `\.{\\zip}', the mini-index entry will contain neither
+colon nor equals, just a comma. The program name and section number
+can also be replaced by a string. For example,
+$$\.{@@\$printf "<stdio.h>" \\zip@@>}$$
+will generate a mini-index entry like `\\{printf}, \.{<stdio.h>}.'.
+
+A special ``proofmode'' is provided so that you can check \.{CTWILL}'s
+conclusions about cross-references. Run \.{CTWILL} with the
+flag \.{+P}, and \TeX\ will produce a specially formatted document
+({\it without\/} mini-indexes)
+in which you can check that your specifications are correct.
+You should always do this before generating mini-indexes, because
+mini-indexes can mask errors if page breaks are favorable but the
+errors might reveal themselves later after your program has changed.
+The proofmode output is much easier to check than the mini-indexes themselves.
+
+The control code \.{@@r} or \.{@@R} causes \.{CTWILL} to emit
+the \TeX\ macro `\.{\\shortpage}' just before starting the next
+section of the program. This causes the section to appear at the top of
+a right-hand page, if it would ordinarily have appeared near the bottom
+of a left-hand page and split across the pages. (The \.{\\shortpage} macro
+is fragile and should be used only in cases where it will not mess up
+the output; insert it only when fine-tuning a set of pages.) If the
+next section is a starred section, the behavior is slightly different
+(but still fragile): The starred section will either be postponed to
+a left-hand page, if it normally would begin on a right-hand page,
+or vice versa. In other words, \.{@@r@@*} inverts the left/right logic.
+
+\.{CTANGLE} does not recognize the operations \.{@@\$}, \.{@@\%}, \.{@@-},
+and \.{@@r}, which are unique to \.{CTWILL}. But that is no problem,
+since you use them only in change files set up for book publishing,
+which are quite different from the change files you set up for tangling.
+
+(End of user manual.)
+
+@d max_tex_chars 50 /* limit on the \TeX\ part of a meaning */
+
+@q Section 25->274. @>
+@* Temporary and permanent meanings.
+\.{CTWILL} has special data structures to keep track of current
+and temporary meanings. These structures were not designed for maximum
+efficiency; they were designed to be easily grafted into \.{CWEAVE}'s
+existing code without major surgery.
+
+@d max_meanings 100 /* max temporary meanings per section */
+@d max_titles 100 /* max distinct program or header names in meanings */
+
+@<Type...@>=
+typedef struct {
+ name_pointer id; /* identifier whose meaning is being recorded */
+ sixteen_bits prog_no; /* title of program or header in which defined */
+ sixteen_bits sec_no; /* section number in which defined */
+ char tex_part[max_tex_chars]; /* \TeX\ part of meaning */
+} meaning_struct;
+
+@q Section 26->275. @>
+@ @<Private...@>=
+struct perm_meaning {
+ meaning_struct perm; /* current meaning of an identifier */
+ int stamp; /* last section number in which further output suppressed */
+ struct perm_meaning *link; /* another meaning to output in this section */
+} cur_meaning[max_names]; /* the current ``permanent'' meanings */
+static struct perm_meaning *top_usage; /* first meaning to output in this section */
+static meaning_struct temp_meaning_stack[max_meanings]; /* the current ``temporary'' meanings */
+static meaning_struct *temp_meaning_ptr; /* first available slot in |temp_meaning_stack| */
+static meaning_struct *max_temp_meaning_ptr; /* its maximum value so far */
+static name_pointer title_code[max_titles]; /* program names seen so far */
+static name_pointer *title_code_ptr; /* first available slot in |title_code| */
+static char ministring_buf[max_tex_chars]; /* \TeX\ code being generated */
+static char *ministring_ptr; /* first available slot in |ministring_buf| */
+static boolean ms_mode; /* are we outputting to |ministring_buf|? */
+
+@q Section 27->276. @>
+@ @<Set init...@>=
+max_temp_meaning_ptr=temp_meaning_stack;
+title_code_ptr=title_code;
+ms_mode=false;
+
+@q Section 277. @>
+@ @<Predec...@>=@+static void new_meaning(name_pointer);
+
+@q Section 30->278. @>
+@ The |new_meaning| routine changes the current ``permanent meaning''
+when an identifier is redeclared. It gets the |tex_part| from
+|ministring_buf|.
+
+@c
+static void
+new_meaning(
+ name_pointer p)
+{
+ struct perm_meaning *q=p-name_dir+cur_meaning;
+ ms_mode=false;
+ if (q->stamp!=section_count) {
+ if (*(ministring_ptr-1)==' ') ministring_ptr--;
+ if (ministring_ptr>=&ministring_buf[max_tex_chars])
+ strcpy(ministring_buf,"\\zip"); /* ignore |tex_part| if too long */
+@.\\zip@>
+ else *ministring_ptr='\0';
+ q->perm.prog_no=0; /* |q->perm.id=p| */
+ q->perm.sec_no=section_count;
+ strcpy(q->perm.tex_part,ministring_buf);
+ }
+ @<Write the new meaning to the \.{.aux} file@>@;
+}
+
+@q Section 75->279. @>
+@ @<Process a user-generated meaning@>=
+{ char *first=id_first;
+ while (xisspace(*first)) first++;
+ loc=first;
+ while (xisalpha(*loc)||xisdigit(*loc)||*loc=='_') loc++;
+ if (*loc++!=' ')
+ err_print(_("! Identifier in meaning should be followed by space"));
+ else {@+ int n=0;
+ name_pointer p=id_lookup(first,loc-1,normal);
+ sixteen_bits t=title_lookup();
+ if (*(loc-1)=='}')
+ while (xisdigit(*loc)) n=10*n+(*loc++)-'0';
+ if (*loc++!=' ')
+ err_print(_("! Location in meaning should be followed by space"));
+ else @<Digest the meaning of |p|, |t|, |n|@>@;
+ }
+ loc=id_loc+2;
+}
+
+@q Section 76->280. @>
+@ @<Suppress mini-index entry@>=
+{ char *first=id_first,*last=id_loc;
+ while (xisspace(*first)) first++;
+ while (xisspace(*(last-1))) last--;
+ if (first<last) {
+ struct perm_meaning *q=id_lookup(first,last,normal)-name_dir+cur_meaning;
+ q->stamp=section_count; /* this is what actually suppresses output */
+ }
+}
+
+@q Section 77->281. @>
+@ @<Digest...@>=
+{ meaning_struct *m;
+ struct perm_meaning *q=p-name_dir+cur_meaning;
+ if (temp_switch) {
+ m=temp_meaning_ptr++;
+ if (temp_meaning_ptr>max_temp_meaning_ptr) {
+ if (temp_meaning_ptr>&temp_meaning_stack[max_meanings])
+ overflow(_("temp meanings"));
+ max_temp_meaning_ptr=temp_meaning_ptr;
+ }
+ } else m=&(q->perm);
+ m->id=p;
+ m->prog_no=t;
+ m->sec_no=n;
+ if (id_loc-loc>=max_tex_chars) strcpy(m->tex_part,"\\zip");
+@.\\zip@>
+ else { char *q=m->tex_part;
+ while (loc<id_loc) *q++=*loc++;
+ *q='\0';
+ }
+}
+
+@q Section 141->282/3. @>
+@* Make ministrings.
+ \.{CTWILL} needs the following procedure, which appends tokens of a
+translated text until coming to |tok_loc|, then suppresses text that may
+appear between parentheses or brackets. The calling routine |make_ministring|
+should set |ident_seen=false| first. (This is admittedly tricky.)
+
+@<Private var...@>=
+static boolean ident_seen;
+
+@ @c
+static boolean app_supp(
+ text_pointer p)
+{ token_pointer j;
+ if (ident_seen && **p>=tok_flag)
+ switch (**(**p-tok_flag+tok_start)) {
+ case '(': app('(');@+app('\\');@+app(',');@+app(')'); goto catch14;
+ case '[': app('[');@+app('\\');@+app(',');@+app(']'); goto catch14;
+ }
+ for (j=*p;j<*(p+1);j++) {
+ if (*j<tok_flag) {
+ if (*j==inserted) break;
+ if (j==tok_loc) ident_seen=true;
+ else app(*j);
+ } else if (*j>=inner_tok_flag) confusion(_("inner"));
+ else if (app_supp(*j-tok_flag+tok_start)) goto catch14;
+ }
+ return false;
+catch14: return *(*(p+1)-1)=='9'; /* was production 14 used? */
+}
+
+@q Section 284. @>
+@ @<Predec...@>=@+static boolean app_supp(text_pointer);
+
+@q Section 142->285. @>
+@ The trickiest part of \.{CTWILL} is the procedure |make_ministring(l)|,
+which tries to figure out a symbolic form of definition after
+|make_underlined(pp+l)| has been called. We rely heavily on the
+existing productions, which force the translated texts to have a
+structure that's decodable even though the underlying |cat| and |mathness|
+codes have disappeared.
+
+@c static void
+make_ministring(
+ int l) /* 0, 1, or 2 */
+{
+ name_pointer cn;
+ if (tok_loc<=operator_found) return;
+ cn=((*tok_loc)%id_flag)+name_dir;
+ @<Append the type of the declaree; |return| if it begins with \&{extern}@>@;
+ null_scrap.mathness=(((pp+l)->mathness)%4)*5; big_app1(&null_scrap);
+ /* now we're ready for the mathness that follows (I think);
+ (without the mod 4 times 5, comments posed a problem,
+ namely in cases like |int a(b,c)| followed by comment) */
+ ident_seen=false;@+app_supp((pp+l)->trans);
+ null_scrap.mathness=10; big_app1(&null_scrap);
+ /* now |cur_mathness==no_math| */
+ ms_mode=true; ministring_ptr=ministring_buf;
+ if (l==2) *ministring_ptr++='=';
+ make_output(); /* translate the current text into a ministring */
+ tok_ptr=*(--text_ptr); /* delete that text */
+ new_meaning(cn);
+ cur_mathness=maybe_math; /* restore it */
+}
+
+@q Section 286. @>
+@ @<Predec...@>=@+static void make_ministring(int);
+
+@q Section 43->287. @>
+@ @<Private...@>=
+static sixteen_bits int_loc, ext_loc; /* locations of special reserved words */
+
+@q Section 143->288. @>
+@ Here we use the fact that a |decl_head| comes from |int_like| only in
+production~27, whose translation is fairly easy to recognize. (Well,
+production 28 has been added for \CPLUSPLUS/, but we hope that doesn't
+mess us up.) And we also use other similar facts.
+
+If an identifier is given an \&{extern} definition, we don't change
+its current meaning, but we do suppress mini-index entries to its
+current meaning in other sections.
+
+@<Append the type of the declaree; |return| if it begins with \&{extern}@>=
+if (l==0) { app(int_loc+res_flag); app(' '); cur_mathness=no_math; }
+else {
+ text_pointer q=(pp+l-1)->trans, r;
+ token t;
+ int ast_count=0; /* asterisks preceding the expression */
+ boolean non_ast_seen=false; /* have we seen a non-asterisk? */
+ while (true) {
+ if (*(q+1)==*q+1) {
+ r=q;@+break; /* e.g. \&{struct}; we're doing production 45 or 46 */
+ }
+ if (**q<tok_flag) confusion(_("find type"));
+ r=**q-tok_flag+tok_start;
+ if ((t=*(*(q+1)-2))>=tok_flag && **(t-tok_flag+tok_start)=='*') {
+ /* production 34 */
+ if (!non_ast_seen) ast_count++; /* count immediately preceding |*|'s */
+ } else non_ast_seen=true;
+ if (*(*q+1)==' ' && *(q+1)==*q+2) break; /* production 27 */
+ if (*(*q+1)=='{' && *(*q+2)=='}' && *(*q+3)=='$' && *(*q+4)==' '@|
+ && *(q+1)==*q+5) break; /* production 27 in disguise */
+ q=r;
+ }
+ while (**r>=tok_flag) {
+ if (*(r+1)>*r+9 && *(*r+1)=='{' && *(*r+2)=='}' && *(*r+3)=='$' @|
+ && *(*r+4)==indent) q=**r-tok_flag+tok_start; /* production 49 */
+ r=**r-tok_flag+tok_start;
+ }
+ if (**r==ext_loc+res_flag) return; /* \&{extern} gives no definition */
+ @<Append tokens for type |q|@>@;
+}
+
+@q Section 144->289. @>
+@ @<Append tokens for type |q|@>=
+cur_mathness=no_math; /* it was |maybe_math| */
+if (*(q+1)==*q+8 && *(*q+1)==' ' && *(*q+3)==' ') {
+ app(**q);@+app(' ');@+app(*(*q+2)); /* production 46 */
+} else if ((t=*(*(q+1)-1))>=tok_flag && **(r=t-tok_flag+tok_start)=='\\'
+ && *(*r+1)=='{') app(**q); /* |struct_like| identifier */
+else app((q-tok_start)+tok_flag);
+while (ast_count) {
+ big_app('{');@+app('*');@+app('}');@+ast_count--;
+}
+
+@q Section 253->290. @>
+@ @<Private...@>=
+static boolean is_macro; /* it's a macro def, not a format def */
+static boolean def_diff; /* |false| iff the current macro has parameters */
+static name_pointer id_being_defined; /* the definee */
+
+@q Section 257->291. @>
+@ @<Make ministring for a new macro@>=
+{
+ ms_mode=true; ministring_ptr=ministring_buf;
+ *ministring_ptr++='=';
+ if (def_diff) { /* parameterless */
+ scrap_pointer s=scrap_ptr;
+ text_pointer t;
+ token_pointer j;
+ while (s->cat==insert) s--;
+ if ((s-1)->cat==dead && s->cat==exp && **(t=s->trans)=='\\'
+ && *(*t+1)=='T') /* it's just a constant */
+ for (j=*t;j<*(t+1);j++) *ministring_ptr++=*j;
+ else out_str("macro");
+ } else out_str("macro (\\,)");
+ new_meaning(id_being_defined);
+}
-\bigskip
-\font\itt=cmitt10
-{\noindent \it Although \.{\itt CTWILL} is based on \.{\itt cweave.w}, new and
-modified material is incorporated all over the place, without taking special
-care for keeping the original section numbering intact.}
+@q Section 246->292. @>
+@* Process {\tentex .aux} files.
+
+@<Private...@>=
+static FILE *aux_file;
+static char aux_file_name[max_file_name_length]; /* name of \.{.aux} file */
+
+@q Section 247->293. @>
+@ @<Read the \.{.aux} file, if present; then open it for output@>=
+memcpy(aux_file_name,tex_file_name,strlen(tex_file_name)-4);
+strcat(aux_file_name,".bux");
+include_depth=1; /* we simulate \.{@@i} */
+strcpy(cur_file_name,aux_file_name); /* first in, third out */
+if ((cur_file=fopen(cur_file_name,"r"))) { cur_line=0; include_depth++; }
+strcpy(aux_file_name+strlen(aux_file_name)-4,".aux");@/
+strcpy(cur_file_name,aux_file_name); /* second in, second out */
+if ((cur_file=fopen(cur_file_name,"r"))) { cur_line=0; include_depth++; }
+strcpy(cur_file_name,"system.bux"); /* third in, first out */
+if ((cur_file=fopen(cur_file_name,"r"))) cur_line=0;
+else include_depth--;
+if (include_depth) { /* at least one new file was opened */
+ while (get_next()==meaning) ; /* new meaning is digested */
+ if (include_depth) err_print(_("! Only @@$ is allowed in aux and bux files"));
+ finish_line(); loc=buffer; /* now reading beginning of line 1 */
+}
+if ((aux_file=fopen(aux_file_name,"wb"))==NULL)
+ fatal(_("! Cannot open aux output file "),aux_file_name);
+
+@q Section 31->294. @>
+@ @<Write the new meaning to the \.{.aux} file@>=
+{@+int n=q->perm.prog_no;
+ fprintf(aux_file,"@@$%.*s %.*s",@|
+ (int)length(p),p->byte_start,@|
+ (int)length(title_code[n]),title_code[n]->byte_start);
+ if (*(title_code[n]->byte_start)=='{') fprintf(aux_file,"%d",q->perm.sec_no);
+ fprintf(aux_file," %s@@>\n",q->perm.tex_part);
+}
+
+@q Section 268->295. @>
+@* Usage of identifiers.
+The following code is performed for each identifier parsed during
+a section. Variable |top_usage| is always nonzero; it has the sentinel
+value~1 initially, then it points to each variable scheduled for
+possible citation. A variable is on this list if and only if its
+|link| field is nonzero. All variables mentioned in the section are
+placed on the list, unless they are reserved and their current
+\TeX\ meaning is uninitialized.
+
+@<Flag the usage of this identifier, for the mini-index@>=
+{ struct perm_meaning *q=p-name_dir+cur_meaning;
+ if (!(abnormal(p)) || strcmp(q->perm.tex_part,"\\uninitialized")!=0)
+ if (q->link==NULL) {
+ q->link=top_usage;
+ top_usage=q;
+ }
+}
+
+@q Section 269->296. @>
+@ @<Output information about usage of id's defined in other sections@>=
+{ struct perm_meaning *q;
+ while (temp_meaning_ptr>temp_meaning_stack) {
+ out_mini(--temp_meaning_ptr);
+ q=temp_meaning_ptr->id-name_dir+cur_meaning;
+ q->stamp=section_count; /* suppress output from ``permanent'' data */
+ }
+ while (top_usage!=usage_sentinel) {
+ q=top_usage;
+ top_usage=q->link;
+ q->link=NULL;
+ if (q->stamp!=section_count) out_mini(&(q->perm));
+ }
+}
+
+@q Section 270->297. @>
+@ @c static void
+out_mini(
+ meaning_struct *m)
+{ char s[60];
+ name_pointer cur_name=m->id;
+ if (m->prog_no==0) { /* reference within current program */
+ if (m->sec_no==section_count) return; /* defined in current section */
+ sprintf(s,"\\[%d",m->sec_no);
+ } else { name_pointer n=title_code[m->prog_no];
+ if (*(n->byte_start)=='{')
+ sprintf(s,"\\]%.*s%d",(int)length(n),n->byte_start,m->sec_no);
+ else sprintf(s,"\\]%.*s",(int)length(n),n->byte_start);
+ }
+ out_str(s); out(' ');
+ @<Mini-output the name at |cur_name|@>@;
+ out(' '); out_str(m->tex_part); finish_line();
+}
+
+@q Section 271->298. @>
+@ @<Predec...@>=@+static void out_mini(meaning_struct *);
+
+@q Section 272->299. @>
+@ Compare this code with section |@<Output the name...@>|.
+
+@<Mini-output...@>=
+switch (cur_name->ilk) {@+char *j;
+ case normal: case func_template:
+ if (is_tiny(cur_name)) out_str("\\|");
+ else {
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ if (xislower(*j)) goto lowcase;
+ out_str("\\."); break;
+lowcase: out_str("\\\\");
+ }
+ break;
+@.\\|@>
+@.\\.@>
+@.\\\\@>
+ case wildcard: out_str("\\9"); break;
+@.\\9@>
+ case typewriter: out_str("\\.");
+@.\\.@>
+ case roman: break;
+ case custom:
+ out_str("$\\");
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ out(*j=='_'? 'x': *j=='$'? 'X': *j);
+ out('$');
+ goto name_done;
+ default: out_str("\\&");
+@.\\\&@>
+}
+out_name(cur_name,true);
+name_done:@;
+
+@q Section 28->300. @>
+@* Handle program title.
+Here's a routine that converts a program title from the buffer
+into an internal number for the |prog_no| field of a meaning.
+It advances |loc| past the title found.
+
+@c static sixteen_bits title_lookup(void)
+{
+ char *first=loc,*last; /* boundaries */
+ register name_pointer *p;
+ if (*loc=='"') {
+ while (++loc<=limit && *loc!='"') if (*loc=='\\') loc++;
+ } else if (*loc=='{') {
+ int balance=1; /* excess of left over right */
+ while (++loc<=limit) {
+ if (*loc==' ' && balance==1)
+ *loc='}'; /* Skip ``version'' after module name and fall through */
+ if (*loc=='}' && --balance==0) break;
+ if (*loc=='{') balance++;
+ }
+ } else err_print(_("! Title should be enclosed in braces or doublequotes"));
+ last=++loc;
+ if (last>limit) err_print(_("! Title name didn't end"));
+ if (title_code_ptr==&title_code[max_titles]) overflow(_("titles"));
+ *title_code_ptr=id_lookup(first,last,title);
+ for (p=title_code;true;p++) if (*p==*title_code_ptr) break;
+ if (p==title_code_ptr) title_code_ptr++;
+ return p-title_code;
+}
+
+@q Section 301. @>
+@ @<Predec...@>=@+static sixteen_bits title_lookup(void);
+
+@q Section 29->302. @>
+@ @<Give a default title to the program, if necessary@>=
+if (title_code_ptr==title_code) { /* no \.{\\def\\title} found in limbo */
+ char *saveloc=loc,*savelimit=limit; /* save */
+ loc=limit+1; limit=loc;
+ *limit++='{';
+ memcpy(limit,tex_file_name,strlen(tex_file_name)-4);
+ limit+=strlen(tex_file_name)-4;
+ *limit++='}';
+ title_lookup();@/
+ loc=saveloc; limit=savelimit; /* restore */
+}
+
+@q Section 303. @>
+@** Extensions to {\tentex CWEB}. The following sections introduce new or
+improved features that have been created by numerous contributors over the
+course of a quarter century.
@* Formatting alternatives.
-\.{CWEAVE} indents declarations after old-style function definitions.
-With the \.{-i} option they will come out flush left. You won't see
-any difference if you use ANSI-style function definitions.
+\.{CWEAVE} indents declarations after old-style function definitions and
+long parameter lists of modern function definitions.
+With the \.{-i} option they will come out flush left.
@d indent_param_decl flags['i'] /* should formal parameter declarations be indented? */
@@ -1940,14 +1949,13 @@ be found in the program \.{NUWEB} by Preston Briggs, to whom credit is due.
@<Update the result...@>=
if((tex_file=fopen(tex_file_name,"r"))!=NULL) {
- char x[BUFSIZ],y[BUFSIZ];
- int x_size,y_size,comparison=false;
+ boolean comparison=false;
if((check_file=fopen(check_file_name,"r"))==NULL)
fatal(_("! Cannot open output file "),check_file_name);
@.Cannot open output file@>
- if (temporary_output) @<Compare the temporary output...@>@;
+ if (check_for_change) @<Compare the temporary output...@>@;
fclose(tex_file); tex_file=NULL;
fclose(check_file); check_file=NULL;
@@ -1962,10 +1970,10 @@ strcpy(check_file_name,""); /* We want to get rid of the temporary file */
@<Compare the temporary output to the previous output@>=
do {
- x_size = fread(x,1,BUFSIZ,tex_file);
- y_size = fread(y,1,BUFSIZ,check_file);
- comparison = (x_size == y_size); /* Do not merge these statements! */
- if(comparison) comparison = !memcmp(x,y,x_size);
+ char x[BUFSIZ],y[BUFSIZ];
+ int x_size = fread(x,sizeof(char),BUFSIZ,tex_file);
+ int y_size = fread(y,sizeof(char),BUFSIZ,check_file);
+ comparison = (x_size == y_size) && !memcmp(x,y,x_size);
} while(comparison && !feof(tex_file) && !feof(check_file));
@ Note the superfluous call to |remove| before |rename|. We're using it to
@@ -1979,7 +1987,7 @@ else {
rename(check_file_name,tex_file_name);
}
-@* Put ``version'' information in \.{COMMON}.
+@* Print ``version'' information.
Don't do this at home, kids! Push our local macro to the variable in \.{COMMON}
for printing the |banner| and the |versionstring| from there.