summaryrefslogtreecommitdiff
path: root/web/c_cpp/cweb/ctangle.w
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2023-08-20 03:01:12 +0000
committerNorbert Preining <norbert@preining.info>2023-08-20 03:01:12 +0000
commit53b22757814343c6071be2e64dc0639f7afc5468 (patch)
tree17c8c7a1bd1da7c2f985ce7bfeffb21cc8e1cf3f /web/c_cpp/cweb/ctangle.w
parenta953fdb33424be714f17f4d46f05712637bd0c3a (diff)
CTAN sync 202308200301
Diffstat (limited to 'web/c_cpp/cweb/ctangle.w')
-rw-r--r--web/c_cpp/cweb/ctangle.w128
1 files changed, 56 insertions, 72 deletions
diff --git a/web/c_cpp/cweb/ctangle.w b/web/c_cpp/cweb/ctangle.w
index 0c372e59ed..c8ae55df85 100644
--- a/web/c_cpp/cweb/ctangle.w
+++ b/web/c_cpp/cweb/ctangle.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
@@ -27,11 +27,11 @@
\mathchardef\RA="3221 % right arrow
\mathchardef\BA="3224 % double arrow
-\def\title{CTANGLE (Version 4.8)}
+\def\title{CTANGLE (Version 4.10)}
\def\topofcontents{\null\vfill
\centerline{\titlefont The {\ttitlefont CTANGLE} processor}
\vskip 15pt
- \centerline{(Version 4.8)}
+ \centerline{(Version 4.10)}
\vfill}
\def\botofcontents{\vfill
\noindent
@@ -61,7 +61,7 @@ Joachim Schrod, Lee Wittenberg, and others who have contributed improvements.
The ``banner line'' defined here should be changed whenever \.{CTANGLE}
is modified.
-@d banner "This is CTANGLE (Version 4.8)"
+@d banner "This is CTANGLE (Version 4.10)"
@c
@<Include files@>@/
@@ -162,10 +162,8 @@ eight_bits t) /* not used by \.{CTANGLE} */
return length(p)==l && strncmp(first,p->byte_start,l)==0;
}
-@ The common lookup routine refers to separate routines |init_node| and
-|init_p| when the data structure grows. Actually |init_p| is called only by
-\.{CWEAVE}, but we need to declare a dummy version so that
-the loader won't complain of its absence.
+@ The common lookup routine |id_lookup| refers to a separate routine
+|init_node| when the data structure grows.
@c
void
@@ -174,8 +172,6 @@ name_pointer node)
{
node->equiv=(void *)text_info;
}
-void
-init_p(name_pointer p,eight_bits t) {@+(void)p;@+(void)t;@+}
@* Tokens.
Replacement texts, which represent \CEE/ code in a compressed format,
@@ -247,13 +243,10 @@ sixteen_bits x)
@** Stacks for output. The output process uses a stack to keep track
of what is going on at different ``levels'' as the sections are being
-written out. Entries on this stack have five parts:
-
-\yskip\hang |end_field| is the |tok_mem| location where the replacement
-text of a particular level will end;
+written out. Entries on this stack have four parts:
-\hang |byte_field| is the |tok_mem| location from which the next token
-on a particular level will be read;
+\yskip\hang |byte_field| is the |tok_mem| location from which the next
+token on a particular level will be read;
\hang |name_field| points to the name corresponding to a particular level;
@@ -262,10 +255,10 @@ at a particular level;
\hang |section_field| is the section number, or zero if this is a macro.
-\yskip\noindent The current values of these five 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_byte|,
-|cur_name|, |cur_repl|, and |cur_section|.
+\yskip\noindent The current values of these four quantities are referred to
+quite frequently, so they are stored in an extra slot at the very end of the
+|stack| array. We call the current values |cur_byte|, |cur_name|, |cur_repl|,
+and |cur_section|.
The global variable |stack_ptr| tells how many levels of output are
currently in progress. The end of all output occurs when the stack is
@@ -273,7 +266,6 @@ empty, i.e., when |stack_ptr==stack|.
@<Typed...@>=
typedef struct {
- eight_bits *end_field; /* ending location of replacement text */
eight_bits *byte_field; /* present location within replacement text */
name_pointer name_field; /* |byte_start| index for text being output */
text_pointer repl_field; /* |tok_start| index for text being output */
@@ -282,16 +274,16 @@ typedef struct {
typedef output_state *stack_pointer;
@ @d stack_size 50 /* number of simultaneous levels of macro expansion */
-@d cur_end cur_state.end_field /* current ending location in |tok_mem| */
+@d cur_state stack[stack_size+1] /* |cur_byte|, |cur_name|, |cur_repl|,
+ and |cur_section| */
@d cur_byte cur_state.byte_field /* location of next output byte in |tok_mem|*/
@d cur_name cur_state.name_field /* pointer to current name being expanded */
@d cur_repl cur_state.repl_field /* pointer to current replacement text */
@d cur_section cur_state.section_field /* current section number being expanded */
+@d cur_end (cur_repl+1)->tok_start /* current ending location in |tok_mem| */
@<Private...@>=
-static output_state cur_state; /* |cur_end|, |cur_byte|, |cur_name|, |cur_repl|,
- and |cur_section| */
-static output_state stack[stack_size+1]; /* info for non-current levels */
+static output_state stack[stack_size+2]; /* info for non-current levels */
static stack_pointer stack_end=stack+stack_size; /* end of |stack| */
static stack_pointer stack_ptr; /* first unused location in the output state stack */
@@ -303,7 +295,7 @@ error message will have been generated before we do any of the initialization.
@<Initialize the output stacks@>=
stack_ptr=stack+1; cur_name=name_dir; cur_repl=text_info->text_link+text_info;
-cur_byte=cur_repl->tok_start; cur_end=(cur_repl+1)->tok_start; cur_section=0;
+cur_byte=cur_repl->tok_start; cur_section=0;
@ When the replacement text for name |p| is to be inserted into the output,
the following subroutine is called to save the old level of output and get
@@ -322,8 +314,7 @@ name_pointer p)
stack_ptr++;
if (p!=NULL) { /* |p==NULL| means we are in |output_defs| */
cur_name=p; cur_repl=(text_pointer)p->equiv;
- cur_byte=cur_repl->tok_start; cur_end=(cur_repl+1)->tok_start;
- cur_section=0;
+ cur_byte=cur_repl->tok_start; cur_section=0;
}
}
@@ -342,11 +333,10 @@ boolean flag) /* |flag==false| means we are in |output_defs| */
{
if (flag && cur_repl->text_link<section_flag) { /* link to a continuation */
cur_repl=cur_repl->text_link+text_info; /* stay on the same level */
- cur_byte=cur_repl->tok_start; cur_end=(cur_repl+1)->tok_start;
- return;
+ cur_byte=cur_repl->tok_start; return;
}
stack_ptr--; /* go down to the previous level */
- if (stack_ptr>stack) cur_state=*stack_ptr;
+ if (stack_ptr>stack) cur_state=*stack_ptr;@^system dependencies@>
}
@ The heart of the output procedure is the function |get_output|,
@@ -472,7 +462,7 @@ flush_buffer(void) /* writes one line to output file */
if (cur_line % 100 == 0 && show_progress) {
putchar('.');
if (cur_line % 500 == 0) printf("%d",cur_line);
- update_terminal; /* progress report */
+ update_terminal(); /* progress report */
}
cur_line++;
}
@@ -525,30 +515,24 @@ phase_two (void) {
@<Initialize the output stacks@>@;
@<Output macro definitions if appropriate@>@;
if (text_info->text_link==macro && cur_out_file==end_output_files) {
- fputs("\n! No program text was specified.",stdout); mark_harmless;
+ fputs("\n! No program text was specified.",stdout); mark_harmless();
@.No program text...@>
}
else {
- if (cur_out_file==end_output_files) {
- if (show_progress) {
- printf("\nWriting the output file (%s):",C_file_name);
- update_terminal;
- }
- }
- else {
- if (show_progress) {
- fputs("\nWriting the output files:",stdout);
+ if (show_progress) {
+ printf(cur_out_file==end_output_files ? @|
+ "\nWriting the output file (%s):" : @|
+ "\nWriting the output files: (%s)",C_file_name);
@.Writing the output...@>
- printf(" (%s)",C_file_name);
- update_terminal;
- }
- if (text_info->text_link==macro) goto writeloop;
+ update_terminal();
}
- while (stack_ptr>stack) get_output();
- flush_buffer();
-writeloop: @<Write all the named output files@>@;
+ if (text_info->text_link!=macro) {
+ while (stack_ptr>stack) get_output();
+ flush_buffer();
+ }
+ @<Write all the named output files@>@;
if (show_happiness) {
- if (show_progress) new_line;
+ if (show_progress) new_line();
fputs("Done.",stdout);
}
}
@@ -568,13 +552,12 @@ for (an_output_file=end_output_files; an_output_file>cur_out_file;) {
if ((C_file=fopen(output_file_name,"wb"))==NULL)
fatal("! Cannot open output file ",output_file_name);
@.Cannot open output file@>
- if (show_progress) { printf("\n(%s)",output_file_name); update_terminal; }
+ if (show_progress) { printf("\n(%s)",output_file_name); update_terminal(); }
cur_line=1;
stack_ptr=stack+1;
cur_name=*an_output_file;
cur_repl=(text_pointer)cur_name->equiv;
cur_byte=cur_repl->tok_start;
- cur_end=(cur_repl+1)->tok_start;
while (stack_ptr > stack) get_output();
flush_buffer();
}
@@ -594,8 +577,10 @@ static boolean output_defs_seen=false;
static void output_defs(void);@/
static void out_char(eight_bits);
-@ @d C_printf(c,a) fprintf(C_file,c,a)
-@d C_putc(c) putc((int)(c),C_file) /* isn't \CEE/ wonderfully consistent? */
+@ @d macro_end (cur_text+1)->tok_start /* end of |macro| replacement text */
+@#
+@d C_printf(c,a) fprintf(C_file,c,a)
+@d C_putc(c) fputc((int)(c),C_file) /* isn't \CEE/ wonderfully consistent? */
@c
static void
@@ -606,13 +591,12 @@ output_defs(void)
for (cur_text=text_info+1; cur_text<text_ptr; cur_text++)
if (cur_text->text_link==macro) { /* |cur_text| is the text for a |macro| */
cur_byte=cur_text->tok_start;
- cur_end=(cur_text+1)->tok_start;
C_printf("%s","#define ");
out_state=normal;
protect=true; /* newlines should be preceded by |'\\'| */
- while (cur_byte<cur_end) {
+ while (cur_byte<macro_end) {
a=*cur_byte++;
- if (cur_byte==cur_end && a=='\n') break; /* disregard a final newline */
+ if (cur_byte==macro_end && a=='\n') break; /* disregard a final newline */
if (out_state==verbatim && a!=string && a!=constant && a!='\n')
C_putc(a); /* a high-bit character can occur in a string */
@^high-bit character handling@>
@@ -646,7 +630,7 @@ static void
out_char(
eight_bits cur_char)
{
- char *j, *k; /* pointer into |byte_mem| */
+ char *j; /* pointer into |byte_mem| */
restart:
switch (cur_char) {
case '\n': if (protect && out_state!=verbatim) C_putc(' ');
@@ -690,8 +674,8 @@ case period_ast: C_putc('.');@+C_putc('*'); out_state=normal; break;
case minus_gt_ast: C_putc('-');@+C_putc('>');@+C_putc('*'); out_state=normal;
break;
-@ When an identifier is output to the \CEE/ file, characters in the
-range 128--255 must be changed into something else, so the \CEE/
+@ When an identifier is output to the \CEE/ file, characters in the range
+128--255 (|0200|--|0377|) must be changed into something else, so the \CEE/
compiler won't complain. By default, \.{CTANGLE} converts the
character with code $16 x+y$ to the three characters `\.X$xy$', but
a different transliteration table can be specified. Thus a German
@@ -701,19 +685,19 @@ This makes debugging a lot less confusing.
@d translit_length 10
@<Private...@>=
-static char translit[128][translit_length];
+static char translit[0200][translit_length];
@ @<Set init...@>=
-{
- int i;
- for (i=0;i<128;i++) sprintf(translit[i],"X%02X",(unsigned int)(128+i));
+{ int i;
+ for (i=0;i<0200;i++)
+ snprintf(translit[i],translit_length,"X%02X",(unsigned int)(0200+i));
}
@ @<Case of an identifier@>=@t\1\quad@>
case identifier:
if (out_state==num_or_id) C_putc(' ');
- for (j=(cur_val+name_dir)->byte_start, k=(cur_val+name_dir+1)->byte_start;
- j<k; j++)
+ for (j=(cur_val+name_dir)->byte_start;
+ j<(cur_val+name_dir+1)->byte_start; j++)
if ((eight_bits)(*j)<0200) C_putc(*j);
@^high-bit character handling@>
else C_printf("%s",translit[(eight_bits)(*j)-0200]);
@@ -735,8 +719,8 @@ case section_number:
@:line}{\.{\#line}@>
cur_val=(int)(*cur_byte++-0200)*0400;
cur_val+=*cur_byte++; /* points to the file name */
- for (j=(cur_val+name_dir)->byte_start, k=(cur_val+name_dir+1)->byte_start;
- j<k; j++) {
+ for (j=(cur_val+name_dir)->byte_start;
+ j<(cur_val+name_dir+1)->byte_start; j++) {
if (*j=='\\' || *j=='"') C_putc('\\');
C_putc(*j);
}
@@ -1132,7 +1116,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--;
@@ -1384,7 +1368,7 @@ scan_section(void)
sixteen_bits a; /* token for left-hand side of definition */
section_count++; @+ no_where=true;
if (*(loc-1)=='*' && show_progress) { /* starred section */
- printf("*%d",(int)section_count); update_terminal;
+ printf("*%d",(int)section_count); update_terminal();
}
next_control=ignore;
while (true) {
@@ -1533,7 +1517,7 @@ skip_limbo(void)
sscanf(loc-3,"%x",&i);
while(xisspace(*loc)&&loc<limit) loc++;
beg=loc;
- while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||*loc=='_')) loc++;
+ while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||isxalpha(*loc))) loc++;
if (loc-beg>=translit_length)
err_print("! Replacement string in @@l too long");
@.Replacement string in @@l...@>
@@ -1550,7 +1534,7 @@ but not an |int|, we use \.{\%td} to print these quantities.
void
print_stats(void) {
puts("\nMemory 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 replacement texts (out of %ld)\n",
(ptrdiff_t)(text_ptr-text_info),(long)max_texts);