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.
4
5@x l.20
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
9    {\ttitlefont CWEAVE}}
10  \vskip 15pt
11  \centerline{(Version 3.64)}
12  \vfill}
13@y
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
18    {\ttitlefont CWEAVE}}
19  \vskip 15pt
20  \centerline{(Version 3.64k)}
21  \vfill}
22@z
23
24This change can not be applied when `tie' is  used
25(TOC file can not be typeset).
26
27%@x l.42
28%\let\maybe=\iftrue
29%@y
30%\let\maybe=\iffalse % print only changed modules
31%@z
32
33Section 1.
34
35@x l.63
36@<Predeclaration of procedures@>@/
37@y
38#include "cweb.h"
39@<Predeclaration of procedures@>@/
40@z
41
42Section 2.
43We use the definition from `kpathsea/types.h':
44
45  typedef enum { false = 0, true = 1 } boolean;
46
47Note that this definition also occurs in common.h.
48@x l.74
49typedef short boolean;
50@y
51@z
52
53
54Section 4.
55
56@x l.91
57common_init()
58@y
59common_init (void)
60@z
61
62@x l.93
63  @<Initialize pointers@>;
64@y
65  @<Initialize pointers@>;
66  @<Set up |PROGNAME| feature and initialize the search path mechanism@>;
67@z
68
69Section 5.
70
71@x l.103
72#include <ctype.h>
73@y
74#define CWEB
75#include "cpascal.h"
76#include <ctype.h>
77@z
78
79Section 7.
80
81@x l.153
82@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */
83@y
84@d buf_size 1000 /* for \.{CWEAVE} and \.{CTANGLE} */
85@z
86
87@x l.156
88@d xisspace(c) (isspace(c)&&((unsigned char)c<0200))
89@d xisupper(c) (isupper(c)&&((unsigned char)c<0200))
90@y
91@d xisspace(c) (isspace((unsigned char)c)&&((unsigned char)c<0200))
92@d xisupper(c) (isupper((unsigned char)c)&&((unsigned char)c<0200))
93@z
94
95Section 9.
96
97@x l.173
98int input_ln(fp) /* copies a line into |buffer| or returns 0 */
99FILE *fp; /* what file to read from */
100@y
101int input_ln (FILE *fp) /* copies a line into |buffer| or returns 0 */
102@z
103
104@x l.181
105    if ((*(k++) = c) != ' ') limit = k;
106@y
107    if ((*(k++) = c) != ' ' && c!='\r') limit = k;
108@z
109
110Section 10.
111
112@x l.207 - max_file_name_length is way too small.
113@d max_file_name_length 60
114@y
115@d max_file_name_length 1024
116@z
117
118@x l.221 - no alt_web_file_name needed.
119char alt_web_file_name[max_file_name_length]; /* alternate name to try */
120@y
121@z
122
123Section 12.
124
125@x l.252
126void
127prime_the_change_buffer()
128@y
129static void
130prime_the_change_buffer (void)
131@z
132
133@x l.271
134  if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
135@y
136  if (xisupper(buffer[1])) buffer[1]=tolower((unsigned char)buffer[1]);
137@z
138
139Section 16.
140
141@x l.321
142void
143check_change() /* switches to |change_file| if the buffers match */
144@y
145static void
146check_change (void) /* switches to |change_file| if the buffers match */
147@z
148
149@x l.340
150      char xyz_code=xisupper(buffer[1])? tolower(buffer[1]): buffer[1];
151@y
152      char xyz_code=xisupper(buffer[1])? tolower((unsigned char)buffer[1]): buffer[1];
153@z
154
155Section 18.
156
157@x l.380
158reset_input()
159@y
160reset_input (void)
161@z
162
163Section 19.
164
165@x l.394
166if ((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);
170}
171@y
172if ((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);
178}
179@z
180
181@x l.402
182if ((change_file=fopen(change_file_name,"r"))==NULL)
183       fatal("! Cannot open change file ", change_file_name);
184@y
185if ((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);
191}
192@z
193
194@x l.415
195@d max_sections 2000 /* number of identifiers, strings, section names;
196@y
197@d max_sections 10239 /* number of identifiers, strings, section names;
198@z
199
200Section 21.
201
202@x l.427
203int get_line() /* inputs the next line */
204@y
205int get_line (void) /* inputs the next line */
206@z
207
208Section 22.
209
210@x l.472
211#include <stdlib.h> /* declaration of |getenv| and |exit| */
212@y
213#include <kpathsea/kpathsea.h> /* include every \Kpathsea/ header */
214#include <stdlib.h> /* declaration of |getenv| and |exit| */
215#include "help.h"
216
217@ The \.{ctangle} and \.{cweave} programs from the original \.{CWEB}
218package use the compile-time default directory or the value of the
219environment variable \.{CWEBINPUTS} as an alternative place to be
220searched for files, if they could not be found in the current
221directory.
222
223This version uses the \Kpathsea/ mechanism for searching files.
224The directories to be searched for come from three sources:
225
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}).
233
234
235@d kpse_find_cweb(name) kpse_find_file(name,kpse_cweb_format,true)
236
237@ The simple file searching is replaced by `path searching' mechanism
238that \Kpathsea/ library provides.
239
240We set |kpse_program_name| to a |"cweb"|.  This means if the
241variable |CWEBINPUTS.cweb| is present in \.{texmf.cnf} (or |CWEBINPUTS_cweb|
242in the environment) its value will be used as the search path for
243filenames.  This allows different flavors of \.{CWEB} to have
244different search paths.
245
246FIXME: Not sure this is the best way to go about this.
247
248@<Set up |PROGNAME| feature and initialize the search path mechanism@>=
249kpse_set_program_name(argv[0], "cweb");
250@z
251
252
253Section 23.
254
255@x l.475
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 */
260@y
261  char *cur_file_name_end=cur_file_name+max_file_name_length-1;
262  char *k=cur_file_name;
263@z
264
265@x l.489
266  if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
267@y
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);
274    }
275@z
276
277Replaced by Kpathsea `kpse_find_file'
278
279@x l.493
280  kk=getenv("CWEBINPUTS");
281  if (kk!=NULL) {
282    if ((l=strlen(kk))>max_file_name_length-2) too_long();
283    strcpy(temp_file_name,kk);
284  }
285  else {
286#ifdef CWEBINPUTS
287    if ((l=strlen(CWEBINPUTS))>max_file_name_length-2) too_long();
288    strcpy(temp_file_name,CWEBINPUTS);
289#else
290    l=0;
291#endif /* |CWEBINPUTS| */
292  }
293  if (l>0) {
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 */
302    }
303  }
304@y
305@z
306
307Section 26.
308
309@x l.553
310      if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
311@y
312      if (xisupper(buffer[1])) buffer[1]=tolower((unsigned char)buffer[1]);
313@z
314
315@x l.571
316check_complete(){
317@y
318check_complete (void) {
319@z
320
321@x l.589
322@d max_bytes 90000 /* the number of bytes in identifiers,
323@y
324@d max_bytes 1000000 /* the number of bytes in identifiers,
325@z
326
327@x l.591
328@d max_names 4000 /* number of identifiers, strings, section names;
329@y
330@d max_names 10239 /* number of identifiers, strings, section names;
331@z
332
333@x l.642
334@d hash_size 353 /* should be prime */
335@y
336@d hash_size 8501 /* should be prime */
337@z
338
339Section 33.
340
341@x l.650
342@ @<Predec...@>=
343extern int names_match();
344@y
345@ @<External functions@>=
346extern int names_match (name_pointer, const char*, int, char);
347@z
348
349Section 35.
350
351@x l.661
352id_lookup(first,last,t) /* looks up a string in the identifier table */
353char *first; /* first character of string */
354char *last; /* last character of string plus one */
355char t; /* the |ilk|; used by \.{CWEAVE} only */
356@y
357/* looks up a string in the identifier table */
358id_lookup (const char *first, const char *last, char t)
359@z
360
361@x l.667
362  char *i=first; /* position in |buffer| */
363@y
364  const char *i=first; /* position in |buffer| */
365@z
366
367@x l.668 - rename local var, not to shadow global
368  int h; /* hash code */
369@y
370  int h; /* hash code */
371@z
372
373Section 36.
374
375@x l.684 - use renamed local var
376h=(unsigned char)*i;
377while (++i<last) h=(h+h+(int)((unsigned char)*i)) % hash_size;
378@y
379h=(unsigned char)*i;
380while (++i<last) h=(h+h+(int)((unsigned char)*i)) % hash_size;
381@z
382
383Section 37.
384
385@x l.692 - use renamed local var
386p=hash[h];
387@y
388p=hash[h];
389@z
390
391@x l.696 - use renamed local var
392  p->link=hash[h]; hash[h]=p; /* insert |p| at beginning of hash list */
393@y
394  p->link=hash[h]; hash[h]=p; /* insert |p| at beginning of hash list */
395@z
396
397Section 38.
398
399@x l.703
400@<Pred...@>=
401void init_p();
402@y
403@<External functions@>=
404extern void init_p (name_pointer p, char t);
405@z
406
407Section 42.
408
409@x l.766
410print_section_name(p)
411name_pointer p;
412@y
413print_section_name (name_pointer p)
414@z
415
416Section 43.
417
418@x l.785
419sprint_section_name(dest,p)
420  char*dest;
421  name_pointer p;
422@y
423sprint_section_name (char *dest, name_pointer p)
424@z
425
426Section 44.
427
428@x l.805
429void
430print_prefix_name(p)
431name_pointer p;
432@y
433static void
434print_prefix_name (name_pointer p)
435@z
436
437Section 45.
438
439@x l.826
440int 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 */
443@y
444/* fuller comparison than |strcmp| */
445static int
446web_strcmp (char *j, int j_len, char *k, int k_len)
447@z
448
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;
455@y
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;
461@z
462
463Section 46.
464
465@x l.852
466@<Prede...@>=
467extern void init_node();
468@y
469@<External functions@>=
470extern void init_node (name_pointer node);
471@z
472
473Section 47.
474
475@x l.856
476name_pointer
477add_section_name(par,c,first,last,ispref) /* install a new node in the tree */
478name_pointer par; /* parent of new node */
479int c; /* right or left? */
480char *first; /* first character of section name */
481char *last; /* last character of section name, plus one */
482int ispref; /* are we adding a prefix or a full name? */
483@y
484static name_pointer
485add_section_name (name_pointer par, int c, char *first, char *last,
486                  int ispref)  /* install a new node in the tree */
487@z
488
489Section 48.
490
491@x l.885
492void
493extend_section_name(p,first,last,ispref)
494name_pointer p; /* name to be extended */
495char *first; /* beginning of extension text */
496char *last; /* one beyond end of extension text */
497int ispref; /* are we adding a prefix or a full name? */
498@y
499static void
500extend_section_name (name_pointer p, char *first, char *last, int ispref)
501@z
502
503Section 49.
504
505@x l.914
506section_lookup(first,last,ispref) /* find or install section name in tree */
507char *first, *last; /* first and last characters of new name */
508int ispref; /* is the new name a prefix or a full name? */
509@y
510/* find or install section name in tree */
511section_lookup (char *first, char *last, int ispref)
512@z
513
514Section 53.
515
516@x l.1018
517int section_name_cmp();
518@y
519static int section_name_cmp (char**, int, name_pointer);
520@z
521
522Section 54.
523
524@x l.1021
525int section_name_cmp(pfirst,len,r)
526char **pfirst; /* pointer to beginning of comparison string */
527int len; /* length of string */
528name_pointer r; /* section name being compared */
529@y
530static int
531section_name_cmp (char **pfirst, int len, name_pointer r)
532@z
533
534Section 57.
535
536@x l.1092
537@<Predecl...@>=
538void  err_print();
539@y
540@<External functions@>=
541extern void  err_print (const char*);
542@z
543
544Section 58.
545
546@x l.1098
547err_print(s) /* prints `\..' and location of error message */
548char *s;
549@y
550err_print (const char *s) /* prints `\..' and location of error message */
551@z
552
553Section 60.
554
555@x l.1140
556@<Prede...@>=
557int wrap_up();
558extern void print_stats();
559@y
560@<External functions@>=
561extern int wrap_up (void);
562extern void print_stats (void);
563@z
564
565Section 61.
566
567@x l.1151
568int wrap_up() {
569@y
570int wrap_up (void) {
571@z
572
573Section 63.
574
575@x l.1173
576@<Predec...@>=
577void fatal(), overflow();
578@y
579@<External functions@>=
580extern void fatal (const char*, const char*);
581extern void overflow (const char*);
582@z
583
584Section 64.
585
586@x l.1180
587fatal(s,t)
588  char *s,*t;
589@y
590fatal (const char *s, const char *t)
591@z
592
593Section 65.
594
595@x l.1191
596overflow(t)
597  char *t;
598@y
599overflow (const char *t)
600@z
601
602Section 67.
603
604@x l.1212
605the names of those files. Most of the 128 flags are undefined but available
606for future extensions.
607@y
608the names of those files. Most of the 128 flags are undefined but available
609for future extensions.
610
611We use `kpathsea' library functions to find literate sources and
612NLS configuration files. When the files you expect are not
613being found, the thing to do is to enable `kpathsea' runtime
614debugging by assigning to |kpathsea_debug| variable a small number
615via `\.{-d}' option. The meaning of number is shown below. To set
616more 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
62216&report directory list\cr
62332&report on each file search\cr
62464&report values of variables being looked up\cr}$$
625Debugging output is always written to |stderr|, and begins with the string
626`\.{kdebug:}'.
627@z
628
629@x l.1218
630@d show_happiness flags['h'] /* should lack of errors be announced? */
631@y
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? */
635@z
636
637@x l.1234
638show_banner=show_happiness=show_progress=1;
639@y
640show_banner=show_happiness=show_progress=1;
641@z
642
643Section 69.
644
645@x l.1252
646void scan_args();
647@y
648static void scan_args (void);
649@z
650
651
652Section 70.
653
654@x l.1255
655void
656scan_args()
657@y
658static void
659scan_args (void)
660@z
661
662
663Section 71.
664
665@x l.1282 - use a define for /dev/null
666  if (found_change<=0) strcpy(change_file_name,"/dev/null");
667@y
668  if (found_change<=0) strcpy(change_file_name,DEV_NULL);
669@z
670
671@x l.1302 - no alt_web_file_name
672  sprintf(alt_web_file_name,"%s.web",*argv);
673@y
674@z
675
676
677Section 74.
678
679@x l.1344
680@ @<Handle flag...@>=
681{
682@y
683@ @<Handle flag...@>=
684{
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@>;
689@z
690
691@x l.1347
692  else flag_change=1;
693@y
694  else flag_change=1;
695  if (*(*argv+1)=='d')
696    if (sscanf(*argv+2,"%u",&kpathsea_debug)!=1) @<Print usage error...@>;
697@z
698
699@x l.1349
700    flags[*dot_pos]=flag_change;
701@y
702    flags[(unsigned char)*dot_pos]=flag_change;
703@z
704
705Section 75.
706
707@x l.1354
708if (program==ctangle)
709  fatal(
710"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
711   ,"");
712@.Usage:@>
713else fatal(
714"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
715   ,"");
716@y
717if (program==ctangle) {
718  fprintf(stderr, "ctangle: Need one to three file arguments.\n");
719  usage("ctangle");
720} else {
721  fprintf(stderr, "cweave: Need one to three file arguments.\n");
722  usage("cweave");
723}
724@z
725
726Section 77.
727
728@x l.1375
729FILE *active_file; /* currently active file for \.{CWEAVE} output */
730@y
731FILE *active_file; /* currently active file for \.{CWEAVE} output */
732char *found_filename; /* filename found by |kpse_find_file| */
733@z
734
735Section 78.
736
737@x l.1380 Use binary mode for output files
738  if ((C_file=fopen(C_file_name,"w"))==NULL)
739@y
740  if ((C_file=fopen(C_file_name,"wb"))==NULL)
741@z
742
743@x l.1386 Use binary mode for output files
744  if ((tex_file=fopen(tex_file_name,"w"))==NULL)
745@y
746  if ((tex_file=fopen(tex_file_name,"wb"))==NULL)
747@z
748
749
750Section 81. (reused)
751
752@x l.1403
753@ We predeclare several standard system functions here instead of including
754their system header files, because the names of the header files are not as
755standard as the names of the functions. (For example, some \CEE/ environments
756have \.{<string.h>} where others have \.{<strings.h>}.)
757
758@<Predecl...@>=
759extern int strlen(); /* length of string */
760extern int strcmp(); /* compare strings lexicographically */
761extern char* strcpy(); /* copy one string to another */
762extern int strncmp(); /* compare up to $n$ string characters */
763extern char* strncpy(); /* copy up to $n$ string characters */
764@y
765@ We declare some more prototypes for exported function in cases where this
766could not be done easily without changing section numbers.
767
768@<External functions@>=
769extern void common_init (void);
770extern int input_ln (FILE *fp);
771extern void reset_input (void);
772extern int get_line (void);
773extern void check_complete (void);
774extern name_pointer id_lookup (const char *first, const char *last, char t);
775extern void print_section_name (name_pointer p);
776extern void sprint_section_name (char *dest, name_pointer p);
777extern name_pointer section_lookup (char *first, char *last, int ispref);
778@z
779
780@x
781@** Index.
782@y
783@** External functions.  In order to allow for type checking we create a
784header file \.{cweb.h} containing the declaration of all functions defined
785in \.{common.w} and used in \.{ctangle.w} and \.{cweave.w} or vice versa.
786
787@(cweb.h@>=
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@>@;
792extern const char *versionstring;
793
794@** System dependent changes.
795
796@ Modules for dealing with help messages and version info.
797
798@<Display help message and exit@>=
799usagehelp(program==ctangle ? CTANGLEHELP : CWEAVEHELP, NULL);
800@.--help@>
801
802@ Will have to change these if the version numbers change (ouch).
803
804@d ctangle_banner "This is CTANGLE, Version 3.64"
805@d cweave_banner "This is CWEAVE, Version 3.64"
806
807@<Display version information and exit@>=
808printversionandexit((program==ctangle ? ctangle_banner : cweave_banner),
809  "Silvio Levy and Donald E. Knuth", NULL, NULL);
810@.--version@>
811
812@** Index.
813@z
814