summaryrefslogtreecommitdiff
path: root/web/c_cpp/cweb/cweave.w
diff options
context:
space:
mode:
Diffstat (limited to 'web/c_cpp/cweb/cweave.w')
-rw-r--r--web/c_cpp/cweb/cweave.w268
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);