summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/cwebdir/comm-w2c.ch
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
committerKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
commitad547a6b5986815fda458221149728d9d9ab1d87 (patch)
tree16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/web2c/cwebdir/comm-w2c.ch
parent947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff)
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/cwebdir/comm-w2c.ch')
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-w2c.ch866
1 files changed, 866 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/cwebdir/comm-w2c.ch b/Build/source/texk/web2c/cwebdir/comm-w2c.ch
new file mode 100644
index 00000000000..286a39723e1
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-w2c.ch
@@ -0,0 +1,866 @@
+@q Changes for CWEB in TeX Live from numerous contributors. @>
+@q This file is in the Public Domain. @>
+
+@q Most of the original Kpathsea changes by Wlodek Bzyl and Olaf Weber @>
+@q were merged with the set of change files of the CWEBbin project; @>
+@q see https://github.com/ascherer/cwebbin for the original parts. @>
+
+@q This stripped change file {comm,ctang,cweav,ctwill,cwebman}-w2c.ch @>
+@q has been created from the elaborate set of change files @>
+@q {comm,ctang,cweav,cwebman}-patch.ch, @>
+@q {comm,cweav,cwebman}-extensions.ch, {comm,ctang,cweav}-output.ch, @>
+@q {comm,ctang,cweav}-i18n.ch, and cweav-twill.ch for CTWILL, and @>
+@q {comm,ctang,cweav,ctwill,cwebman}-texlive.ch with the 'tie' processor @>
+@q and is used as a monolithic changefile for {common,ctangle,cweave}.w @>
+@q and cwebman.tex in TeX Live. @>
+
+@q Please send comments, suggestions, etc. to tex-k@@tug.org. @>
+
+@x
+\def\title{Common code for CTANGLE and CWEAVE (Version 4.2)}
+@y
+\def\Kpathsea/{{\mc KPATHSEA\spacefactor1000}} \ifacro\sanitizecommand\Kpathsea{KPATHSEA}\fi
+\def\title{Common code for CTANGLE and CWEAVE (4.2 [\TeX~Live])}
+@z
+
+@x
+ \centerline{(Version 4.2)}
+@y
+ \centerline{(Version 4.2 [\TeX~Live])}
+@z
+
+@x
+\def\botofcontents{\vfill
+@y
+\def\covernote{\vbox{%
+@z
+
+@x
+}
+@y
+}}\datecontentspage
+@z
+
+@x
+to both \.{CTANGLE} and \.{CWEAVE}, which roughly concerns the following
+@y
+to \.{CTANGLE}, \.{CWEAVE}, and \.{CTWILL},
+which roughly concerns the following
+@z
+
+@x
+sometimes use \.{CWEB} to refer to either of the two component
+@y
+sometimes use \.{CWEB} to refer to any of the three component
+@z
+
+@x
+@i common.h
+@y
+@i comm-w2c.h
+@z
+
+@x
+|program|.
+@y
+|program|. And \.{CTWILL} adds some extra twists.
+@z
+
+@x
+boolean program; /* \.{CWEAVE} or \.{CTANGLE}? */
+@y
+cweb program; /* \.{CTANGLE} or \.{CWEAVE} or \.{CTWILL}? */
+@z
+
+@x
+ @<Initialize pointers@>@;
+@y
+ @<Initialize pointers@>@;
+ @<Set up |PROGNAME| feature and initialize the search path mechanism@>@;
+@z
+
+@x
+ @<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>@;
+@y
+ @<Set locale and bind language catalogs@>@;
+ @<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>@;
+@z
+
+@x
+ if ((*(k++) = c) != ' ') limit = k;
+@y
+ if ((*(k++) = c) != ' ' && c != '\r') limit = k;
+@z
+
+@x
+ ungetc(c,fp); loc=buffer; err_print("! Input line too long");
+@y
+ ungetc(c,fp); loc=buffer; err_print(_("! Input line too long"));
+@z
+
+@x
+static char alt_web_file_name[max_file_name_length]; /* alternate name to try */
+@y
+@z
+
+@x
+ err_print("! Missing @@x in change file");
+@y
+ err_print(_("! Missing @@x in change file"));
+@z
+
+@x
+ err_print("! Change file ended after @@x");
+@y
+ err_print(_("! Change file ended after @@x"));
+@z
+
+@x
+ err_print("! Change file ended before @@y");
+@y
+ err_print(_("! Change file ended before @@y"));
+@z
+
+@x
+ err_print("! CWEB file ended during a change");
+@y
+ err_print(_("! CWEB file ended during a change"));
+@z
+
+@x
+ loc=buffer+2; err_print("! Where is the matching @@y?");
+@y
+ loc=buffer+2; err_print(_("! Where is the matching @@y?"));
+@z
+
+@x
+ err_print("of the preceding lines failed to match");
+@y
+ err_print(_("of the preceding lines failed to match"));
+@z
+
+@x
+if ((web_file=fopen(web_file_name,"r"))==NULL) {
+ strcpy(web_file_name,alt_web_file_name);
+ if ((web_file=fopen(web_file_name,"r"))==NULL)
+ fatal("! Cannot open input file ", web_file_name);
+}
+@y
+if ((found_filename=kpse_find_cweb(web_file_name))==NULL || @|
+ (web_file=fopen(found_filename,"r"))==NULL) {
+ fatal(_("! Cannot open input file "), web_file_name);
+} else if (strlen(found_filename) < max_file_name_length) {
+ /* Copy name for |#line| directives. */
+ if (strcmp(web_file_name, found_filename))
+ strcpy(web_file_name, found_filename +
+ ((strncmp(found_filename,"./",2)==0) ? 2 : 0));
+ free(found_filename);
+} else fatal(_("! Filename too long\n"), found_filename);
+@z
+
+@x
+if ((change_file=fopen(change_file_name,"r"))==NULL)
+ fatal("! Cannot open change file ", change_file_name);
+@y
+if ((found_filename=kpse_find_cweb(change_file_name))==NULL || @|
+ (change_file=fopen(found_filename,"r"))==NULL) {
+ fatal(_("! Cannot open change file "), change_file_name);
+} else if (strlen(found_filename) < max_file_name_length) {
+ /* Copy name for |#line| directives. */
+ if (strcmp(change_file_name, found_filename))
+ strcpy(change_file_name, found_filename +
+ ((strncmp(found_filename,"./",2)==0) ? 2 : 0));
+ free(found_filename);
+} else fatal(_("! Filename too long\n"), found_filename);
+@z
+
+@x
+ err_print("! Include file name not given");
+@y
+ err_print(_("! Include file name not given"));
+@z
+
+@x
+ err_print("! Too many nested includes");
+@y
+ err_print(_("! Too many nested includes"));
+@z
+
+@x
+@ When an \.{@@i} line is found in the |cur_file|, we must temporarily
+stop reading it and start reading from the named include file. The
+\.{@@i} line should give a complete file name with or without
+double quotes.
+If the environment variable \.{CWEBINPUTS} is set, or if the compiler flag
+of the same name was defined at compile time,
+\.{CWEB} will look for include files in the directory thus named, if
+it cannot find them in the current directory.
+(Colon-separated paths are not supported.)
+The remainder of the \.{@@i} line after the file name is ignored.
+@y
+@ When an \.{@@i} line is found in the |cur_file|, we must temporarily
+stop reading it and start reading from the named include file. The
+\.{@@i} line should give a complete file name with or without
+double quotes.
+The actual file lookup is done with the help of the \Kpathsea/ library;
+see section~\X91:File lookup with \Kpathsea/\X~for details. % FIXME
+The remainder of the \.{@@i} line after the file name is ignored.
+@^system dependencies@> @.CWEBINPUTS@>
+@z
+
+@x
+ err_print("! Include file name too long"); goto restart;}
+@y
+ err_print(_("! Include file name too long")); goto restart;}
+@z
+
+@x
+ 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;
+ int l; /* length of file name */
+@y
+ char *cur_file_name_end=cur_file_name+max_file_name_length-1;
+ char *k=cur_file_name;
+@z
+
+@x
+ if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
+@y
+ if ((found_filename=kpse_find_cweb(cur_file_name))!=NULL && @|
+ (cur_file=fopen(found_filename,"r"))!=NULL) {
+ /* Copy name for |#line| directives. */
+ if (strlen(found_filename) < max_file_name_length) {
+ if (strcmp(cur_file_name, found_filename))
+ strcpy(cur_file_name, found_filename +
+ ((strncmp(found_filename,"./",2)==0) ? 2 : 0));
+ free(found_filename);
+ } else fatal(_("! Filename too long\n"), found_filename);
+@z
+
+@x
+ kk=getenv("CWEBINPUTS");
+ if (kk!=NULL) {
+ if ((l=strlen(kk))>max_file_name_length-2) too_long();
+ strcpy(temp_file_name,kk);
+ }
+ else {
+#ifdef CWEBINPUTS
+ if ((l=strlen(CWEBINPUTS))>max_file_name_length-2) too_long();
+ strcpy(temp_file_name,CWEBINPUTS);
+#else
+ l=0;
+#endif /* |CWEBINPUTS| */
+ }
+ if (l>0) {
+ if (k+l+2>=cur_file_name_end) too_long();
+@.Include file name ...@>
+ for (; k>= cur_file_name; k--) *(k+l+1)=*k;
+ 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=true;
+ goto restart; /* success */
+ }
+ }
+ include_depth--; err_print("! Cannot open include file"); goto restart;
+@y
+ include_depth--; err_print(_("! Cannot open include file")); goto restart;
+@z
+
+@x
+ err_print("! Change file ended without @@z");
+@y
+ err_print(_("! Change file ended without @@z"));
+@z
+
+@x
+ err_print("! Where is the matching @@z?");
+@y
+ err_print(_("! Where is the matching @@z?"));
+@z
+
+@x
+ err_print("! Change file entry did not match");
+@y
+ err_print(_("! Change file entry did not match"));
+@z
+
+@x
+ if (byte_ptr+l>byte_mem_end) overflow("byte memory");
+ if (name_ptr>=name_dir_end) overflow("name");
+@y
+ if (byte_ptr+l>byte_mem_end) overflow(_("byte memory"));
+ if (name_ptr>=name_dir_end) overflow(_("name"));
+@z
+
+@x
+ if (s+name_len>byte_mem_end) overflow("byte memory");
+ if (name_ptr+1>=name_dir_end) overflow("name");
+@y
+ if (s+name_len>byte_mem_end) overflow(_("byte memory"));
+ if (name_ptr+1>=name_dir_end) overflow(_("name"));
+@z
+
+@x
+ if (name_ptr>=name_dir_end) overflow("name");
+@y
+ if (name_ptr>=name_dir_end) overflow(_("name"));
+@z
+
+@x
+ if (s+name_len>byte_mem_end) overflow("byte memory");
+@y
+ if (s+name_len>byte_mem_end) overflow(_("byte memory"));
+@z
+
+@x
+ fputs("\n! Ambiguous prefix: matches <",stdout);
+@y
+ fputs(_("\n! Ambiguous prefix: matches <"),stdout);
+@z
+
+@x
+ fputs(">\n and <",stdout);
+@y
+ fputs(_(">\n and <"),stdout);
+@z
+
+@x
+ fputs("\n! New name is a prefix of <",stdout);
+@y
+ fputs(_("\n! New name is a prefix of <"),stdout);
+@z
+
+@x
+ fputs("\n! New name extends <",stdout);
+@y
+ fputs(_("\n! New name extends <"),stdout);
+@z
+
+@x
+ fputs("\n! Section name incompatible with <",stdout);
+@y
+ fputs(_("\n! Section name incompatible with <"),stdout);
+@z
+
+@x
+ fputs(">,\n which abbreviates <",stdout);
+@y
+ fputs(_(">,\n which abbreviates <"),stdout);
+@z
+
+@x
+ printf(". (l. %d of change file)\n", change_line);
+else if (include_depth==0) printf(". (l. %d)\n", cur_line);
+ else printf(". (l. %d of include file %s)\n", cur_line, cur_file_name);
+@y
+ printf(_(". (l. %d of change file)\n"), change_line);
+else if (include_depth==0) printf(_(". (l. %d)\n"), cur_line);
+ else printf(_(". (l. %d of include file %s)\n"), cur_line, cur_file_name);
+@z
+
+@x
+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@>
+@y
+On multi-tasking systems like the {\mc AMIGA} it is very convenient to
+know a little bit more about the reasons why a program failed. The four
+levels of return indicated by the |history| value are very suitable for
+this purpose. Here, for instance, we pass the operating system a status
+of~0 if and only if the run was a complete success. Any warning or error
+message will result in a higher return value, so that {\mc AREXX} scripts
+can be made sensitive to these conditions.
+@^system dependencies@>
+
+@d RETURN_OK 0 /* No problems, success */
+@d RETURN_WARN 5 /* A warning only */
+@d RETURN_ERROR 10 /* Something wrong */
+@d RETURN_FAIL 20 /* Complete or severe failure */
+@z
+
+@x
+ @<Print the job |history|@>@;
+@y
+ @<Print the job |history|@>@;
+ @<Remove the temporary file if not already done@>@;
+@z
+
+@x
+ if (history > harmless_message) return EXIT_FAILURE;
+ else return EXIT_SUCCESS;
+@y
+ switch(history) {
+ case harmless_message: return RETURN_WARN;
+ case error_message: return RETURN_ERROR;
+ case fatal_message: return RETURN_FAIL;
+ default: return RETURN_OK;
+ }
+@z
+
+@x
+case spotless: if (show_happiness) puts("(No errors were found.)"); break;
+case harmless_message:
+ puts("(Did you see the warning message above?)"); break;
+case error_message:
+ puts("(Pardon me, but I think I spotted something wrong.)"); break;
+case fatal_message: puts("(That was a fatal error, my friend.)");
+@y
+case spotless:
+ if (show_happiness) puts(_("(No errors were found.)")); break;
+case harmless_message:
+ puts(_("(Did you see the warning message above?)")); break;
+case error_message:
+ puts(_("(Pardon me, but I think I spotted something wrong.)")); break;
+case fatal_message:
+ puts(_("(That was a fatal error, my friend.)"));
+@z
+
+@x
+ printf("\n! Sorry, %s capacity exceeded",t); fatal("","");
+@y
+ printf(_("\n! Sorry, %s capacity exceeded"),t); fatal("","");
+@z
+
+@x
+char scn_file_name[max_file_name_length]; /* name of |scn_file| */
+@y
+char scn_file_name[max_file_name_length]; /* name of |scn_file| */
+char check_file_name[max_file_name_length]; /* name of |check_file| */
+@z
+
+@x
+show_banner=show_happiness=show_progress=make_xrefs=true;@/
+@y
+make_xrefs=true;@/
+temporary_output=true; /* Check temporary output for changes */
+@z
+
+@x
+file. It may have an extension, or it may omit the extension to get |".w"| or
+|".web"| added. The \TEX/ output file name is formed by replacing the \.{CWEB}
+@y
+file. It may have an extension, or it may omit the extension to get |".w"|
+added. The \TEX/ output file name is formed by replacing the \.{CWEB}
+@z
+
+@x
+An omitted change file argument means that |"/dev/null"| should be used,
+when no changes are desired.
+@y
+An omitted change file argument means that |"/dev/null"| or---on non-\UNIX/
+systems the contents of the compile-time variable |DEV_NULL| (\TeX~Live) or
+|_DEV_NULL| (Amiga)---should be used, when no changes are desired.
+@z
+
+@x
+ strcpy(change_file_name,"/dev/null");
+@y
+@#
+#if defined DEV_NULL
+ strncpy(change_file_name,DEV_NULL,max_file_name_length-2);
+ change_file_name[max_file_name_length-2]='\0';
+#elif defined _DEV_NULL
+ strncpy(change_file_name,_DEV_NULL,max_file_name_length-2);
+ change_file_name[max_file_name_length-2]='\0';
+#else
+ strcpy(change_file_name,"/dev/null");
+#endif
+@^system dependencies@>
+@z
+
+@x
+ while (*s) {
+ if (*s=='.') dot_pos=s++;
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+ else s++;
+ }
+@y
+ while (*s) {
+ if (*s=='.') dot_pos=s++;
+ else if (*s==DIR_SEPARATOR || *s==DEVICE_SEPARATOR || *s=='/')
+ dot_pos=NULL,name_pos=++s;
+ else s++;
+ }
+@^system dependencies@>
+@z
+
+@x
+@ 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.
+@y
+@ We use all of |*argv| for the |web_file_name| if there is a |'.'| in it,
+otherwise we add |".w"|.
+@z
+
+@x
+ sprintf(alt_web_file_name,"%s.web",*argv);
+@y
+@z
+
+@x
+@<Handle flag...@>=
+{
+ for(dot_pos=*argv+1;*dot_pos>'\0';dot_pos++)
+@y
+@<Handle flag...@>=
+{
+ if (strcmp("-help",*argv)==0 || strcmp("--help",*argv)==0)
+@.--help@>
+ @<Display help message and |exit|@>@;
+ if (strcmp("-version",*argv)==0 || strcmp("--version",*argv)==0)
+@.--version@>
+ @<Display version information and |exit|@>@;
+ if (strcmp("-verbose",*argv)==0 || strcmp("--verbose",*argv)==0)
+@.--verbose@>
+ { show_banner=show_progress=show_happiness=1; continue; }
+ if (strcmp("-quiet",*argv)==0 || strcmp("--quiet",*argv)==0)
+@.--quiet@>
+ { show_banner=show_progress=show_happiness=0; continue; }
+ for(dot_pos=*argv+1;*dot_pos>'\0';dot_pos++)
+ if (*dot_pos=='v') {
+ show_banner=show_progress=show_happiness=true;
+ } else
+ if (*dot_pos=='q') {
+ show_banner=show_progress=show_happiness=false;
+ } else
+ if (*dot_pos=='d') {
+ if (sscanf(++dot_pos,"%u",&kpathsea_debug)!=1) @<Print usage error...@>@;
+ while (isdigit(*dot_pos)) dot_pos++; /* skip numeric part */
+ dot_pos--; /* reset to final digit */
+ } else
+ if(*dot_pos=='l') {
+ use_language=++dot_pos;
+ break;
+ } else
+@z
+
+@x
+@ @<Print usage error message and quit@>=
+{
+if (program==ctangle)
+ fatal(
+"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
+ ,"");
+@.Usage:@>
+else fatal(
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+ ,"");
+}
+@y
+@ @<Print usage error message and quit@>=
+cb_usage(program==ctangle ? "ctangle" : program==cweave ? "cweave" : "ctwill");
+@.Usage:@>
+@z
+
+@x
+@ @<Complain about arg...@>= fatal("! Filename too long\n", *argv);
+@y
+@ @<Complain about arg...@>= fatal(_("! Filename too long\n"), *argv);
+@z
+
+@x
+FILE *scn_file; /* where list of sections from \.{CWEAVE} goes */
+@y
+FILE *scn_file; /* where list of sections from \.{CWEAVE} goes */
+FILE *check_file; /* temporary output file */
+@z
+
+@x
+FILE *active_file; /* currently active file for \.{CWEAVE} output */
+@y
+FILE *active_file; /* currently active file for \.{CWEAVE} output */
+char *found_filename; /* filename found by |kpse_find_file| */
+@z
+
+@x
+@ @<Scan arguments and open output files@>=
+scan_args();
+if (program==ctangle) {
+ 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,"wb"))==NULL)
+ fatal("! Cannot open output file ", tex_file_name);
+}
+@y
+@ @<Scan arguments and open output files@>=
+scan_args();
+if (program==ctangle) {
+ if ((C_file=fopen(C_file_name,"a"))==NULL)
+ fatal(_("! Cannot open output file "), C_file_name);
+@.Cannot open output file@>
+ else fclose(C_file); /* Test accessability */
+ strcpy(check_file_name,C_file_name);
+ if(check_file_name[0]!='\0') {
+ char *dot_pos=strrchr(check_file_name,'.');
+ if(dot_pos==NULL) strcat(check_file_name,".ttp");
+ else strcpy(dot_pos,".ttp");
+ }
+ if ((C_file=fopen(check_file_name,"wb"))==NULL)
+ fatal(_("! Cannot open output file "), check_file_name);
+@.Cannot open output file@>
+}
+else {
+ if ((tex_file=fopen(tex_file_name,"a"))==NULL)
+ fatal(_("! Cannot open output file "), tex_file_name);
+ else fclose(tex_file); /* Test accessability */
+ strcpy(check_file_name,tex_file_name);
+ if(check_file_name[0]!='\0') {
+ char *dot_pos=strrchr(check_file_name,'.');
+ if(dot_pos==NULL) strcat(check_file_name,".wtp");
+ else strcpy(dot_pos,".wtp");
+ }
+ if ((tex_file=fopen(check_file_name,"wb"))==NULL)
+ fatal(_("! Cannot open output file "), check_file_name);
+}
+@z
+
+@x
+@** Index.
+@y
+@** Extensions to \.{CWEB}. The following sections introduce new or improved
+features that have been created by numerous contributors over the course of a
+quarter century.
+
+Care has been taken to keep the original section numbering intact, so this new
+material should nicely integrate with the original ``\&{85.~Index}.''
+
+@* Language setting. This global variable is set by the argument of the
+`\.{+l}' (or `\.{-l}') command-line option.
+
+@<Global var...@>=
+const char *use_language=""; /* prefix of \.{cwebmac.tex} in \TEX/ output */
+
+
+@* User communication. The |scan_args| and |cb_show_banner| routines and the
+|bindtextdomain| argument string need a few extra variables.
+
+@d max_banner 50
+
+@d PATH_SEPARATOR separators[0]
+@d DIR_SEPARATOR separators[1]
+@d DEVICE_SEPARATOR separators[2]
+
+@<Global var...@>=
+char cb_banner[max_banner];@/
+string texmf_locale;@/
+#ifndef SEPARATORS
+#define SEPARATORS "://"
+#endif
+char separators[]=SEPARATORS;
+
+@* Temporary file output. Before we leave the program we have to make
+sure that the output files are correctly written.
+
+@<Remove the temporary file...@>=
+if(C_file) fclose(C_file);
+if(tex_file) fclose(tex_file);
+if(check_file) fclose(check_file);
+if(strlen(check_file_name)) /* Delete the temporary file in case of a break */
+ remove(check_file_name);
+
+@* Internationalization. If translation catalogs for your personal
+\.{LANGUAGE} are installed at the appropriate place, \.{CTANGLE} and \.{CWEAVE}
+will talk to you in your favorite language. Catalog \.{cweb} contains all
+strings from ``plain \.{CWEB},'' catalog \.{cweb-tl} contains a few extra
+strings specific to the \TeX~Live interface, and catalog \.{web2c-help}
+contains the ``\.{--help}'' texts for \.{CTANGLE} and \.{CWEAVE}.
+@.cweb.mo@>
+@.cweb-tl.mo@>
+@.web2c-help.mo@>
+@.--help@>
+
+If such translation files are not available, you may want to improve this
+system by checking out the sources and translating the strings in files
+\.{cweb.pot}, \.{cweb-tl.pot}, and \.{web2c-help.pot}, and submitting the
+resulting \.{*.po} files to the maintainers at \.{tex-k@@tug.org}.
+
+\medskip \noindent \&{Note to maintainers:} \.{CWEB} in \TeX~Live generally
+does \\{not} set |HAVE_GETTEXT| at build-time, so \.{i18n} is ``off'' by
+default. If you want to create \.{CWEB} executables with NLS support, you
+have to recompile the \TeX~Live sources with a positive value for
+|HAVE_GETTEXT| in \.{comm-w2c.h}. Also you have to ``compile'' the NLS
+catalogs provided for \.{CWEB} in the source tree with \.{msgfmt} and store the
+resulting \.{.mo} files at an appropriate place in the file system.
+
+Plans for \TeX~Live are to store NLS catalogs inside the ``\TeX\ Directory
+Structure'' (TDS) and look them up with the help of the configuration variable
+``|TEXMFLOCALEDIR|,'' which should contain a single absolute path definition.
+Below we use the \Kpathsea/ function |kpse_var_expand| to evaluate this
+variable from various origins and redirect the ``GNU~gettext utilities''
+to a possibly different location than the canonical \.{/usr/share/locale}.
+
+There are several ways to set |TEXMFLOCALEDIR|:
+\smallskip
+{\parindent5em
+\item{(a)} a user-set environment variable \.{TEXMFLOCALEDIR}\hfil\break
+ (overridden by \.{TEXMFLOCALEDIR\_cweb});
+\item{(b)} a line in \Kpathsea/ configuration file \.{texmf.cnf},\hfil\break
+ e.g., \.{TEXMFLOCALEDIR=\$TEXMFMAIN/locale}\hfil\break
+ or \.{TEXMFLOCALEDIR.cweb=\$TEXMFMAIN/locale}.\par}
+
+@<Include files@>=
+#if HAVE_GETTEXT
+#include <locale.h> /* |@!LC_MESSAGES|, |@!LC_CTYPE| */
+#else
+#define setlocale(A,B) ""
+#define bindtextdomain(A,B) ""
+#define textdomain(A) ""
+#endif
+
+@ @<Set locale...@>=
+setlocale(LC_MESSAGES, setlocale(LC_CTYPE, ""));
+texmf_locale = kpse_var_expand ("${TEXMFLOCALEDIR}");
+
+bindtextdomain("cweb",
+ bindtextdomain("cweb-tl",
+ bindtextdomain("web2c-help", @|
+ strcmp(texmf_locale, "") ?
+ texmf_locale : "/usr/share/locale")));
+
+free(texmf_locale);
+textdomain("cweb"); /* the majority of |"strings"| come from ``plain \.{CWEB}'' */
+@.cweb.mo@>
+
+@* File lookup with \Kpathsea/. The \.{CTANGLE} and \.{CWEAVE} programs from
+the original \.{CWEB} package use the compile-time default directory or the
+value of the environment variable \.{CWEBINPUTS} as an alternative place to be
+searched for files, if they could not be found in the current directory.
+
+This version uses the \Kpathsea/ mechanism for searching files.
+The directories to be searched for come from three sources:
+\smallskip
+{\parindent5em
+\item{(a)} a user-set environment variable \.{CWEBINPUTS}
+ (overridden by \.{CWEBINPUTS\_cweb});
+\item{(b)} a line in \Kpathsea/ configuration file \.{texmf.cnf},\hfil\break
+ e.g., \.{CWEBINPUTS=\$TEXMFDOTDIR:\$TEXMF/texmf/cweb//}\hfil\break
+ or \.{CWEBINPUTS.cweb=\$TEXMFDOTDIR:\$TEXMF/texmf/cweb//};
+\item{(c)} compile-time default directories (specified in
+ \.{texmf.in}),\hfil\break
+ i.e., \.{\$TEXMFDOTDIR:\$TEXMF/texmf/cweb//}.\par}
+@.CWEBINPUTS@>
+
+@s const_string int
+@s string int
+
+@d kpse_find_cweb(name) kpse_find_file(name,kpse_cweb_format,true)
+
+@<Include files@>=
+typedef bool boolean;
+#define HAVE_BOOLEAN
+#include <kpathsea/kpathsea.h> /* include every \Kpathsea/ header;
+ |@!kpathsea_debug|, |@!const_string|, |@!string| */
+#include <w2c/config.h> /* \&{integer} */
+#include <lib/lib.h> /* |@!versionstring| */
+
+@ We set |kpse_program_name| to `\.{cweb}'. This means if the variable
+\.{CWEBINPUTS.cweb} is present in \.{texmf.cnf} (or \.{CWEBINPUTS\_cweb}
+in the environment) its value will be used as the search path for filenames.
+This allows different flavors of \.{CWEB} to have different search paths.
+@.CWEBINPUTS@>
+
+@<Set up |PROGNAME| feature and initialize the search path mechanism@>=
+kpse_set_program_name(argv[0], "cweb");
+
+@ When the files you expect are not found, the thing to do is to enable
+\Kpathsea/ runtime debugging by assigning to the |kpathsea_debug| variable a
+small number via the `\.{-d}' option. The meaning of this number is shown
+below. To set more than one debugging option, simply sum the corresponding
+numbers.
+\medskip
+\halign{\hskip5em\tt\hfil#&&\qquad\rm#\hfil\cr
+ 1&report `\.{stat}' calls\cr
+ 2&report lookups in all hash tables\cr
+ 4&report file openings and closings\cr
+ 8&report path information\cr
+16&report directory list\cr
+32&report on each file search\cr
+64&report values of variables being looked up\cr}
+\medskip
+Debugging output is always written to |stderr|, and begins with the string
+`\.{kdebug:}'.
+
+@* System dependent changes. The most volatile stuff comes at the very end.
+
+Modules for dealing with help messages and version info.
+
+@<Include files@>=
+#define CWEB
+#include "help.h" /* |@!CTANGLEHELP|, |@!CWEAVEHELP|, |@!CTWILLHELP| */
+
+@ @<Display help message and |exit|@>=
+cb_usagehelp(program==ctangle ? CTANGLEHELP :
+ program==cweave ? CWEAVEHELP : CTWILLHELP, NULL);
+@.--help@>
+
+@ Special variants from Web2c's `\.{lib/usage.c}', adapted for
+\.{i18n}/\.{t10n}. We simply filter the strings through the catalogs
+(if available).
+
+@<Predecl...@>=
+static void cb_usage (const_string str);@/
+static void cb_usagehelp (const_string *message, const_string bug_email);@/
+
+@ @c
+static void cb_usage (const_string str)
+{
+ textdomain("cweb-tl");
+@.cweb-tl.mo@>
+ fprintf(stderr, _("%s: Need one to three file arguments.\n"), str);
+ fprintf(stderr, _("Try `%s --help' for more information.\n"), str);
+@.--help@>
+ textdomain("cweb");
+@.cweb.mo@>
+ history=fatal_message; exit(wrap_up());
+}
+
+static void cb_usagehelp (const_string *message, const_string bug_email)
+{
+ if (!bug_email)
+ bug_email = "tex-k@@tug.org";
+ textdomain("web2c-help");
+@.web2c-help.mo@>
+ while (*message) {
+ printf("%s\n", strcmp("", *message) ? _(*message) : *message);
+ ++message;
+ }
+ textdomain("cweb-tl");
+@.cweb-tl.mo@>
+ printf(_("\nEmail bug reports to %s.\n"), bug_email);
+ textdomain("cweb");
+@.cweb.mo@>
+ history=spotless; exit(wrap_up());
+}
+
+@ The version information will not be translated, it uses a generic text
+template in English.
+
+@<Display version information and |exit|@>=
+printversionandexit(cb_banner,
+ program == ctwill ? "Donald E. Knuth" : "Silvio Levy and Donald E. Knuth",
+ NULL, "Contemporary development on https://github.com/ascherer/cweb.\n");
+@.--version@>
+
+@ But the ``banner'' is, at least the first part.
+
+@c
+void cb_show_banner (void)
+{
+ assert(cb_banner[0]!='\0');
+ textdomain("cweb-tl");
+@.cweb-tl.mo@>
+ printf("%s%s\n", _(cb_banner), versionstring);
+ textdomain("cweb");
+@.cweb.mo@>
+}
+
+@** Index.
+@z