1 % Kpathsea changes for CWEB by Wlodek Bzyl and Olaf Weber
2 % Copyright 2002 Wlodek Bzyl and Olaf Weber
3 % This file is in the Public Domain.
6 \def\title{Common code for CTANGLE and CWEAVE (Version 3.64)}
7 \def\topofcontents{\null\vfill
8 \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and
11 \centerline{(Version 3.64)}
14 \def\Kpathsea/{{\mc KPATHSEA\spacefactor1000}}
15 \def\title{Common code for CTANGLE and CWEAVE (Version 3.64k)}
16 \def\topofcontents{\null\vfill
17 \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and
20 \centerline{(Version 3.64k)}
24 This change can not be applied when `tie' is used
25 (TOC file can not be typeset).
30 %\let\maybe=\iffalse % print only changed modules
36 @<Predeclaration of procedures@>@/
39 @<Predeclaration of procedures@>@/
43 We use the definition from `kpathsea/types.h':
45 typedef enum { false = 0, true = 1 } boolean;
47 Note that this definition also occurs in common.h.
49 typedef short boolean;
63 @<Initialize pointers@>;
65 @<Initialize pointers@>;
66 @<Set up |PROGNAME| feature and initialize the search path mechanism@>;
82 @d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */
84 @d buf_size 1000 /* for \.{CWEAVE} and \.{CTANGLE} */
88 @d xisspace(c) (isspace(c)&&((unsigned char)c<0200))
89 @d xisupper(c) (isupper(c)&&((unsigned char)c<0200))
91 @d xisspace(c) (isspace((unsigned char)c)&&((unsigned char)c<0200))
92 @d xisupper(c) (isupper((unsigned char)c)&&((unsigned char)c<0200))
98 int input_ln(fp) /* copies a line into |buffer| or returns 0 */
99 FILE *fp; /* what file to read from */
101 int input_ln (FILE *fp) /* copies a line into |buffer| or returns 0 */
105 if ((*(k++) = c) != ' ') limit = k;
107 if ((*(k++) = c) != ' ' && c!='\r') limit = k;
112 @x l.207 - max_file_name_length is way too small.
113 @d max_file_name_length 60
115 @d max_file_name_length 1024
118 @x l.221 - no alt_web_file_name needed.
119 char alt_web_file_name[max_file_name_length]; /* alternate name to try */
127 prime_the_change_buffer()
130 prime_the_change_buffer (void)
134 if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
136 if (xisupper(buffer[1])) buffer[1]=tolower((unsigned char)buffer[1]);
143 check_change() /* switches to |change_file| if the buffers match */
146 check_change (void) /* switches to |change_file| if the buffers match */
150 char xyz_code=xisupper(buffer[1])? tolower(buffer[1]): buffer[1];
152 char xyz_code=xisupper(buffer[1])? tolower((unsigned char)buffer[1]): buffer[1];
166 if ((web_file=fopen(web_file_name,"r"))==NULL) {
167 strcpy(web_file_name,alt_web_file_name);
168 if ((web_file=fopen(web_file_name,"r"))==NULL)
169 fatal("! Cannot open input file ", web_file_name);
172 if ((found_filename=kpse_find_cweb(web_file_name))==NULL ||
173 (web_file=fopen(found_filename,"r"))==NULL) {
174 fatal("! Cannot open input file ", web_file_name);
175 } else if (strlen(found_filename) < max_file_name_length) {
176 strcpy(web_file_name, found_filename);
177 free(found_filename);
182 if ((change_file=fopen(change_file_name,"r"))==NULL)
183 fatal("! Cannot open change file ", change_file_name);
185 if ((found_filename=kpse_find_cweb(change_file_name))==NULL ||
186 (change_file=fopen(found_filename,"r"))==NULL) {
187 fatal("! Cannot open change file ", change_file_name);
188 } else if (strlen(found_filename) < max_file_name_length) {
189 strcpy(change_file_name, found_filename);
190 free(found_filename);
195 @d max_sections 2000 /* number of identifiers, strings, section names;
197 @d max_sections 10239 /* number of identifiers, strings, section names;
203 int get_line() /* inputs the next line */
205 int get_line (void) /* inputs the next line */
211 #include <stdlib.h> /* declaration of |getenv| and |exit| */
213 #include <kpathsea/kpathsea.h> /* include every \Kpathsea/ header */
214 #include <stdlib.h> /* declaration of |getenv| and |exit| */
217 @ The \.{ctangle} and \.{cweave} programs from the original \.{CWEB}
218 package use the compile-time default directory or the value of the
219 environment variable \.{CWEBINPUTS} as an alternative place to be
220 searched for files, if they could not be found in the current
223 This version uses the \Kpathsea/ mechanism for searching files.
224 The directories to be searched for come from three sources:
226 (a)~a user-set environment variable \.{CWEBINPUTS}
227 (overriden by \.{CWEBINPUTS\_cweb});\par
228 (b)~a line in \Kpathsea/ configuration file \.{texmf.cnf},\hfil\break
229 e.g. \.{CWEBINPUTS=.:$TEXMF/texmf/cweb//}
230 or \.{CWEBINPUTS.cweb=.:$TEXMF/texmf/cweb//};\hangindent=2\parindent\par
231 (c)~compile-time default directories \.{.:$TEXMF/texmf/cweb//}
232 (specified in \.{texmf.in}).
235 @d kpse_find_cweb(name) kpse_find_file(name,kpse_cweb_format,true)
237 @ The simple file searching is replaced by `path searching' mechanism
238 that \Kpathsea/ library provides.
240 We set |kpse_program_name| to a |"cweb"|. This means if the
241 variable |CWEBINPUTS.cweb| is present in \.{texmf.cnf} (or |CWEBINPUTS_cweb|
242 in the environment) its value will be used as the search path for
243 filenames. This allows different flavors of \.{CWEB} to have
244 different search paths.
246 FIXME: Not sure this is the best way to go about this.
248 @<Set up |PROGNAME| feature and initialize the search path mechanism@>=
249 kpse_set_program_name(argv[0], "cweb");
256 char temp_file_name[max_file_name_length];
257 char *cur_file_name_end=cur_file_name+max_file_name_length-1;
258 char *k=cur_file_name, *kk;
259 int l; /* length of file name */
261 char *cur_file_name_end=cur_file_name+max_file_name_length-1;
262 char *k=cur_file_name;
266 if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
268 if ((found_filename=kpse_find_cweb(cur_file_name))!=NULL &&
269 (cur_file=fopen(found_filename,"r"))!=NULL) {
270 /* Copy name for #line directives. */
271 if (strlen(found_filename) < max_file_name_length) {
272 strcpy(cur_file_name, found_filename);
273 free(found_filename);
277 Replaced by Kpathsea `kpse_find_file'
280 kk=getenv("CWEBINPUTS");
282 if ((l=strlen(kk))>max_file_name_length-2) too_long();
283 strcpy(temp_file_name,kk);
287 if ((l=strlen(CWEBINPUTS))>max_file_name_length-2) too_long();
288 strcpy(temp_file_name,CWEBINPUTS);
291 #endif /* |CWEBINPUTS| */
294 if (k+l+2>=cur_file_name_end) too_long();
295 @.Include file name ...@>
296 for (; k>= cur_file_name; k--) *(k+l+1)=*k;
297 strcpy(cur_file_name,temp_file_name);
298 cur_file_name[l]='/'; /* \UNIX/ pathname separator */
299 if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
300 cur_line=0; print_where=1;
301 goto restart; /* success */
310 if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
312 if (xisupper(buffer[1])) buffer[1]=tolower((unsigned char)buffer[1]);
318 check_complete (void) {
322 @d max_bytes 90000 /* the number of bytes in identifiers,
324 @d max_bytes 1000000 /* the number of bytes in identifiers,
328 @d max_names 4000 /* number of identifiers, strings, section names;
330 @d max_names 10239 /* number of identifiers, strings, section names;
334 @d hash_size 353 /* should be prime */
336 @d hash_size 8501 /* should be prime */
343 extern int names_match();
345 @ @<External functions@>=
346 extern int names_match (name_pointer, const char*, int, char);
352 id_lookup(first,last,t) /* looks up a string in the identifier table */
353 char *first; /* first character of string */
354 char *last; /* last character of string plus one */
355 char t; /* the |ilk|; used by \.{CWEAVE} only */
357 /* looks up a string in the identifier table */
358 id_lookup (const char *first, const char *last, char t)
362 char *i=first; /* position in |buffer| */
364 const char *i=first; /* position in |buffer| */
367 @x l.668 - rename local var, not to shadow global
368 int h; /* hash code */
370 int h; /* hash code */
375 @x l.684 - use renamed local var
377 while (++i<last) h=(h+h+(int)((unsigned char)*i)) % hash_size;
380 while (++i<last) h=(h+h+(int)((unsigned char)*i)) % hash_size;
385 @x l.692 - use renamed local var
391 @x l.696 - use renamed local var
392 p->link=hash[h]; hash[h]=p; /* insert |p| at beginning of hash list */
394 p->link=hash[h]; hash[h]=p; /* insert |p| at beginning of hash list */
403 @<External functions@>=
404 extern void init_p (name_pointer p, char t);
410 print_section_name(p)
413 print_section_name (name_pointer p)
419 sprint_section_name(dest,p)
423 sprint_section_name (char *dest, name_pointer p)
434 print_prefix_name (name_pointer p)
440 int web_strcmp(j,j_len,k,k_len) /* fuller comparison than |strcmp| */
441 char *j, *k; /* beginning of first and second strings */
442 int j_len, k_len; /* length of strings */
444 /* fuller comparison than |strcmp| */
446 web_strcmp (char *j, int j_len, char *k, int k_len)
449 @x l.830 -- rename local vars, not to shadow math function
450 char *j1=j+j_len, *k1=k+k_len;
451 while (k<k1 && j<j1 && *j==*k) k++, j++;
452 if (k==k1) if (j==j1) return equal;
453 else return extension;
454 else if (j==j1) return prefix;
456 char *j1=j+j_len, *k1=k+k_len;
457 while (k<k1 && j<j1 && *j==*k) k++, j++;
458 if (k==k1) if (j==j1) return equal;
459 else return extension;
460 else if (j==j1) return prefix;
467 extern void init_node();
469 @<External functions@>=
470 extern void init_node (name_pointer node);
477 add_section_name(par,c,first,last,ispref) /* install a new node in the tree */
478 name_pointer par; /* parent of new node */
479 int c; /* right or left? */
480 char *first; /* first character of section name */
481 char *last; /* last character of section name, plus one */
482 int ispref; /* are we adding a prefix or a full name? */
485 add_section_name (name_pointer par, int c, char *first, char *last,
486 int ispref) /* install a new node in the tree */
493 extend_section_name(p,first,last,ispref)
494 name_pointer p; /* name to be extended */
495 char *first; /* beginning of extension text */
496 char *last; /* one beyond end of extension text */
497 int ispref; /* are we adding a prefix or a full name? */
500 extend_section_name (name_pointer p, char *first, char *last, int ispref)
506 section_lookup(first,last,ispref) /* find or install section name in tree */
507 char *first, *last; /* first and last characters of new name */
508 int ispref; /* is the new name a prefix or a full name? */
510 /* find or install section name in tree */
511 section_lookup (char *first, char *last, int ispref)
517 int section_name_cmp();
519 static int section_name_cmp (char**, int, name_pointer);
525 int section_name_cmp(pfirst,len,r)
526 char **pfirst; /* pointer to beginning of comparison string */
527 int len; /* length of string */
528 name_pointer r; /* section name being compared */
531 section_name_cmp (char **pfirst, int len, name_pointer r)
540 @<External functions@>=
541 extern void err_print (const char*);
547 err_print(s) /* prints `\..' and location of error message */
550 err_print (const char *s) /* prints `\..' and location of error message */
558 extern void print_stats();
560 @<External functions@>=
561 extern int wrap_up (void);
562 extern void print_stats (void);
577 void fatal(), overflow();
579 @<External functions@>=
580 extern void fatal (const char*, const char*);
581 extern void overflow (const char*);
590 fatal (const char *s, const char *t)
599 overflow (const char *t)
605 the names of those files. Most of the 128 flags are undefined but available
606 for future extensions.
608 the names of those files. Most of the 128 flags are undefined but available
609 for future extensions.
611 We use `kpathsea' library functions to find literate sources and
612 NLS configuration files. When the files you expect are not
613 being found, the thing to do is to enable `kpathsea' runtime
614 debugging by assigning to |kpathsea_debug| variable a small number
615 via `\.{-d}' option. The meaning of number is shown below. To set
616 more than one debugging options sum the corresponding numbers.
617 $$\halign{\hskip5em\tt\hfil#&&\qquad\tt#\cr
618 1&report `\.{stat}' calls\cr
619 2&report lookups in all hash tables\cr
620 4&report file openings and closings\cr
621 8&report path information\cr
622 16&report directory list\cr
623 32&report on each file search\cr
624 64&report values of variables being looked up\cr}$$
625 Debugging output is always written to |stderr|, and begins with the string
630 @d show_happiness flags['h'] /* should lack of errors be announced? */
632 @d show_happiness flags['h'] /* should lack of errors be announced? */
633 @d show_kpathsea_debug flags['d']
634 /* should results of file searching be shown? */
638 show_banner=show_happiness=show_progress=1;
640 show_banner=show_happiness=show_progress=1;
648 static void scan_args (void);
665 @x l.1282 - use a define for /dev/null
666 if (found_change<=0) strcpy(change_file_name,"/dev/null");
668 if (found_change<=0) strcpy(change_file_name,DEV_NULL);
671 @x l.1302 - no alt_web_file_name
672 sprintf(alt_web_file_name,"%s.web",*argv);
680 @ @<Handle flag...@>=
683 @ @<Handle flag...@>=
685 if (strcmp("-help",*argv)==0 || strcmp("--help",*argv)==0)
686 @<Display help message and exit@>;
687 if (strcmp("-version",*argv)==0 || strcmp("--version",*argv)==0)
688 @<Display version information and exit@>;
696 if (sscanf(*argv+2,"%u",&kpathsea_debug)!=1) @<Print usage error...@>;
700 flags[*dot_pos]=flag_change;
702 flags[(unsigned char)*dot_pos]=flag_change;
708 if (program==ctangle)
710 "! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
714 "! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
717 if (program==ctangle) {
718 fprintf(stderr, "ctangle: Need one to three file arguments.\n");
721 fprintf(stderr, "cweave: Need one to three file arguments.\n");
729 FILE *active_file; /* currently active file for \.{CWEAVE} output */
731 FILE *active_file; /* currently active file for \.{CWEAVE} output */
732 char *found_filename; /* filename found by |kpse_find_file| */
737 @x l.1380 Use binary mode for output files
738 if ((C_file=fopen(C_file_name,"w"))==NULL)
740 if ((C_file=fopen(C_file_name,"wb"))==NULL)
743 @x l.1386 Use binary mode for output files
744 if ((tex_file=fopen(tex_file_name,"w"))==NULL)
746 if ((tex_file=fopen(tex_file_name,"wb"))==NULL)
753 @ We predeclare several standard system functions here instead of including
754 their system header files, because the names of the header files are not as
755 standard as the names of the functions. (For example, some \CEE/ environments
756 have \.{<string.h>} where others have \.{<strings.h>}.)
759 extern int strlen(); /* length of string */
760 extern int strcmp(); /* compare strings lexicographically */
761 extern char* strcpy(); /* copy one string to another */
762 extern int strncmp(); /* compare up to $n$ string characters */
763 extern char* strncpy(); /* copy up to $n$ string characters */
765 @ We declare some more prototypes for exported function in cases where this
766 could not be done easily without changing section numbers.
768 @<External functions@>=
769 extern void common_init (void);
770 extern int input_ln (FILE *fp);
771 extern void reset_input (void);
772 extern int get_line (void);
773 extern void check_complete (void);
774 extern name_pointer id_lookup (const char *first, const char *last, char t);
775 extern void print_section_name (name_pointer p);
776 extern void sprint_section_name (char *dest, name_pointer p);
777 extern name_pointer section_lookup (char *first, char *last, int ispref);
783 @** External functions. In order to allow for type checking we create a
784 header file \.{cweb.h} containing the declaration of all functions defined
785 in \.{common.w} and used in \.{ctangle.w} and \.{cweave.w} or vice versa.
788 @=/* Prototypes for functions, either@>
789 @= * declared in common.w and used in ctangle.w and cweave.w, or@>
790 @= * used in common.w and declared in ctangle.w and cweave.w. */@>
791 @<External functions@>@;
792 extern const char *versionstring;
794 @** System dependent changes.
796 @ Modules for dealing with help messages and version info.
798 @<Display help message and exit@>=
799 usagehelp(program==ctangle ? CTANGLEHELP : CWEAVEHELP, NULL);
802 @ Will have to change these if the version numbers change (ouch).
804 @d ctangle_banner "This is CTANGLE, Version 3.64"
805 @d cweave_banner "This is CWEAVE, Version 3.64"
807 @<Display version information and exit@>=
808 printversionandexit((program==ctangle ? ctangle_banner : cweave_banner),
809 "Silvio Levy and Donald E. Knuth", NULL, NULL);