diff options
Diffstat (limited to 'web/c_cpp/cweb/cweave.w')
-rw-r--r-- | web/c_cpp/cweb/cweave.w | 268 |
1 files changed, 133 insertions, 135 deletions
diff --git a/web/c_cpp/cweb/cweave.w b/web/c_cpp/cweb/cweave.w index 7de3b4d1d9..70654828c1 100644 --- a/web/c_cpp/cweb/cweave.w +++ b/web/c_cpp/cweb/cweave.w @@ -2,7 +2,7 @@ % This program by Silvio Levy and Donald E. Knuth % is based on a program by Knuth. % It is distributed WITHOUT ANY WARRANTY, express or implied. -% Version 4.8 --- June 2022 +% Version 4.10 --- August 2023 % Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth @@ -32,11 +32,11 @@ \def\skipxTeX{\\{skip\_\TEX/}} \def\copyxTeX{\\{copy\_\TEX/}} -\def\title{CWEAVE (Version 4.8)} +\def\title{CWEAVE (Version 4.10)} \def\topofcontents{\null\vfill \centerline{\titlefont The {\ttitlefont CWEAVE} processor} \vskip 15pt - \centerline{(Version 4.8)} + \centerline{(Version 4.10)} \vfill} \def\botofcontents{\vfill \noindent @@ -67,7 +67,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.8)" +@d banner "This is CWEAVE (Version 4.10)" @c @<Include files@>@/ @@ -100,7 +100,7 @@ char **av) /* argument values */ phase_one(); /* read all the user's text and store the cross-references */ phase_two(); /* read all the text again and translate it to \TEX/ form */ phase_three(); /* output the cross-reference index */ - if (tracing==fully && !show_progress) new_line; + if (tracing==fully && !show_progress) new_line(); return wrap_up(); /* and exit gracefully */ } @@ -111,13 +111,11 @@ possible changes from this \.{COMMON} interface consistently. @i common.h -@ The following parameters are sufficient to handle \TEX/ (converted to -\.{CWEB}), so they should be sufficient for most applications of \.{CWEAVE}. +@ \.{CWEAVE} will use the |INT_MAX| limit in section +|@<Output the code for the beginning...@>| below. -@d line_length 80 /* lines of \TEX/ output have at most this many characters; - should be less than 256 */ -@d max_refs 30000 /* number of cross-references; must be less than 65536 */ -@d max_scraps 5000 /* number of tokens in \CEE/ texts being parsed */ +@<Incl...@>= +#include <limits.h> @* Data structures exclusive to {\tt CWEAVE}. As explained in \.{common.w}, the field of a |name_info| structure @@ -147,7 +145,6 @@ identifiers are \CEE/ or \CPLUSPLUS/ reserved words whose |ilk| explains how they are to be treated when \CEE/ code is being formatted. -@d ilk dummy.Ilk @d normal 0 /* ordinary identifiers have |normal| ilk */ @d roman 1 /* normal index entries have |roman| ilk */ @d wildcard 2 /* user-formatted index entries have |wildcard| ilk */ @@ -217,7 +214,9 @@ typedef struct xref_info { } xref_info; typedef xref_info *xref_pointer; -@ @<Private...@>= +@ @d max_refs 30000 /* number of cross-references; must be less than 65536 */ + +@<Private...@>= static xref_info xmem[max_refs]; /* contains cross-reference information */ static xref_pointer xmem_end = xmem+max_refs-1; static xref_pointer xref_ptr; /* the largest occupied position in |xmem| */ @@ -242,7 +241,7 @@ to one-letter identifiers or \CEE/'s reserved words. If the user has sent the |no_xref| flag (the \.{-x} option of the command line), it is unnecessary to keep track of cross-references for identifiers. If one were careful, one could probably make more changes around section -115 to avoid a lot of identifier looking up. +|@<Match a prod...@>| to avoid a lot of identifier looking up. @d append_xref(c) if (xref_ptr==xmem_end) overflow("cross-reference"); else (++xref_ptr)->num=c @@ -355,7 +354,7 @@ tok_ptr=max_tok_ptr=tok_mem+1;@/ tok_start[0]=tok_start[1]=tok_mem+1;@/ text_ptr=max_text_ptr=tok_start+1; -@ Here are the three procedures needed to complete |id_lookup|: +@ Here are the two procedures needed to complete |id_lookup|: @c boolean names_match( name_pointer p, /* points to the proposed match */ @@ -369,14 +368,6 @@ eight_bits t) /* desired |ilk| */ } void -init_p( -name_pointer p, -eight_bits t) -{ - p->ilk=t; init_node(p); -} - -void init_node( name_pointer p) { @@ -923,7 +914,7 @@ convention, but do not allow the string to be longer than |longest_name|. fputs("\n! String too long: ",stdout); @.String too long@> term_write(section_text+1,25); - printf("..."); mark_error; + printf("..."); mark_error(); } id_loc++; return string; @@ -993,7 +984,7 @@ if (k>=section_text_end) { fputs("\n! Section name too long: ",stdout); @.Section name too long@> term_write(section_text+1,25); - printf("..."); mark_harmless; + printf("..."); mark_harmless(); } if (*k==' ' && k>section_text) k--; @@ -1087,7 +1078,7 @@ phase_one(void) { /* it will become |true| if any line changes */ if (*(loc-1)=='*' && show_progress) { printf("*%d",(int)section_count); - update_terminal; /* print a progress report */ + update_terminal(); /* print a progress report */ } @<Store cross-references in the \TEX/ part of a section@>@; @<Store cross-references in the definition part of a section@>@; @@ -1312,13 +1303,13 @@ name_pointer p) /* print anomalies in subtree |p| */ if ((an_output=(cur_xref->num==file_flag))==true) cur_xref=cur_xref->xlink; if (cur_xref->num <def_flag) { fputs("\n! Never defined: <",stdout); - print_section_name(p); putchar('>'); mark_harmless; + print_section_name(p); putchar('>'); mark_harmless(); @.Never defined: <section name>@> } while (cur_xref->num >=cite_flag) cur_xref=cur_xref->xlink; if (cur_xref==xmem && !an_output) { fputs("\n! Never used: <",stdout); - print_section_name(p); putchar('>'); mark_harmless; + print_section_name(p); putchar('>'); mark_harmless(); @.Never used: <section name>@> } section_check(p->rlink); @@ -1335,6 +1326,9 @@ characters long, so we place it into an output buffer. During the output process, |out_line| will hold the current line number of the line about to be output. +@d line_length 80 /* lines of \TEX/ output have at most this many characters; + should be less than 256 */ + @<Private...@>= static char out_buf[line_length+1]; /* assembled characters */ static char *out_buf_end = out_buf+line_length; /* end of |out_buf| */ @@ -1353,9 +1347,8 @@ carried over to the next line (so that \TEX/ will ignore the completion of commented-out text). @d c_line_write(c) fflush(active_file),fwrite(out_buf+1,sizeof(char),c,active_file) -@d tex_putc(c) putc(c,active_file) -@d tex_new_line putc('\n',active_file) @d tex_printf(c) fprintf(active_file,"%s",c) +@d tex_putc(c) fputc(c,active_file) @d tex_puts(c) fputs(c,active_file) @<Predecl...@>= @@ -1373,7 +1366,7 @@ boolean per_cent,boolean carryover) while (j>out_buf && *j==' ') j--; c_line_write(j-out_buf); if (per_cent) tex_putc('%'); - tex_new_line; out_line++; + tex_putc('\n'); out_line++; if (carryover) while (j>out_buf) if (*j--=='%' && (j==out_buf || *j!='\\')) { @@ -1443,8 +1436,8 @@ to overflow. To make this routine a little faster, we initialize position out_buf[0]='\\'; @ A long line is broken at a blank space or just before a backslash that isn't -preceded by another backslash. In the latter case, a |'%'| is output at -the break. +preceded by another backslash or a \TeX\ comment marker. In the latter case, a +|'%'| is output at the break. @c static void @@ -1456,7 +1449,7 @@ break_out(void) /* finds a way to break the output line */ if (*k==' ') { flush_buffer(k,false,true); return; } - if (*(k--)=='\\' && *k!='\\') { /* we've decreased |k| */ + if (*(k--)=='\\' && *k!='\\' && *k!='%') { /* we've decreased |k| */ flush_buffer(k,true,true); return; } } @@ -1472,7 +1465,7 @@ line by putting a |'%'| just before the last character. printf("\n! Line had to be broken (output l. %d):\n",out_line); @.Line had to be broken@> term_write(out_buf+1, out_ptr-out_buf-1); - new_line; mark_harmless; + new_line(); mark_harmless(); flush_buffer(out_ptr-1,true,true); return; } @@ -1491,7 +1484,7 @@ out_section( sixteen_bits n) { char s[6]; - sprintf(s,"%d",(int)n); out_str(s); + snprintf(s,6,"%d",(int)n); out_str(s); if (changed_section[n]) out_str("\\*"); @.\\*@> } @@ -1505,9 +1498,9 @@ out_name( name_pointer p, boolean quote_xalpha) { - char *k, *k_end=(p+1)->byte_start; /* pointers into |byte_mem| */ + char *k; /* pointer into |byte_mem| */ out('{'); - for (k=p->byte_start; k<k_end; k++) { + for (k=p->byte_start; k<(p+1)->byte_start; k++) { if (isxalpha(*k) && quote_xalpha) out('\\'); @.\\\$@> @.\\\_@> @@ -2124,7 +2117,8 @@ identifier&|exp|: \.{\\\\\{}identifier with underlines and \.{\\X}$n$\.:translated section name\.{\\X}&maybe\cr \.{@@(@q)@>}\thinspace section name\thinspace\.{@@>}&|section_scrap|: \.{\\X}$n$\.{:\\.\{}section name with special characters - quoted\.{\ \}\\X}&maybe\cr + quoted\.{\\,\}\\X}\footnote*{The \.{\\,} (thin space) is omitted + in ``|inner| \TeX\ mode.''}&maybe\cr \.{/*}\thinspace comment\thinspace\.{*/}&|insert|: |cancel| \.{\\C\{}translated comment\.\} |force|&no\cr \.{//}\thinspace comment&|insert|: |cancel| @@ -2169,6 +2163,8 @@ blanks that will not match in any productions. Parsing stops when Since the |scrap| structure will later be used for other purposes, we declare its second element as a union. +@d trans trans_plus.Trans /* translation texts of scraps */ + @<Type...@>= typedef struct { eight_bits cat; @@ -2180,7 +2176,7 @@ typedef struct { } scrap; typedef scrap *scrap_pointer; -@ @d trans trans_plus.Trans /* translation texts of scraps */ +@ @d max_scraps 5000 /* number of tokens in \CEE/ texts being parsed */ @<Private...@>= static scrap scrap_info[max_scraps]; /* memory array for scraps */ @@ -2219,9 +2215,18 @@ translated without line-break controls. @d tok_flag (4*id_flag) /* signifies a token list */ @d inner_tok_flag (5*id_flag) /* signifies a token list in `\pb' */ +@<Predecl...@>= +#ifdef DEBUG +static void print_text(text_pointer p); +#endif + +@ This function prints a token list for debugging; +it is not used in |main| at this time. + @c +#ifdef DEBUG static void -print_text( /* prints a token list for debugging; not used in |main| */ +print_text( text_pointer p) { token_pointer j; /* index into |tok_mem| */ @@ -2244,10 +2249,9 @@ text_pointer p) default: @<Print token |r| in symbolic form@>@; } } - update_terminal; + update_terminal(); } - -@ @<Predecl...@>=@+static void print_text(text_pointer p); +#endif /* |DEBUG| */ @ @<Print token |r|...@>= switch (r) { @@ -2360,9 +2364,9 @@ static int cur_mathness, init_mathness; understanding the format by comparing the code with the symbolic productions as they were listed earlier. -@d begin_math if (cur_mathness==maybe_math) init_mathness=yes_math; +@d begin_math() if (cur_mathness==maybe_math) init_mathness=yes_math; else if (cur_mathness==no_math) app_str("${}") -@d end_math if (cur_mathness==maybe_math) init_mathness=no_math; +@d end_math() if (cur_mathness==maybe_math) init_mathness=no_math; else if (cur_mathness==yes_math) app_str("{}$") @c @@ -2379,10 +2383,10 @@ token a) { if (a==' ' || (a>=big_cancel && a<=big_force) || a==dindent) /* non-math token */ { - end_math; + end_math(); cur_mathness=no_math; } else { - begin_math; + begin_math(); cur_mathness=yes_math; } app(a); @@ -2394,11 +2398,11 @@ scrap_pointer a) { switch (a->mathness % 4) { /* left boundary */ case (no_math): - end_math; + end_math(); cur_mathness=a->mathness / 4; /* right boundary */ break; case (yes_math): - begin_math; + begin_math(); cur_mathness=a->mathness / 4; /* right boundary */ break; case (maybe_math): /* no changes */ break; @@ -3184,7 +3188,7 @@ current token list is empty and ready to be appended~to. Note that |freeze_text| does not check to see that |text_ptr| hasn't gotten too large, since it is assumed that this test was done beforehand. -@d freeze_text *(++text_ptr)=tok_ptr +@d freeze_text() *(++text_ptr)=tok_ptr @<Predecl...@>= static void reduce(scrap_pointer,short,eight_bits,short,short);@/ @@ -3205,7 +3209,7 @@ short d, short n) if (k>0) { j->trans=text_ptr; j->mathness=4*cur_mathness+init_mathness; - freeze_text; + freeze_text(); } if (k>1) { for (i=j+k, i1=j+1; i<=lo_ptr; i++, i1++) { @@ -3348,13 +3352,13 @@ for (j=scrap_base; j<=lo_ptr; j++) { if (j->mathness / 4 == yes_math) app('$'); if (tok_ptr+6>tok_mem_end) overflow("token"); } -freeze_text; return text_ptr-1; +freeze_text(); return text_ptr-1; @ @<If semi-tracing, show the irreducible scraps@>= if (lo_ptr>scrap_base && tracing==partly) { printf("\nIrreducible scrap sequence in section %d:",(int)section_count); @.Irreducible scrap sequence...@> - mark_harmless; + mark_harmless(); for (j=scrap_base; j<=lo_ptr; j++) { putchar(' '); print_cat(j->cat); } @@ -3362,7 +3366,7 @@ if (lo_ptr>scrap_base && tracing==partly) { @ @<If tracing,...@>= if (tracing==fully) { - printf("\nTracing after l. %d:\n",cur_line); mark_harmless; + printf("\nTracing after l. %d:\n",cur_line); mark_harmless(); @.Tracing after...@> if (loc>buffer+50) { printf("..."); @@ -3407,7 +3411,7 @@ been appended: @d app_scrap(c,b) { (++scrap_ptr)->cat=(c); scrap_ptr->trans=text_ptr; scrap_ptr->mathness=5*(b); /* no no, yes yes, or maybe maybe */ - freeze_text; + freeze_text(); } @ @<Append the scr...@>= @@ -3705,7 +3709,7 @@ outer_parse(void) /* makes scraps from \CEE/ tokens and comments */ @.\\SHC@> bal=copy_comment(is_long_comment,1); next_control=ignore; while (bal>0) { - p=text_ptr; freeze_text; q=C_translate(); + p=text_ptr; freeze_text(); q=C_translate(); /* at this point we have |tok_ptr+6<=max_toks| */ app(tok_flag+(int)(p-tok_start)); if (make_pb) app_str("\\PB{"); @@ -3753,8 +3757,8 @@ on a particular level will be read; \yskip\hang |mode_field| is the current mode, either |inner| or |outer|. \yskip\noindent The current values of these quantities are referred to -quite frequently, so they are stored in a separate place instead of in the -|stack| array. We call the current values |cur_end|, |cur_tok|, and +quite frequently, so they are stored in an extra slot at the very end of +the |stack| array. We call the current values |cur_end|, |cur_tok|, and |cur_mode|. The global variable |stack_ptr| tells how many levels of output are @@ -3762,26 +3766,28 @@ currently in progress. The end of output occurs when an |end_translation| token is found, so the stack is never empty except when we first begin the output process. -@d inner false /* value of |mode| for \CEE/ texts within \TEX/ texts */ -@d outer true /* value of |mode| for \CEE/ texts in sections */ - -@<Typed...@>= typedef int mode; +@s mode int +@<Typed...@>= +typedef enum { + @!inner, /* value of |mode| for \CEE/ texts within \TEX/ texts */ + @!outer /* value of |mode| for \CEE/ texts in sections */ +} mode; typedef struct { token_pointer end_field; /* ending location of token list */ token_pointer tok_field; /* present location within token list */ - boolean mode_field; /* interpretation of control tokens */ + mode mode_field; /* interpretation of control tokens */ } output_state; typedef output_state *stack_pointer; @ @d stack_size 2000 /* number of simultaneous output levels */ +@d cur_state stack[stack_size] /* |cur_end|, |cur_tok|, |cur_mode| */ @d cur_end cur_state.end_field /* current ending location in |tok_mem| */ @d cur_tok cur_state.tok_field /* location of next output token in |tok_mem| */ @d cur_mode cur_state.mode_field /* current mode of interpretation */ -@d init_stack stack_ptr=stack;cur_mode=outer /* initialize the stack */ +@d init_stack() stack_ptr=stack;cur_mode=outer /* initialize the stack */ @<Private...@>= -static output_state cur_state; /* |cur_end|, |cur_tok|, |cur_mode| */ -static output_state stack[stack_size]; /* info for non-current levels */ +static output_state stack[stack_size+1]; /* info for non-current levels */ static stack_pointer stack_end=stack+stack_size-1; /* end of |stack| */ static stack_pointer stack_ptr; /* first unused location in the output state stack */ static stack_pointer max_stack_ptr; /* largest value assumed by |stack_ptr| */ @@ -3789,25 +3795,21 @@ static stack_pointer max_stack_ptr; /* largest value assumed by |stack_ptr| */ @ @<Set init...@>= max_stack_ptr=stack; +@ @<Predecl...@>= +static void push_level(text_pointer); + @ To insert token-list |p| into the output, the |push_level| subroutine is called; it saves the old level of output and gets a new one going. The value of |cur_mode| is not changed. -@<Predecl...@>= -static void push_level(text_pointer);@/ -static void pop_level(void); - -@ @c +@c static void push_level( /* suspends the current level */ text_pointer p) { if (stack_ptr==stack_end) overflow("stack"); - if (stack_ptr>stack) { /* save current state */ - stack_ptr->end_field=cur_end; - stack_ptr->tok_field=cur_tok; - stack_ptr->mode_field=cur_mode; - } + if (stack_ptr>stack) /* save current state */ + *stack_ptr = cur_state;@^system dependencies@> stack_ptr++; if (stack_ptr>max_stack_ptr) max_stack_ptr=stack_ptr; cur_tok=*p; cur_end=*(p+1); @@ -3815,15 +3817,9 @@ text_pointer p) @ Conversely, the |pop_level| routine restores the conditions that were in force when the current level was begun. This subroutine will never be -called when |stack_ptr==1|. +called when |stack_ptr==1|. It is so simple, we declare it as a macro: -@c -static void -pop_level(void) -{ - cur_end=(--stack_ptr)->end_field; - cur_tok=stack_ptr->tok_field; cur_mode=stack_ptr->mode_field; -} +@d pop_level() cur_state = *(--stack_ptr)@^system dependencies@> @ The |get_output| function returns the next byte of output that is not a reference to a token list. It returns the values |identifier| or |res_word| @@ -3891,10 +3887,10 @@ output_C(void) /* outputs the current token list */ text_pointer p; /* translation of the \CEE/ text */ next_control=ignore; p=C_translate(); app(inner_tok_flag+(int)(p-tok_start)); - if (make_pb) { - out_str("\\PB{"); make_output(); out('}'); + if (make_pb) out_str("\\PB{"); @.\\PB@> - }@+else make_output(); /* output the list */ + make_output(); /* output the list */ + if (make_pb) out('}'); if (text_ptr>max_text_ptr) max_text_ptr=text_ptr; if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr; text_ptr=save_text_ptr; tok_ptr=save_tok_ptr; /* forget the tokens */ @@ -3920,7 +3916,7 @@ make_output(void) /* outputs the equivalents of tokens */ boolean save_mode; /* value of |cur_mode| before a sequence of breaks */ boolean dindent_pending=false; /* should a |dindent| be output? */ app(end_translation); /* append a sentinel */ - freeze_text; push_level(text_ptr-1); + freeze_text(); push_level(text_ptr-1); while (true) { a=get_output(); reswitch: switch(a) { @@ -4093,7 +4089,7 @@ out(':'); if (an_output) out_str("\\.{"@q}@>); @.\\.@> @<Output the text of the section name@>@; -if (an_output) out_str(@q{@>" }"); +if (an_output) cur_mode==inner?out_str(@q{@>"}"):out_str(@q{@>"\\,}"); out_str("\\X"); @ @<Output the text...@>= @@ -4136,7 +4132,7 @@ while (k<k_limit) { if (*k++!='@@') { fputs("\n! Illegal control code in section name: <",stdout); @.Illegal control code...@> - print_section_name(cur_section_name); printf("> "); mark_error; + print_section_name(cur_section_name); printf("> "); mark_error(); } @ The \CEE/ text enclosed in \pb\ should not contain `\.{\v}' characters, @@ -4151,7 +4147,7 @@ while (true) { if (k>=k_limit) { fputs("\n! C text in section name didn't end: <",stdout); @.C text...didn't end@> - print_section_name(cur_section_name); printf("> "); mark_error; break; + print_section_name(cur_section_name); printf("> "); mark_error(); break; } b=*(k++); if (b=='@@' || (b=='\\' && delim!=0)) @@ -4202,8 +4198,8 @@ within a single section. The variables |out_line| or |out_ptr| will change if a section is non-null, so the following macros `|save_position|' and `|emit_space_if_needed|' are able to handle the situation: -@d save_position save_line=out_line; save_place=out_ptr -@d emit_space_if_needed if (save_line!=out_line || save_place!=out_ptr) +@d save_position() save_line=out_line; save_place=out_ptr +@d emit_space_if_needed() if (save_line!=out_line || save_place!=out_ptr) out_str("\\Y"); space_checked=true; @.\\Y@> @@ -4220,7 +4216,7 @@ static boolean group_found=false; /* has a starred section occurred? */ @ @<Translate the current section@>= { section_count++; @<Output the code for the beginning of a new section@>@; - save_position; + save_position(); @<Translate the \TEX/ part of the current section@>@; @<Translate the definition part of the current section@>@; @<Translate the \CEE/ part of the current section@>@; @@ -4245,16 +4241,16 @@ else { loc++; } else { - for (sec_depth=0; xisdigit(*loc);loc++) - sec_depth = sec_depth*10 + (*loc) -'0'; + for (sec_depth=0; xisdigit(*loc);loc++)@^system dependencies@> + if (sec_depth < INT_MAX / 10) sec_depth = sec_depth*10 + (*loc) -'0'; } while (*loc == ' ') loc++; /* remove spaces before group title */ group_found=true; out_str("\\N"); @.\\N@> - {@+ char s[32];@+sprintf(s,"{%d}",sec_depth+1);@+out_str(s);@+} + {@+ char s[32];@+snprintf(s,32,"{%d}",sec_depth+1);@+out_str(s);@+} if (show_progress) - printf("*%d",(int)section_count); update_terminal; /* print a progress report */ + printf("*%d",(int)section_count); update_terminal(); /* print a progress report */ } out('{'); out_section(section_count); out('}'); @@ -4263,7 +4259,7 @@ index entries are not copied and \CEE/ text within \pb\ is translated. @<Translate the \T...@>= do switch (next_control=copy_TeX()) { - case '|': init_stack; output_C(); break; + case '|': init_stack(); output_C(); break; case '@@': out('@@'); break; case TeX_string: case noop: case xref_roman: case xref_wildcard: case xref_typewriter: @@ -4286,7 +4282,7 @@ the token memory is in its initial empty state. @<Translate the d...@>= space_checked=false; while (next_control<=definition) { /* |format_code| or |definition| */ - init_stack; + init_stack(); if (next_control==definition) @<Start a macro definition@>@; else @<Start a format definition@>@; outer_parse(); finish_C(format_visible); format_visible=true; @@ -4343,16 +4339,15 @@ it starts after we scan the matching `\.)'. @<Start a macro...@>= { if (save_line!=out_line || save_place!=out_ptr || space_checked) app(backup); - if(!space_checked){emit_space_if_needed;save_position;} + if(!space_checked){emit_space_if_needed();save_position();} app_str("\\D"); /* this will produce `\#\&{define }' */ @.\\D@> if ((next_control=get_next())!=identifier) err_print("! Improper macro definition"); @.Improper macro definition@> else { - app_cur_id(false); + app('$'); app_cur_id(false); if (*loc=='(') { - app('$'); reswitch: switch (next_control=get_next()) { case '(': case ',': app(next_control); goto reswitch; case identifier: app_cur_id(false); goto reswitch; @@ -4364,10 +4359,9 @@ it starts after we scan the matching `\.)'. } @=/* otherwise fall through */@>@; default: err_print("! Improper macro definition"); break; } - app('$'); } else next_control=get_next(); - app(break_space); + app_str("$ "); app(break_space); app_scrap(dead,no_math); /* scrap won't take part in the parsing */ } } @@ -4375,7 +4369,7 @@ it starts after we scan the matching `\.)'. @ @<Start a format...@>= { doing_format=true; if(*(loc-1)=='s' || *(loc-1)=='S') format_visible=false; - if(!space_checked){emit_space_if_needed;save_position;} + if(!space_checked){emit_space_if_needed();save_position();} app_str("\\F"); /* this will produce `\&{format }' */ @.\\F@> next_control=get_next(); @@ -4403,7 +4397,7 @@ static name_pointer this_section; /* the current section name, or zero */ @ @<Translate the \CEE/...@>= this_section=name_dir; if (next_control<=section_name) { - emit_space_if_needed; init_stack; + emit_space_if_needed(); init_stack(); if (next_control==begin_C) next_control=get_next(); else { this_section=cur_section; @@ -4531,46 +4525,50 @@ contents. @c static void phase_three(void) { -if (no_xref) { - finish_line(); +phase=3; +finish_line(); /* the bulk of |tex_file| has been written */ +if (no_xref) out_str("\\end"); @.\\end@> - finish_line(); -} else { - phase=3; if (show_progress) fputs("\nWriting the index...",stdout); + if (show_progress) fputs("\nWriting the index...",stdout); @.Writing the index...@> - finish_line(); - if ((idx_file=fopen(idx_file_name,"wb"))==NULL) - fatal("! Cannot open index file ",idx_file_name); -@.Cannot open index file@> if (change_exists) { - @<Tell about changed sections@>@; finish_line(); finish_line(); + @<Tell about changed sections@>@; + finish_line(); flush_buffer(out_buf,false,false); + /* insert a blank line, it looks nice */ } out_str("\\inx"); finish_line(); @.\\inx@> +@# + if ((idx_file=fopen(idx_file_name,"wb"))==NULL) + fatal("! Cannot open index file ",idx_file_name); +@.Cannot open index file@> active_file=idx_file; /* change active file to the index file */ @<Do the first pass of sorting@>@; @<Sort and output the index@>@; finish_line(); fclose(active_file); /* finished with |idx_file| */ +@# active_file=tex_file; /* switch back to |tex_file| for a tic */ out_str("\\fin"); finish_line(); @.\\fin@> +@# if ((scn_file=fopen(scn_file_name,"wb"))==NULL) fatal("! Cannot open section file ",scn_file_name); @.Cannot open section file@> active_file=scn_file; /* change active file to section listing file */ @<Output all the section names@>@; finish_line(); fclose(active_file); /* finished with |scn_file| */ - active_file=tex_file; +@# + active_file=tex_file; /* switch back to |tex_file| for the last time */ if (group_found) out_str("\\con");@+else out_str("\\end"); @.\\con@> @.\\end@> - finish_line(); - fclose(active_file); } +finish_line(); +fclose(active_file); if (show_happiness) { - if (show_progress) new_line; + if (show_progress) new_line(); fputs("Done.",stdout); } check_complete(); /* was all of the change file used? */ @@ -4671,7 +4669,7 @@ needs to be changed if ASCII code is not being used. @^high-bit character handling@> We initialize |collate| by copying a few characters at a time, because -some \CEE/ compilers choke on long strings. +some \CEE/ compilers choke on long strings.@^system dependencies@> @<Set init...@>= collate[0]=0; @@ -4778,14 +4776,15 @@ while (sort_ptr>scrap_info) { } @ @<Output the name...@>= -switch (cur_name->ilk) {@+char *j;@+@t}\6{\4@> +switch (cur_name->ilk) {@+char *p; /* index into |byte_mem| */@+@t}\6{\4@> 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("\\\\"); + else {@+boolean all_caps=true;@+@t}\6{@> + for (p=cur_name->byte_start;p<(cur_name+1)->byte_start;p++) + if (xislower(*p)) { /* not entirely uppercase */ + all_caps=false; break; + } + out_str(all_caps ? "\\." : "\\\\"); } break; @.\\|@> @@ -4793,14 +4792,13 @@ lowcase: out_str("\\\\"); @.\\\\@> case wildcard: out_str("\\9");@+ goto not_an_identifier; @.\\9@> - case typewriter: out_str("\\."); - @=/* fall through */@>@; + case typewriter: out_str("\\.");@+ goto not_an_identifier; @.\\.@> case roman: not_an_identifier: out_name(cur_name,false); goto name_done; case custom: out_str("$\\"); - for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++) - out(*j=='_'? 'x': *j=='$'? 'X': *j); + for (p=cur_name->byte_start;p<(cur_name+1)->byte_start;p++) + out(*p=='_'? 'x': *p=='$'? 'X': *p); out('$'); goto name_done; default: out_str("\\&"); @@ -4850,7 +4848,7 @@ name_pointer p) if (p) { section_print(p->llink); out_str("\\I"); @.\\I@> - tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info; init_stack; + tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info; init_stack(); app(section_flag+(int)(p-name_dir)); make_output(); footnote(cite_flag); footnote(0); /* |cur_xref| was set by |make_output| */ @@ -4871,7 +4869,7 @@ void print_stats(void) { puts("\nMemory usage statistics:"); @.Memory usage statistics:@> - printf("%td names (out of %ld)\n", + printf("%td names (out of %ld)\n",@^system dependencies@> (ptrdiff_t)(name_ptr-name_dir),(long)max_names); printf("%td cross-references (out of %ld)\n", (ptrdiff_t)(xref_ptr-xmem),(long)max_refs); |