summaryrefslogtreecommitdiff
path: root/web/c_cpp/cweb/common.w
diff options
context:
space:
mode:
Diffstat (limited to 'web/c_cpp/cweb/common.w')
-rw-r--r--web/c_cpp/cweb/common.w677
1 files changed, 280 insertions, 397 deletions
diff --git a/web/c_cpp/cweb/common.w b/web/c_cpp/cweb/common.w
index d8aacfb7b9..15e93c2c5e 100644
--- a/web/c_cpp/cweb/common.w
+++ b/web/c_cpp/cweb/common.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 3.64 --- January 2002
+% Version 4.2 --- February 2021
% Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth
@@ -15,14 +15,19 @@
% entire resulting derived work is given a different name and distributed
% under the terms of a permission notice identical to this one.
+% Amendments to 'common.w' resulting in this updated version were created
+% by numerous collaborators over the course of many years.
+
+% Please send comments, suggestions, etc. to tex-k@@tug.org.
+
\def\v{\char'174} % vertical (|) in typewriter font
-\def\title{Common code for CTANGLE and CWEAVE (Version 3.64)}
+\def\title{Common code for CTANGLE and CWEAVE (Version 4.2)}
\def\topofcontents{\null\vfill
\centerline{\titlefont Common code for {\ttitlefont CTANGLE} and
{\ttitlefont CWEAVE}}
\vskip 15pt
- \centerline{(Version 3.64)}
+ \centerline{(Version 4.2)}
\vfill}
\def\botofcontents{\vfill
\noindent
@@ -41,7 +46,10 @@ under the terms of a permission notice identical to this one.
\pageno=\contentspagenumber \advance\pageno by 1
\let\maybe=\iftrue
-@s not_eq normal @q unreserve a C++ keyword @>
+
+@s boolean int
+@s uint8_t int
+@s uint16_t int
@** Introduction. This file contains code common
to both \.{CTANGLE} and \.{CWEAVE}, which roughly concerns the following
@@ -58,20 +66,21 @@ The file begins with a few basic definitions.
@c
@<Include files@>@/
@h
-@<Definitions that should agree with \.{CTANGLE} and \.{CWEAVE}@>@/
-@<Other definitions@>@/
-@<Predeclaration of procedures@>@/
+@<Common code for \.{CWEAVE} and \.{CTANGLE}@>@/
+@<Global variables@>@/
+@<Predeclaration of procedures@>
+
+@ The details will be filled in due course. The interface of this module
+is included first. It is also used by the main programs.
+
+@i common.h
@ In certain cases \.{CTANGLE} and \.{CWEAVE} should do almost, but not
quite, the same thing. In these cases we've written common code for
both, differentiating between the two by means of the global variable
|program|.
-@d ctangle 0
-@d cweave 1
-
-@<Definitions...@>=
-typedef short boolean;
+@<Global var...@>=
boolean program; /* \.{CWEAVE} or \.{CTANGLE}? */
@ \.{CWEAVE} operates in three phases: First it inputs the source
@@ -80,7 +89,8 @@ produces the \TEX/ output file, and finally it sorts and outputs the index.
Similarly, \.{CTANGLE} operates in two phases.
The global variable |phase| tells which phase we are in.
-@<Other...@>= int phase; /* which phase are we in? */
+@<Global var...@>=
+int phase; /* which phase are we in? */
@ There's an initialization procedure that gets both \.{CTANGLE} and
\.{CWEAVE} off to a good start. We will fill in the details of this
@@ -88,29 +98,26 @@ procedure later.
@c
void
-common_init()
+common_init(void)
{
- @<Initialize pointers@>;
- @<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>;
- @<Scan arguments and open output files@>;
+ @<Initialize pointers@>@;
+ @<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>@;
+ @<Scan arguments and open output files@>@;
}
@* The character set.
\.{CWEB} uses the conventions of \CEE/ programs found in the standard
\.{ctype.h} header file.
-@<Include files@>=
-#include <ctype.h>
+A few character pairs are encoded internally as single characters,
+using the definitions in the interface sections above. These definitions
+are consistent with an extension of ASCII code originally developed at
+MIT and explained in Appendix~C of {\sl The \TEX/book\/}; thus, users
+who have such a character set can type things like \.{\char'32} and
+\.{\char'4} instead of \.{!=} and \.{\&\&}. (However, their files will
+not be too portable until more people adopt the extended code.)
-@ A few character pairs are encoded internally as single characters,
-using the definitions below. These definitions are consistent with
-an extension of ASCII code originally developed at MIT and explained in
-Appendix~C of {\sl The \TEX/book\/}; thus, users who have such a
-character set can type things like \.{\char'32} and \.{\char'4} instead
-of \.{!=} and \.{\&\&}. (However, their files will not be too portable
-until more people adopt the extended code.)
-
-If the character set is not ASCII, the definitions given here may conflict
+If the character set is not ASCII, the definitions given may conflict
with existing characters; in such cases, other arbitrary codes should be
substituted. The indexes to \.{CTANGLE} and \.{CWEAVE} mention every
case where similar codes may have to be changed in order to
@@ -120,26 +127,16 @@ in those indexes.
@^ASCII code dependencies@>
@^system dependencies@>
-@d and_and 04 /* `\.{\&\&}'\,; corresponds to MIT's {\tentex\char'4} */
-@d lt_lt 020 /* `\.{<<}'\,; corresponds to MIT's {\tentex\char'20} */
-@d gt_gt 021 /* `\.{>>}'\,; corresponds to MIT's {\tentex\char'21} */
-@d plus_plus 013 /* `\.{++}'\,; corresponds to MIT's {\tentex\char'13} */
-@d minus_minus 01 /* `\.{--}'\,; corresponds to MIT's {\tentex\char'1} */
-@d minus_gt 031 /* `\.{->}'\,; corresponds to MIT's {\tentex\char'31} */
-@d not_eq 032 /* `\.{!=}'\,; corresponds to MIT's {\tentex\char'32} */
-@d lt_eq 034 /* `\.{<=}'\,; corresponds to MIT's {\tentex\char'34} */
-@d gt_eq 035 /* `\.{>=}'\,; corresponds to MIT's {\tentex\char'35} */
-@d eq_eq 036 /* `\.{==}'\,; corresponds to MIT's {\tentex\char'36} */
-@d or_or 037 /* `\.{\v\v}'\,; corresponds to MIT's {\tentex\char'37} */
-@d dot_dot_dot 016 /* `\.{...}'\,; corresponds to MIT's {\tentex\char'16} */
-@d colon_colon 06 /* `\.{::}'\,; corresponds to MIT's {\tentex\char'6} */
-@d period_ast 026 /* `\.{.*}'\,; corresponds to MIT's {\tentex\char'26} */
-@d minus_gt_ast 027 /* `\.{->*}'\,; corresponds to MIT's {\tentex\char'27} */
+@<Global var...@>=
+char section_text[longest_name+1]; /* text being sought for */
+char *section_text_end = section_text+longest_name; /* end of |section_text| */
+char *id_first; /* where the current identifier begins in the buffer */
+char *id_loc; /* just after the current identifier in the buffer */
@** Input routines. The lowest level of input to the \.{CWEB} programs
is performed by |input_ln|, which must be told which file to read from.
-The return value of |input_ln| is 1 if the read is successful and 0 if
-not (generally this means the file has ended). The conventions
+The return value of |input_ln| is |true| if the read is successful and
+|false| if not (generally this means the file has ended). The conventions
of \TEX/ are followed; i.e., the characters of the next line of the file
are copied into the |buffer| array,
and the global variable |limit| is set to the first unoccupied position.
@@ -150,32 +147,23 @@ Since |buf_size| is strictly less than |long_buf_size|,
some of \.{CWEB}'s routines use the fact that it is safe to refer to
|*(limit+2)| without overstepping the bounds of the array.
-@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */
-@d longest_name 10000
-@d long_buf_size (buf_size+longest_name) /* for \.{CWEAVE} */
-@d xisspace(c) (isspace(c)&&((unsigned char)c<0200))
-@d xisupper(c) (isupper(c)&&((unsigned char)c<0200))
-
-@<Definitions...@>=
+@<Global var...@>=
char buffer[long_buf_size]; /* where each line of input goes */
char *buffer_end=buffer+buf_size-2; /* end of |buffer| */
-char *limit=buffer; /* points to the last character in the buffer */
char *loc=buffer; /* points to the next character to be read from the buffer */
-
-@ @<Include files@>=
-#include <stdio.h>
+char *limit=buffer; /* points to the last character in the buffer */
@ In the unlikely event that your standard I/O library does not
support |feof|, |getc|, and |ungetc| you may have to change things here.
@^system dependencies@>
@c
-int input_ln(fp) /* copies a line into |buffer| or returns 0 */
-FILE *fp; /* what file to read from */
+static boolean input_ln(@t\1\1@> /* copies a line into |buffer| or returns |false| */
+FILE *fp@t\2\2@>) /* what file to read from */
{
register int c=EOF; /* character read; initialized so some compilers won't complain */
register char *k; /* where next character goes */
- if (feof(fp)) return(0); /* we have hit end-of-file */
+ if (feof(fp)) return false; /* we have hit end-of-file */
limit = k = buffer; /* beginning of buffer */
while (k<=buffer_end && (c=getc(fp)) != EOF && c!='\n')
if ((*(k++) = c) != ' ') limit = k;
@@ -183,12 +171,14 @@ FILE *fp; /* what file to read from */
if ((c=getc(fp))!=EOF && c!='\n') {
ungetc(c,fp); loc=buffer; err_print("! Input line too long");
@.Input line too long@>
- }
- if (c==EOF && limit==buffer) return(0); /* there was nothing after
+ }
+ if (c==EOF && limit==buffer) return false; /* there was nothing after
the last newline */
- return(1);
+ return true;
}
+@ @<Predecl...@>=@+static boolean input_ln(FILE *);
+
@ Now comes the problem of deciding which file to read from next.
Recall that the actual text that \.{CWEB} should process comes from two
streams: a |web_file|, which can contain possibly nested include
@@ -201,32 +191,22 @@ from the |change_file|.
The line number of each open file is also kept for error reporting and
for the benefit of \.{CTANGLE}.
-@f line x /* make |line| an unreserved word */
-@d max_include_depth 10 /* maximum number of source files open
- simultaneously, not counting the change file */
-@d max_file_name_length 60
-@d cur_file file[include_depth] /* current file */
-@d cur_file_name file_name[include_depth] /* current file name */
-@d cur_line line[include_depth] /* number of current line in current file */
-@d web_file file[0] /* main source file */
-@d web_file_name file_name[0] /* main source file name */
-
-@<Definitions...@>=
+@<Global var...@>=
int include_depth; /* current level of nesting */
FILE *file[max_include_depth]; /* stack of non-change files */
FILE *change_file; /* change file */
char file_name[max_include_depth][max_file_name_length];
/* stack of non-change file names */
char change_file_name[max_file_name_length]; /* name of change file */
-char alt_web_file_name[max_file_name_length]; /* alternate name to try */
+static char alt_web_file_name[max_file_name_length]; /* alternate name to try */
int line[max_include_depth]; /* number of current line in the stacked files */
int change_line; /* number of current line in change file */
int change_depth; /* where \.{@@y} originated during a change */
boolean input_has_ended; /* if there is no more input */
boolean changing; /* if the current line is from |change_file| */
-boolean web_file_open=0; /* if the web file is being read */
+boolean web_file_open=false; /* if the web file is being read */
-@ When |changing==0|, the next line of |change_file| is kept in
+@ When |changing==false|, the next line of |change_file| is kept in
|change_buffer|, for purposes of comparison with the next
line of |cur_file|. After the change file has been completely input, we
set |change_limit=change_buffer|,
@@ -234,41 +214,43 @@ so that no further matches will be made.
Here's a shorthand expression for inequality between the two lines:
-@d lines_dont_match (change_limit-change_buffer != limit-buffer ||
- strncmp(buffer, change_buffer, limit-buffer))
+@d lines_dont_match (change_limit-change_buffer != limit-buffer || @|
+ strncmp(buffer, change_buffer, (size_t)(limit-buffer)))
-@<Other...@>=
-char change_buffer[buf_size]; /* next line of |change_file| */
-char *change_limit; /* points to the last character in |change_buffer| */
+@<Global var...@>=
+static char change_buffer[buf_size]; /* next line of |change_file| */
+static char *change_limit; /* points to the last character in |change_buffer| */
@ Procedure |prime_the_change_buffer|
sets |change_buffer| in preparation for the next matching operation.
Since blank lines in the change file are not used for matching, we have
|(change_limit==change_buffer && !changing)| if and only if
the change file is exhausted. This procedure is called only when
-|changing| is 1; hence error messages will be reported correctly.
+|changing| is |true|; hence error messages will be reported correctly.
@c
-void
-prime_the_change_buffer()
+static void
+prime_the_change_buffer(void)
{
change_limit=change_buffer; /* this value is used if the change file ends */
- @<Skip over comment lines in the change file; |return| if end of file@>;
- @<Skip to the next nonblank line; |return| if end of file@>;
- @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>;
+ @<Skip over comment lines in the change file; |return| if end of file@>@;
+ @<Skip to the next nonblank line; |return| if end of file@>@;
+ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>@;
}
+@ @<Predecl...@>=@+static void prime_the_change_buffer(void);
+
@ While looking for a line that begins with \.{@@x} in the change file, we
allow lines that begin with \.{@@}, as long as they don't begin with \.{@@y},
\.{@@z}, or \.{@@i} (which would probably mean that the change file is fouled up).
@<Skip over comment lines in the change file...@>=
-while(1) {
+while(true) {
change_line++;
if (!input_ln(change_file)) return;
if (limit<buffer+2) continue;
if (buffer[0]!='@@') continue;
- if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
+ if (xisupper(buffer[1])) buffer[1]=tolower((eight_bits)buffer[1]);
if (buffer[1]=='x') break;
if (buffer[1]=='y' || buffer[1]=='z' || buffer[1]=='i') {
loc=buffer+2;
@@ -291,12 +273,12 @@ do {
@ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>=
{
- change_limit=change_buffer+(limit-buffer);
- strncpy(change_buffer,buffer,limit-buffer+1);
+ change_limit=change_buffer+(ptrdiff_t)(limit-buffer);
+ strncpy(change_buffer,buffer,(size_t)(limit-buffer+1));
}
@ The following procedure is used to see if the next change entry should
-go into effect; it is called only when |changing| is 0.
+go into effect; it is called only when |changing| is |false|.
The idea is to test whether or not the current
contents of |buffer| matches the current contents of |change_buffer|.
If not, there's nothing more to do; but if so, a change is called for:
@@ -306,7 +288,7 @@ prepares to read the next line from |change_file|.
When a match is found, the current section is marked as changed unless
the first line after the \.{@@x} and after the \.{@@y} both start with
-either |'@@*'| or |'@@ '| (possibly preceded by whitespace).
+either `\.{@@*}' or `\.{@@\ }' (possibly preceded by whitespace).
This procedure is called only when |buffer<limit|, i.e., when the
current line is nonempty.
@@ -318,36 +300,36 @@ current line is nonempty.
}
@c
-void
-check_change() /* switches to |change_file| if the buffers match */
+static void
+check_change(void) /* switches to |change_file| if the buffers match */
{
int n=0; /* the number of discrepancies found */
if (lines_dont_match) return;
- change_pending=0;
+ change_pending=false;
if (!changed_section[section_count]) {
- if_section_start_make_pending(1);
- if (!change_pending) changed_section[section_count]=1;
+ if_section_start_make_pending(true);
+ if (!change_pending) changed_section[section_count]=true;
}
- while (1) {
- changing=1; print_where=1; change_line++;
+ while (true) {
+ changing=true; print_where=true; change_line++;
if (!input_ln(change_file)) {
err_print("! Change file ended before @@y");
@.Change file ended...@>
- change_limit=change_buffer; changing=0;
+ change_limit=change_buffer; changing=false;
return;
}
if (limit>buffer+1 && buffer[0]=='@@') {
- char xyz_code=xisupper(buffer[1])? tolower(buffer[1]): buffer[1];
+ char xyz_code=xisupper(buffer[1])? tolower((eight_bits)buffer[1]): buffer[1];
@<If the current line starts with \.{@@y},
- report any discrepancies and |return|@>;
+ report any discrepancies and |return|@>@;
}
- @<Move |buffer| and |limit|...@>;
- changing=0; cur_line++;
+ @<Move |buffer| and |limit|...@>@;
+ changing=false; cur_line++;
while (!input_ln(cur_file)) { /* pop the stack or quit */
if (include_depth==0) {
err_print("! CWEB file ended during a change");
@.CWEB file ended...@>
- input_has_ended=1; return;
+ input_has_ended=true; return;
}
include_depth--; cur_line++;
}
@@ -355,6 +337,8 @@ check_change() /* switches to |change_file| if the buffers match */
}
}
+@ @<Predecl...@>=@+static void check_change(void);
+
@ @<If the current line starts with \.{@@y}...@>=
if (xyz_code=='x' || xyz_code=='z') {
loc=buffer+2; err_print("! Where is the matching @@y?");
@@ -377,14 +361,14 @@ phases one and two of \.{CWEAVE}.
@c
void
-reset_input()
+reset_input(void)
{
limit=buffer; loc=buffer+1; buffer[0]=' ';
- @<Open input files@>;
+ @<Open input files@>@;
include_depth=0; cur_line=0; change_line=0;
change_depth=include_depth;
changing=1; prime_the_change_buffer(); changing=!changing;
- limit=buffer; loc=buffer+1; buffer[0]=' '; input_has_ended=0;
+ limit=buffer; loc=buffer+1; buffer[0]=' '; input_has_ended=false;
}
@ The following code opens the input files.
@@ -398,7 +382,7 @@ if ((web_file=fopen(web_file_name,"r"))==NULL) {
}
@.Cannot open input file@>
@.Cannot open change file@>
-web_file_open=1;
+web_file_open=true;
if ((change_file=fopen(change_file_name,"r"))==NULL)
fatal("! Cannot open change file ", change_file_name);
@@ -412,28 +396,24 @@ If we've just changed from the |cur_file| to the |change_file|, or if
the |cur_file| has changed, we tell \.{CTANGLE} to print this
information in the \CEE/ file by means of the |print_where| flag.
-@d max_sections 2000 /* number of identifiers, strings, section names;
- must be less than 10240 */
-
-@<Defin...@>=
-typedef unsigned short sixteen_bits;
+@<Global var...@>=
sixteen_bits section_count; /* the current section number */
boolean changed_section[max_sections]; /* is the section changed? */
boolean change_pending; /* if the current change is not yet recorded in
|changed_section[section_count]| */
-boolean print_where=0; /* should \.{CTANGLE} print line and file info? */
+boolean print_where=false; /* should \.{CTANGLE} print line and file info? */
@ @c
-int get_line() /* inputs the next line */
+boolean get_line(void) /* inputs the next line */
{
restart:
if (changing && include_depth==change_depth)
- @<Read from |change_file| and maybe turn off |changing|@>;
+ @<Read from |change_file| and maybe turn off |changing|@>@;
if (! changing || include_depth>change_depth) {
- @<Read from |cur_file| and maybe turn on |changing|@>;
+ @<Read from |cur_file| and maybe turn on |changing|@>@;
if (changing && include_depth==change_depth) goto restart;
}
- if (input_has_ended) return 0;
+ if (input_has_ended) return false;
loc=buffer; *limit=' ';
if (buffer[0]=='@@' && (buffer[1]=='i' || buffer[1]=='I')) {
loc=buffer+2; *limit='"';
@@ -449,9 +429,9 @@ int get_line() /* inputs the next line */
goto restart;
}
include_depth++; /* push input stack */
- @<Try to open include file, abort push if unsuccessful, go to |restart|@>;
+ @<Try to open include file, abort push if unsuccessful, go to |restart|@>@;
}
- return 1;
+ return true;
}
@ When an \.{@@i} line is found in the |cur_file|, we must temporarily
@@ -468,10 +448,7 @@ The remainder of the \.{@@i} line after the file name is ignored.
@d too_long() {include_depth--;
err_print("! Include file name too long"); goto restart;}
-@<Include...@>=
-#include <stdlib.h> /* declaration of |getenv| and |exit| */
-
-@ @<Try to open...@>= {
+@.CWEBINPUTS@>@<Try to open...@>= {
char temp_file_name[max_file_name_length];
char *cur_file_name_end=cur_file_name+max_file_name_length-1;
char *k=cur_file_name, *kk;
@@ -487,7 +464,7 @@ The remainder of the \.{@@i} line after the file name is ignored.
@.Include file name ...@>
*k='\0';
if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
- cur_line=0; print_where=1;
+ cur_line=0; print_where=true;
goto restart; /* success */
}
kk=getenv("CWEBINPUTS");
@@ -510,7 +487,7 @@ The remainder of the \.{@@i} line after the file name is ignored.
strcpy(cur_file_name,temp_file_name);
cur_file_name[l]='/'; /* \UNIX/ pathname separator */
if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
- cur_line=0; print_where=1;
+ cur_line=0; print_where=true;
goto restart; /* success */
}
}
@@ -520,8 +497,8 @@ The remainder of the \.{@@i} line after the file name is ignored.
@ @<Read from |cur_file|...@>= {
cur_line++;
while (!input_ln(cur_file)) { /* pop the stack or quit */
- print_where=1;
- if (include_depth==0) {input_has_ended=1; break;}
+ print_where=true;
+ if (include_depth==0) {input_has_ended=true; break;}
else {
fclose(cur_file); include_depth--;
if (changing && include_depth==change_depth) break;
@@ -543,21 +520,21 @@ The remainder of the \.{@@i} line after the file name is ignored.
}
if (limit>buffer) { /* check if the change has ended */
if (change_pending) {
- if_section_start_make_pending(0);
+ if_section_start_make_pending(false);
if (change_pending) {
- changed_section[section_count]=1; change_pending=0;
+ changed_section[section_count]=true; change_pending=false;
}
}
*limit=' ';
if (buffer[0]=='@@') {
- if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
+ if (xisupper(buffer[1])) buffer[1]=tolower((eight_bits)buffer[1]);
if (buffer[1]=='x' || buffer[1]=='y') {
loc=buffer+2;
err_print("! Where is the matching @@z?");
@.Where is the match...@>
}
else if (buffer[1]=='z') {
- prime_the_change_buffer(); changing=!changing; print_where=1;
+ prime_the_change_buffer(); changing=!changing; print_where=true;
}
}
}
@@ -568,11 +545,11 @@ had a line that didn't match any relevant line in |web_file|.
@c
void
-check_complete(){
- if (change_limit!=change_buffer) { /* |changing| is 0 */
- strncpy(buffer,change_buffer,change_limit-change_buffer+1);
- limit=buffer+(int)(change_limit-change_buffer);
- changing=1; change_depth=include_depth; loc=buffer;
+check_complete(void) {
+ if (change_limit!=change_buffer) { /* |changing| is |false| */
+ strncpy(buffer,change_buffer,(size_t)(change_limit-change_buffer+1));
+ limit=buffer+(ptrdiff_t)(change_limit-change_buffer);
+ changing=true; change_depth=include_depth; loc=buffer;
err_print("! Change file entry did not match");
@.Change file entry did not match@>
}
@@ -584,52 +561,58 @@ other strings in a large array of |char|s, called |byte_mem|.
Information about the names is kept in the array |name_dir|, whose
elements are structures of type |name_info|, containing a pointer into
the |byte_mem| array (the address where the name begins) and other data.
-A |name_pointer| variable is a pointer into |name_dir|.
-
-@d max_bytes 90000 /* the number of bytes in identifiers,
- index entries, and section names; must be less than $2^{24}$ */
-@d max_names 4000 /* number of identifiers, strings, section names;
- must be less than 10240 */
-
-@<Definitions that...@>=
-typedef struct name_info {
- char *byte_start; /* beginning of the name in |byte_mem| */
- @<More elements of |name_info| structure@>@;
-} name_info; /* contains information about an identifier or section name */
-typedef name_info *name_pointer; /* pointer into array of |name_info|s */
+A |name_pointer| variable is a pointer into |name_dir|. You find the
+complete layout of |name_info| in the interface sections above.
+
+The actual sequence of characters in the name pointed to by a |name_pointer
+p| appears in positions |p->byte_start| to |(p+1)->byte_start-1|, inclusive.
+
+The names of identifiers are found by computing a hash address |h| and
+then looking at strings of bytes signified by the |name_pointer|s
+|hash[h]|, |hash[h]->link|, |hash[h]->link->link|, \dots,
+until either finding the desired name or encountering the null pointer.
+
+The names of sections are stored in |byte_mem| together
+with the identifier names, but a hash table is not used for them because
+\.{CTANGLE} needs to be able to recognize a section name when given a prefix of
+that name. A conventional binary search tree is used to retrieve section names,
+with fields called |llink| and |rlink| (where |llink| takes the place
+of |link|). The root of this tree is stored in |name_dir->rlink|;
+this will be the only information in |name_dir[0]|.
+
+Since the space used by |rlink| has a different function for
+identifiers than for section names, we declare it as a |union|.
+
+The last component of |name_info| is different for \.{CTANGLE} and
+\.{CWEAVE}. In \.{CTANGLE}, if |p| is a pointer to a section name,
+|p->equiv| is a pointer to its replacement text, an element of the
+array |text_info|. In \.{CWEAVE}, on the other hand, if
+|p| points to an identifier, |p->xref| is a pointer to its
+list of cross-references, an element of the array |xmem|. The make-up
+of |text_info| and |xmem| is discussed in the \.{CTANGLE} and \.{CWEAVE}
+source files, respectively; here we just declare a common field
+|equiv_or_xref| as a pointer to |void|.
+
+@<Global var...@>=
char byte_mem[max_bytes]; /* characters of names */
char *byte_mem_end = byte_mem+max_bytes-1; /* end of |byte_mem| */
name_info name_dir[max_names]; /* information about names */
name_pointer name_dir_end = name_dir+max_names-1; /* end of |name_dir| */
-@ The actual sequence of characters in the name pointed to by a |name_pointer
-p| appears in positions |p->byte_start| to |(p+1)->byte_start-1|, inclusive.
-The |print_id| macro prints this text on the user's terminal.
-
-@d length(c) (c+1)->byte_start-(c)->byte_start /* the length of a name */
-@d print_id(c) term_write((c)->byte_start,length((c))) /* print identifier */
-
@ The first unused position in |byte_mem| and |name_dir| is
kept in |byte_ptr| and |name_ptr|, respectively. Thus we
usually have |name_ptr->byte_start==byte_ptr|, and certainly
we want to keep |name_ptr<=name_dir_end| and |byte_ptr<=byte_mem_end|.
-@<Defini...@>=
-name_pointer name_ptr; /* first unused position in |name_dir| */
+@<Global var...@>=
char *byte_ptr; /* first unused position in |byte_mem| */
+name_pointer name_ptr; /* first unused position in |name_dir| */
@ @<Init...@>=
name_dir->byte_start=byte_ptr=byte_mem; /* position zero in both arrays */
name_ptr=name_dir+1; /* |name_dir[0]| will be used only for error recovery */
name_ptr->byte_start=byte_mem; /* this makes name 0 of length zero */
-
-@ The names of identifiers are found by computing a hash address |h| and
-then looking at strings of bytes signified by the |name_pointer|s
-|hash[h]|, |hash[h]->link|, |hash[h]->link->link|, \dots,
-until either finding the desired name or encountering the null pointer.
-
-@<More elements of |name...@>=
-struct name_info *link;
+root=NULL; /* the binary search tree starts out with nothing in it */
@ The hash table itself
consists of |hash_size| entries of type |name_pointer|, and is
@@ -639,17 +622,13 @@ function |names_match|, which is slightly different in
\.{CWEAVE} and \.{CTANGLE}. If there is no match for the identifier,
it is inserted into the table.
-@d hash_size 353 /* should be prime */
+@d hash_size 8501 /* should be prime */
-@<Defini...@>=
-typedef name_pointer *hash_pointer;
+@<Global var...@>=
name_pointer hash[hash_size]; /* heads of hash lists */
hash_pointer hash_end = hash+hash_size-1; /* end of |hash| */
hash_pointer h; /* index into hash-head array */
-@ @<Predec...@>=
-extern int names_match();
-
@ Initially all the hash lists are empty.
@<Init...@>=
@@ -659,21 +638,21 @@ for (h=hash; h<=hash_end; *h++=NULL) ;
@c
name_pointer
-id_lookup(first,last,t) /* looks up a string in the identifier table */
-char *first; /* first character of string */
-char *last; /* last character of string plus one */
-char t; /* the |ilk|; used by \.{CWEAVE} only */
+id_lookup(@t\1\1@> /* looks up a string in the identifier table */
+const char *first, /* first character of string */
+const char *last, /* last character of string plus one */
+char t@t\2\2@>) /* the |ilk|; used by \.{CWEAVE} only */
{
- char *i=first; /* position in |buffer| */
+ const char *i=first; /* position in |buffer| */
int h; /* hash code */
int l; /* length of the given identifier */
name_pointer p; /* where the identifier is being sought */
if (last==NULL) for (last=first; *last!='\0'; last++);
- l=last-first; /* compute the length */
- @<Compute the hash code |h|@>;
- @<Compute the name location |p|@>;
- if (p==name_ptr) @<Enter a new name into the table at position |p|@>;
- return(p);
+ l=(int)(last-first); /* compute the length */
+ @<Compute the hash code |h|@>@;
+ @<Compute the name location |p|@>@;
+ if (p==name_ptr) @<Enter a new name into the table at position |p|@>@;
+ return p;
}
@ A simple hash code is used: If the sequence of
@@ -681,8 +660,8 @@ character codes is $c_1c_2\ldots c_n$, its hash value will be
$$(2^{n-1}c_1+2^{n-2}c_2+\cdots+c_n)\,\bmod\,|hash_size|.$$
@<Compute the hash...@>=
-h=(unsigned char)*i;
-while (++i<last) h=(h+h+(int)((unsigned char)*i)) % hash_size;
+h=(eight_bits)*i;
+while (++i<last) h=(h+h+(int)((eight_bits)*i)) % hash_size;
@^high-bit character handling@>
@ If the identifier is new, it will be placed in position |p=name_ptr|,
@@ -699,44 +678,14 @@ if (p==NULL) {
@ The information associated with a new identifier must be initialized
in a slightly different way in \.{CWEAVE} than in \.{CTANGLE}; hence the
|init_p| procedure.
-
-@<Pred...@>=
-void init_p();
-
-@ @<Enter a new name...@>= {
+@<Enter a new name...@>= {
if (byte_ptr+l>byte_mem_end) overflow("byte memory");
if (name_ptr>=name_dir_end) overflow("name");
strncpy(byte_ptr,first,l);
(++name_ptr)->byte_start=byte_ptr+=l;
- if (program==cweave) init_p(p,t);
+ init_p(p,t);
}
-@ The names of sections are stored in |byte_mem| together
-with the identifier names, but a hash table is not used for them because
-\.{CTANGLE} needs to be able to recognize a section name when given a prefix of
-that name. A conventional binary search tree is used to retrieve section names,
-with fields called |llink| and |rlink| (where |llink| takes the place
-of |link|). The root of this tree is stored in |name_dir->rlink|;
-this will be the only information in |name_dir[0]|.
-
-Since the space used by |rlink| has a different function for
-identifiers than for section names, we declare it as a |union|.
-
-@d llink link /* left link in binary search tree for section names */
-@d rlink dummy.Rlink /* right link in binary search tree for section names */
-@d root name_dir->rlink /* the root of the binary search tree
- for section names */
-
-@<More elements of |name...@>=
-union {
- struct name_info *Rlink; /* right link in binary search tree for section
- names */
- char Ilk; /* used by identifiers in \.{CWEAVE} only */
-} dummy;
-
-@ @<Init...@>=
-root=NULL; /* the binary search tree starts out with nothing in it */
-
@ If |p| is a |name_pointer| variable, as we have seen,
|p->byte_start| is the beginning of the area where the name
corresponding to |p| is stored. However, if |p| refers to a section
@@ -756,24 +705,24 @@ to additional chunks in the same way. Null links are represented by
|name_dir|.
@d first_chunk(p) ((p)->byte_start+2)
-@d prefix_length(p) (int)((unsigned char)*((p)->byte_start)*256 +
- (unsigned char)*((p)->byte_start+1))
+@d prefix_length(p) (int)((eight_bits)*((p)->byte_start)*256 +
+ (eight_bits)*((p)->byte_start+1))
@d set_prefix_length(p,m) (*((p)->byte_start)=(m)/256,
*((p)->byte_start+1)=(m)%256)
@c
void
-print_section_name(p)
-name_pointer p;
+print_section_name(
+name_pointer p)
{
char *ss, *s = first_chunk(p);
name_pointer q = p+1;
while (p!=name_dir) {
ss = (p+1)->byte_start-1;
if (*ss==' ' && ss>=s) {
- term_write(s,ss-s); p=q->link; q=p;
+ term_write(s,(size_t)(ss-s)); p=q->link; q=p;
} else {
- term_write(s,ss+1-s); p=name_dir; q=NULL;
+ term_write(s,(size_t)(ss+1-s)); p=name_dir; q=NULL;
}
s = p->byte_start;
}
@@ -782,9 +731,9 @@ name_pointer p;
@ @c
void
-sprint_section_name(dest,p)
- char*dest;
- name_pointer p;
+sprint_section_name(
+ char *dest,
+ name_pointer p)
{
char *ss, *s = first_chunk(p);
name_pointer q = p+1;
@@ -795,7 +744,7 @@ sprint_section_name(dest,p)
} else {
ss++; p=name_dir;
}
- strncpy(dest,s,ss-s), dest+=ss-s;
+ strncpy(dest,s,(size_t)(ss-s)), dest+=ss-s;
s = p->byte_start;
}
*dest='\0';
@@ -803,8 +752,8 @@ sprint_section_name(dest,p)
@ @c
void
-print_prefix_name(p)
-name_pointer p;
+print_prefix_name(
+name_pointer p)
{
char *s = first_chunk(p);
int l = prefix_length(p);
@@ -822,10 +771,17 @@ are null-terminated, and we keep an eye open for prefixes and extensions.
@d prefix 3 /* the first name is a proper prefix of the second */
@d extension 4 /* the first name is a proper extension of the second */
-@c
-int web_strcmp(j,j_len,k,k_len) /* fuller comparison than |strcmp| */
- char *j, *k; /* beginning of first and second strings */
- int j_len, k_len; /* length of strings */
+@<Predecl...@>=
+static int web_strcmp(char *,int,char *,int);@/
+static name_pointer add_section_name(name_pointer,int,char *,char *,int);@/
+static void extend_section_name(name_pointer,char *,char *,int);
+
+@ @c
+static int web_strcmp(@t\1\1@> /* fuller comparison than |strcmp| */
+ char *j, /* beginning of first string */
+ int j_len, /* length of first string */
+ char *k, /* beginning of second string */
+ int k_len@t\2\2@>) /* length of second string */
{
char *j1=j+j_len, *k1=k+k_len;
while (k<k1 && j<j1 && *j==*k) k++, j++;
@@ -849,21 +805,18 @@ differently in \.{CWEAVE} and \.{CTANGLE}; hence the
|init_node| procedure, which is defined differently in \.{cweave.w}
and \.{ctangle.w}.
-@<Prede...@>=
-extern void init_node();
-
-@ @c
-name_pointer
-add_section_name(par,c,first,last,ispref) /* install a new node in the tree */
-name_pointer par; /* parent of new node */
-int c; /* right or left? */
-char *first; /* first character of section name */
-char *last; /* last character of section name, plus one */
-int ispref; /* are we adding a prefix or a full name? */
+@c
+static name_pointer
+add_section_name(@t\1\1@> /* install a new node in the tree */
+name_pointer par, /* parent of new node */
+int c, /* right or left? */
+char *first, /* first character of section name */
+char *last, /* last character of section name, plus one */
+int ispref@t\2\2@>) /* are we adding a prefix or a full name? */
{
name_pointer p=name_ptr; /* new node */
char *s=first_chunk(p);
- int name_len=last-first+ispref; /* length of section name */
+ int name_len=(int)(last-first)+ispref; /* length of section name */
if (s+name_len>byte_mem_end) overflow("byte memory");
if (name_ptr+1>=name_dir_end) overflow("name");
(++name_ptr)->byte_start=byte_ptr=s+name_len;
@@ -882,16 +835,16 @@ int ispref; /* are we adding a prefix or a full name? */
}
@ @c
-void
-extend_section_name(p,first,last,ispref)
-name_pointer p; /* name to be extended */
-char *first; /* beginning of extension text */
-char *last; /* one beyond end of extension text */
-int ispref; /* are we adding a prefix or a full name? */
+static void
+extend_section_name(@t\1\1@>
+name_pointer p, /* name to be extended */
+char *first, /* beginning of extension text */
+char *last, /* one beyond end of extension text */
+int ispref@t\2\2@>) /* are we adding a prefix or a full name? */
{
char *s;
name_pointer q=p+1;
- int name_len=last-first+ispref;
+ int name_len=(int)(last-first)+ispref;
if (name_ptr>=name_dir_end) overflow("name");
while (q->link!=name_dir) q=q->link;
q->link=name_ptr;
@@ -911,9 +864,9 @@ exactly equals or is a prefix or extension of a name in the tree.
@c
name_pointer
-section_lookup(first,last,ispref) /* find or install section name in tree */
-char *first, *last; /* first and last characters of new name */
-int ispref; /* is the new name a prefix or a full name? */
+section_lookup(@t\1\1@> /* find or install section name in tree */
+char *first,char *last, /* first and last characters of new name */
+int ispref@t\2\2@>) /* is the new name a prefix or a full name? */
{
int c=0; /* comparison between two names; initialized so some compilers won't complain */
name_pointer p=root; /* current node of the search tree */
@@ -921,11 +874,11 @@ int ispref; /* is the new name a prefix or a full name? */
name_pointer r=NULL; /* where a match has been found */
name_pointer par=NULL; /* parent of |p|, if |r| is |NULL|;
otherwise parent of |r| */
- int name_len=last-first+1;
+ int name_len=(int)(last-first)+1;
@<Look for matches for new name among shortest prefixes, complaining
- if more than one is found@>;
- @<If no match found, add new name to tree@>;
- @<If one match found, check for compatibility and return match@>;
+ if more than one is found@>@;
+ @<If no match found, add new name to tree@>@;
+ @<If one match found, check for compatibility and return match@>@;
}
@ A legal new name matches an existing section name if and only if it
@@ -942,10 +895,10 @@ while (p) { /* compare shortest prefix of |p| with new name */
p=(c==less?p->llink:p->rlink);
} else { /* new name matches |p| */
if (r!=NULL) { /* and also |r|: illegal */
- printf("\n! Ambiguous prefix: matches <");
+ fputs("\n! Ambiguous prefix: matches <",stdout);
@.Ambiguous prefix ... @>
print_prefix_name(p);
- printf(">\n and <");
+ fputs(">\n and <",stdout);
print_prefix_name(r);
err_print(">");
return name_dir; /* the unsection */
@@ -971,7 +924,7 @@ switch(section_name_cmp(&first,name_len,r)) {
/* compare all of |r| with new name */
case prefix:
if (!ispref) {
- printf("\n! New name is a prefix of <");
+ fputs("\n! New name is a prefix of <",stdout);
@.New name is a prefix...@>
print_section_name(r);
err_print(">");
@@ -983,16 +936,16 @@ switch(section_name_cmp(&first,name_len,r)) {
extend_section_name(r,first,last+1,ispref);
return r;
case bad_extension:
- printf("\n! New name extends <");
+ fputs("\n! New name extends <",stdout);
@.New name extends...@>
print_section_name(r);
err_print(">");
return r;
default: /* no match: illegal */
- printf("\n! Section name incompatible with <");
+ fputs("\n! Section name incompatible with <",stdout);
@.Section name incompatible...@>
print_prefix_name(r);
- printf(">,\n which abbreviates <");
+ fputs(">,\n which abbreviates <",stdout);
print_section_name(r);
err_print(">");
return r;
@@ -1014,53 +967,39 @@ us to regard \.{@@<foo...@@>} as an ``extension'' of itself.
@d bad_extension 5
-@<Predec...@>=
-int section_name_cmp();
-
-@ @c
-int section_name_cmp(pfirst,len,r)
-char **pfirst; /* pointer to beginning of comparison string */
-int len; /* length of string */
-name_pointer r; /* section name being compared */
+@c
+static int section_name_cmp(@t\1\1@>
+char **pfirst, /* pointer to beginning of comparison string */
+int len, /* length of string */
+name_pointer r@t\2\2@>) /* section name being compared */
{
char *first=*pfirst; /* beginning of comparison string */
name_pointer q=r+1; /* access to subsequent chunks */
char *ss, *s=first_chunk(r);
int c; /* comparison */
int ispref; /* is chunk |r| a prefix? */
- while (1) {
+ while (true) {
ss=(r+1)->byte_start-1;
if (*ss==' ' && ss>=r->byte_start) ispref=1,q=q->link;
else ispref=0,ss++,q=name_dir;
switch(c=web_strcmp(first,len,s,ss-s)) {
case equal: if (q==name_dir)
if (ispref) {
- *pfirst=first+(ss-s);
+ *pfirst=first+(ptrdiff_t)(ss-s);
return extension; /* null extension */
} else return equal;
else return (q->byte_start==(q+1)->byte_start)? equal: prefix;
case extension:
if (!ispref) return bad_extension;
first += ss-s;
- if (q!=name_dir) {len -= ss-s; s=q->byte_start; r=q; continue;}
+ if (q!=name_dir) {len -= (int)(ss-s); s=q->byte_start; r=q; continue;}
*pfirst=first; return extension;
default: return c;
}
}
}
-@ The last component of |name_info| is different for \.{CTANGLE} and
-\.{CWEAVE}. In \.{CTANGLE}, if |p| is a pointer to a section name,
-|p->equiv| is a pointer to its replacement text, an element of the
-array |text_info|. In \.{CWEAVE}, on the other hand, if
-|p| points to an identifier, |p->xref| is a pointer to its
-list of cross-references, an element of the array |xmem|. The make-up
-of |text_info| and |xmem| is discussed in the \.{CTANGLE} and \.{CWEAVE}
-source files, respectively; here we just declare a common field
-|equiv_or_xref| as a pointer to a |char|.
-
-@<More elements of |name...@>=
-char *equiv_or_xref; /* info corresponding to names */
+@ @<Predec...@>=@+static int section_name_cmp(char **,int,name_pointer);
@** Reporting errors to the user.
A global variable called |history| will contain one of four values
@@ -1072,14 +1011,7 @@ terminated abnormally. The value of |history| does not influence the
behavior of the program; it is simply computed for the convenience
of systems that might want to use such information.
-@d spotless 0 /* |history| value for normal jobs */
-@d harmless_message 1 /* |history| value when non-serious info was printed */
-@d error_message 2 /* |history| value when an error was noted */
-@d fatal_message 3 /* |history| value when we had to stop prematurely */
-@d mark_harmless {if (history==spotless) history=harmless_message;}
-@d mark_error history=error_message
-
-@<Definit...@>=
+@<Global var...@>=
int history=spotless; /* indicates how bad this run was */
@ The command `|err_print("! Error message")|' will report a syntax error to
@@ -1089,17 +1021,14 @@ Note that no period follows the error message, since the error routine
will automatically supply a period. A newline is automatically supplied
if the string begins with |"!"|.
-@<Predecl...@>=
-void err_print();
-
-@ @c
+@c
void
-err_print(s) /* prints `\..' and location of error message */
-char *s;
+err_print(@t\1\1@> /* prints `\..' and location of error message */
+const char *s@t\2\2@>)
{
char *k,*l; /* pointers into |buffer| */
printf(*s=='!'? "\n%s" : "%s",s);
- if(web_file_open) @<Print error location based on input buffer@>;
+ if(web_file_open) @<Print error location based on input buffer@>@;
update_terminal; mark_error;
}
@@ -1135,52 +1064,46 @@ up and quit as graciously as possible. This is done by calling the
function |wrap_up| at the end of the code.
\.{CTANGLE} and \.{CWEAVE} have their own notions about how to
-print the job statistics.
+print the job statistics. See the function(s) |print_stats| in the
+interface above and in the index.
-@<Prede...@>=
-int wrap_up();
-extern void print_stats();
-
-@ Some implementations may wish to pass the |history| value to the
+Some implementations may wish to pass the |history| value to the
operating system so that it can be used to govern whether or not other
programs are started. Here, for instance, we pass the operating system
a status of 0 if and only if only harmless messages were printed.
@^system dependencies@>
@c
-int wrap_up() {
- putchar('\n');
+int wrap_up(void) {
+ if (show_progress) new_line;
if (show_stats)
print_stats(); /* print statistics about memory usage */
- @<Print the job |history|@>;
- if (history > harmless_message) return(1);
- else return(0);
+ @<Print the job |history|@>@;
+ if (history > harmless_message) return EXIT_FAILURE;
+ else return EXIT_SUCCESS;
}
@ @<Print the job |history|@>=
switch (history) {
-case spotless: if (show_happiness) printf("(No errors were found.)\n"); break;
+case spotless: if (show_happiness) puts("(No errors were found.)"); break;
case harmless_message:
- printf("(Did you see the warning message above?)\n"); break;
+ puts("(Did you see the warning message above?)"); break;
case error_message:
- printf("(Pardon me, but I think I spotted something wrong.)\n"); break;
-case fatal_message: printf("(That was a fatal error, my friend.)\n");
+ puts("(Pardon me, but I think I spotted something wrong.)"); break;
+case fatal_message: puts("(That was a fatal error, my friend.)");
} /* there are no other cases */
@ When there is no way to recover from an error, the |fatal| subroutine is
invoked. This happens most often when |overflow| occurs.
-@<Predec...@>=
-void fatal(), overflow();
-
-@ The two parameters to |fatal| are strings that are essentially
+The two parameters to |fatal| are strings that are essentially
concatenated to print the final error message.
@c void
-fatal(s,t)
- char *s,*t;
+fatal(
+ const char *s,const char *t)
{
- if (*s) printf(s);
+ if (*s) err_print(s);
err_print(t);
history=fatal_message; exit(wrap_up());
}
@@ -1188,8 +1111,8 @@ fatal(s,t)
@ An overflow stop occurs if \.{CWEB}'s tables aren't large enough.
@c void
-overflow(t)
- char *t;
+overflow(
+ const char *t)
{
printf("\n! Sorry, %s capacity exceeded",t); fatal("","");
}
@@ -1200,9 +1123,6 @@ and \.{CWEB} prints an error message that is really for the \.{CWEB}
maintenance person, not the user. In such cases the program says
|confusion("indication of where we are")|.
-@d confusion(s) fatal("! This can't happen: ",s)
-@.This can't happen@>
-
@** Command line arguments.
The user calls \.{CWEAVE} and \.{CTANGLE} with arguments on the command line.
These are either file names or flags to be turned off (beginning with |"-"|)
@@ -1212,12 +1132,7 @@ of the program. The various file name variables contain strings with
the names of those files. Most of the 128 flags are undefined but available
for future extensions.
-@d show_banner flags['b'] /* should the banner line be printed? */
-@d show_progress flags['p'] /* should progress reports be printed? */
-@d show_stats flags['s'] /* should statistics be printed at end of run? */
-@d show_happiness flags['h'] /* should lack of errors be announced? */
-
-@<Defin...@>=
+@<Global var...@>=
int argc; /* copy of |ac| parameter to |main| */
char **argv; /* copy of |av| parameter to |main| */
char C_file_name[max_file_name_length]; /* name of |C_file| */
@@ -1226,12 +1141,13 @@ char idx_file_name[max_file_name_length]; /* name of |idx_file| */
char scn_file_name[max_file_name_length]; /* name of |scn_file| */
boolean flags[128]; /* an option for each 7-bit code */
-@ The |flags| will be initially zero. Some of them are set to~1 before
-scanning the arguments; if additional flags are 1 by default they
+@ The |flags| will be initially |false|. Some of them are set to~|true| before
+scanning the arguments; if additional flags are |true| by default they
should be set before calling |common_init|.
@<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>=
-show_banner=show_happiness=show_progress=1;
+show_banner=show_happiness=show_progress=make_xrefs=true;@/
+show_stats=false;
@ We now must look at the command line arguments and set the file names
accordingly. At least one file name must be present: the \.{CWEB}
@@ -1248,20 +1164,17 @@ when no changes are desired.
If there's a third file name, it will be the output file.
-@<Pred...@>=
-void scan_args();
-
-@ @c
-void
-scan_args()
+@c
+static void
+scan_args(void)
{
char *dot_pos; /* position of |'.'| in the argument */
char *name_pos; /* file name beginning, sans directory */
register char *s; /* register for scanning strings */
- boolean found_web=0,found_change=0,found_out=0;
+ boolean found_web=false,found_change=false,found_out=false;
/* have these names been seen? */
- boolean flag_change;
+ strcpy(change_file_name,"/dev/null");
while (--argc > 0) {
if ((**(++argv)=='-'||**argv=='+')&&*(*argv+1)) @<Handle flag argument@>@;
else {
@@ -1275,13 +1188,14 @@ scan_args()
|web_file_name|, |tex_file_name|, and |C_file_name|@>@;
else if (!found_change) @<Make |change_file_name| from |fname|@>@;
else if (!found_out) @<Override |tex_file_name| and |C_file_name|@>@;
- else @<Print usage error message and quit@>;
+ else @<Print usage error message and quit@>@;
}
}
- if (!found_web) @<Print usage error message and quit@>;
- if (found_change<=0) strcpy(change_file_name,"/dev/null");
+ if (!found_web) @<Print usage error message and quit@>@;
}
+@ @<Pred...@>=@+static void scan_args(void);
+
@ We use all of |*argv| for the |web_file_name| if there is a |'.'| in it,
otherwise we add |".w"|. If this file can't be opened, we prepare an
|alt_web_file_name| by adding |"web"| after the dot.
@@ -1292,7 +1206,7 @@ after the dot. We must check that there is enough room in
@<Make |web_file_name|...@>=
{
if (s-*argv > max_file_name_length-5)
- @<Complain about argument length@>;
+ @<Complain about argument length@>@;
if (dot_pos==NULL)
sprintf(web_file_name,"%s.w",*argv);
else {
@@ -1304,26 +1218,25 @@ after the dot. We must check that there is enough room in
sprintf(idx_file_name,"%s.idx",name_pos);
sprintf(scn_file_name,"%s.scn",name_pos);
sprintf(C_file_name,"%s.c",name_pos);
- found_web=1;
+ found_web=true;
}
@ @<Make |change_file_name|...@>=
{
- if (strcmp(*argv,"-")==0) found_change=-1;
- else {
+ if (strcmp(*argv,"-")!=0) {
if (s-*argv > max_file_name_length-4)
- @<Complain about argument length@>;
+ @<Complain about argument length@>@;
if (dot_pos==NULL)
sprintf(change_file_name,"%s.ch",*argv);
else strcpy(change_file_name,*argv);
- found_change=1;
}
+ found_change=true;
}
@ @<Override...@>=
{
if (s-*argv > max_file_name_length-5)
- @<Complain about argument length@>;
+ @<Complain about argument length@>@;
if (dot_pos==NULL) {
sprintf(tex_file_name,"%s.tex",*argv);
sprintf(idx_file_name,"%s.idx",*argv);
@@ -1332,21 +1245,20 @@ after the dot. We must check that there is enough room in
} else {
strcpy(tex_file_name,*argv);
strcpy(C_file_name,*argv);
- if (flags['x']) { /* indexes will be generated */
+ if (make_xrefs) { /* indexes will be generated */
*dot_pos=0;
sprintf(idx_file_name,"%s.idx",*argv);
sprintf(scn_file_name,"%s.scn",*argv);
}
}
- found_out=1;
+ found_out=true;
}
-@ @<Handle flag...@>=
+@ @d flag_change (**argv!='-')
+@<Handle flag...@>=
{
- if (**argv=='-') flag_change=0;
- else flag_change=1;
for(dot_pos=*argv+1;*dot_pos>'\0';dot_pos++)
- flags[*dot_pos]=flag_change;
+ flags[(eight_bits)*dot_pos]=flag_change;
}
@ @<Print usage error message and quit@>=
@@ -1367,7 +1279,7 @@ else fatal(
@** Output. Here is the code that opens the output file:
@^system dependencies@>
-@<Defin...@>=
+@<Global var...@>=
FILE *C_file; /* where output of \.{CTANGLE} goes */
FILE *tex_file; /* where output of \.{CWEAVE} goes */
FILE *idx_file; /* where index from \.{CWEAVE} goes */
@@ -1377,42 +1289,13 @@ FILE *active_file; /* currently active file for \.{CWEAVE} output */
@ @<Scan arguments and open output files@>=
scan_args();
if (program==ctangle) {
- if ((C_file=fopen(C_file_name,"w"))==NULL)
+ if ((C_file=fopen(C_file_name,"wb"))==NULL)
fatal("! Cannot open output file ", C_file_name);
@.Cannot open output file@>
}
else {
- if ((tex_file=fopen(tex_file_name,"w"))==NULL)
+ if ((tex_file=fopen(tex_file_name,"wb"))==NULL)
fatal("! Cannot open output file ", tex_file_name);
}
-@ The |update_terminal| procedure is called when we want
-to make sure that everything we have output to the terminal so far has
-actually left the computer's internal buffers and been sent.
-@^system dependencies@>
-
-@d update_terminal fflush(stdout) /* empty the terminal output buffer */
-
-@ Terminal output uses |putchar| and |putc| when we have to
-translate from \.{CWEB}'s code into the external character code,
-and |printf| when we just want to print strings.
-Several macros make other kinds of output convenient.
-@^system dependencies@>
-@d new_line putchar('\n') @d putxchar putchar
-@d term_write(a,b) fflush(stdout),fwrite(a,sizeof(char),b,stdout)
-@d C_printf(c,a) fprintf(C_file,c,a)
-@d C_putc(c) putc(c,C_file) /* isn't \CEE/ wonderfully consistent? */
-
-@ We predeclare several standard system functions here instead of including
-their system header files, because the names of the header files are not as
-standard as the names of the functions. (For example, some \CEE/ environments
-have \.{<string.h>} where others have \.{<strings.h>}.)
-
-@<Predecl...@>=
-extern int strlen(); /* length of string */
-extern int strcmp(); /* compare strings lexicographically */
-extern char* strcpy(); /* copy one string to another */
-extern int strncmp(); /* compare up to $n$ string characters */
-extern char* strncpy(); /* copy up to $n$ string characters */
-
@** Index.