summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/cwebdir/ctwill-w2c.ch
diff options
context:
space:
mode:
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.