% Changes to adapt CTIE to web2c. % Copyright 2002 Julian Gilbey % All rights reserved. % % This file is distributed WITHOUT ANY WARRANTY, express or implied. % % Permission is granted to make and distribute verbatim copies of this % file provided that the copyright notice and this permission notice % are preserved on all copies. % % Permission is granted to copy and distribute modified versions of this % file under the conditions for verbatim copying, provided that the % entire resulting derived work is distributed under the terms of a % permission notice identical to this one. % % This file is based heavily on tie.ch by Olaf Weber to adapt tie.w to % the web2c system. @x These are defined by kpathsea @d false 0 @d true 1 @= typedef int boolean; typedef char* string; @y @= @z @x The kpathsea include files find the right header file for these. @ We predeclare some standard string-handling 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. (There's confusion between \.{} and \.{}.) @= extern int strlen(); /* length of string */ 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 */ extern char *strerror(); @y @ We don't need to predeclare any string handling functions here, as the \.{kpathsea} headers do the right thing. @z @x And this. @ And we need dynamic memory allocation. This should cause no trouble in any \CEE/ program. @^system dependencies@> @= #ifdef __STDC__ #include #else #include #endif @y @ And we need dynamic memory allocation. This should cause no trouble in any \CEE/ program. The \.{kpathsea} include files handle the definition of |malloc()|, too. @^system dependencies@> @z @x boolean get_line(i,do_includes) file_index i; boolean do_includes; @y boolean get_line @,P2C(file_index, i, boolean, do_includes) @z @x Use the \.{kpathsea} library for this job. @ When an \.{@@i} line is found in the 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. @d too_long() {total_include_files--; free(new_inc); err_print(i,"! Include file name too long"); goto restart;} @= { include_description *new_inc; char temp_file_name[max_file_name_length]; char *file_name_end; char *k, *kk; int l; /* length of file name */ new_inc=(include_description *) malloc(sizeof(include_description)); if (new_inc==NULL) fatal_error(i,"! No memory for new include descriptor",""); new_inc->line=0; k=new_inc->file_name; file_name_end=k+max_file_name_length-1; if (quoted_name) { while (*inp_desc->loc!='"'&&k<=file_name_end) *k++=*inp_desc->loc++; if (k>file_name_end) too_long(); if (k==inp_desc->limit) { total_include_files--; free(new_inc); err_print(i,"! Missing \" at end of filename, skipping"); goto restart; } } else { while (*inp_desc->loc!=' '&&*inp_desc->loc!='\t' &&*inp_desc->loc!='"'&&k<=file_name_end) *k++=*inp_desc->loc++; if (k>file_name_end) too_long(); } @.Include file name ...@> *k='\0'; if ((new_inc->the_file=fopen(new_inc->file_name,"r"))!=NULL) { new_inc->parent=inp_desc->current_include; /* link it in */ inp_desc->current_include=new_inc; goto restart; /* success */ } 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>=file_name_end) too_long(); for (; k>= new_inc->file_name; k--) *(k+l+1)=*k; strcpy(new_inc->file_name,temp_file_name); new_inc->file_name[l]='/'; /* \UNIX/ pathname separator */ if ((new_inc->the_file=fopen(new_inc->file_name,"r"))!=NULL) { new_inc->parent=inp_desc->current_include; /* link it in */ inp_desc->current_include=new_inc; goto restart; /* success */ } } total_include_files--; free(new_inc); err_print(i,"! Cannot open include file"); goto restart; } @y @ When an \.{@@i} line is found in the 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. We use the \.{kpathsea} library (in particular, the \.{CWEBINPUTS} variable) to search for this file. The remainder of the \.{@@i} line after the file name is ignored. @d too_long() {total_include_files--; free(new_inc); err_print(i,"! Include file name too long"); goto restart;} @= { include_description *new_inc; char *file_name_end; string fullname; char *k; new_inc=(include_description *) malloc(sizeof(include_description)); if (new_inc==NULL) fatal_error(i,"! No memory for new include descriptor",""); new_inc->line=0; k=new_inc->file_name; file_name_end=k+max_file_name_length-1; if (quoted_name) { while (*inp_desc->loc!='"'&&k<=file_name_end) *k++=*inp_desc->loc++; if (k>file_name_end) too_long(); if (k==inp_desc->limit) { total_include_files--; free(new_inc); err_print(i,"! Missing \" at end of filename, skipping"); goto restart; } } else { while (*inp_desc->loc!=' '&&*inp_desc->loc!='\t' &&*inp_desc->loc!='"'&&k<=file_name_end) *k++=*inp_desc->loc++; if (k>file_name_end) too_long(); } @.Include file name ...@> *k='\0'; fullname = kpse_find_file (new_inc->file_name, kpse_cweb_format, true); new_inc->the_file = fullname ? fopen (fullname, file_open_mode) : NULL; if (new_inc->the_file!=NULL) { new_inc->parent=inp_desc->current_include; /* link it in */ inp_desc->current_include=new_inc; goto restart; /* success */ } else { if (fullname) { pfatal_error("! Cannot open include file ", new_inc->file_name); } else { total_include_files--; free(new_inc); err_print(i,"! Cannot find include file"); goto restart; } } } @z @x void err_print(); @y void err_print @,P2H(file_index, char *); @z @x void err_print(i,s) /* prints `\..' and location of error message */ file_index i; char *s; @y void err_print @,P2C(file_index, i, char *, s) /* prints `\..' and location of error message */ @z @x int wrap_up() @y int wrap_up @,P1H(void) @z @x int wrap_up(); @y int wrap_up @,P1H(void); @z @x void pfatal_error(); @y void pfatal_error @,P2H(char *, char *); @z @x void pfatal_error(s,t) char *s,*t; @y void pfatal_error @,P2C(char *, s, char *, t) @z @x Use the kpathsea library to do this @ For the master file we start by reading its first line into the buffer, if we could open it. @= { input_organisation[0]->the_file= fopen(input_organisation[0]->file_name,"r"); if (input_organisation[0]->the_file==NULL) pfatal_error("! Could not open master file ", input_organisation[0]->file_name); @.Could not open master file@> @y @ For the master file we start by reading its first line into the buffer, if we could open it. We use the \.{kpathsea} library to find the file. @= { string fullname; fullname = kpse_find_file(input_organisation[0]->file_name, kpse_cweb_format, true); input_organisation[0]->the_file = fullname ? fopen(fullname, file_open_mode) : NULL; if (input_organisation[0]->the_file==NULL) { if (fullname) { pfatal_error("! Could not open master file ", input_organisation[0]->file_name); } else { fatal_error(-1,"! Could not find master file ", input_organisation[0]->file_name); } } @.Could not open master file@> @z @x And this @= { file_index i; i=1; while (ithe_file= fopen(input_organisation[i]->file_name,"r"); if (input_organisation[i]->the_file==NULL) pfatal_error("!Could not open change file ", input_organisation[i]->file_name); @.Could not open change file@> @y @= { file_index i; string fullname; i=1; while (ifile_name, kpse_cweb_format, true); input_organisation[i]->the_file = fullname ? fopen(fullname, file_open_mode) : NULL; if (input_organisation[i]->the_file==NULL) { if (fullname) { pfatal_error("! Could not open change file ", input_organisation[0]->file_name); } else { fatal_error(-1,"! Could not find change file ", input_organisation[0]->file_name); } } @.Could not open change file@> @z @x boolean lines_dont_match(i,j) file_index i,j; @y boolean lines_dont_match @,P2C(file_index, i, file_index, j) @z @x void init_change_file(i) file_index i; @y void init_change_file @,P1C(file_index, i) @z @x void put_line(j) file_index j; @y void put_line @,P1C(file_index, j) @z @x boolean e_of_ch_module(i) file_index i; @y boolean e_of_ch_module @,P1C(file_index, i) @z @x boolean e_of_ch_preamble(i) file_index i; @y boolean e_of_ch_preamble @,P1C(file_index, i) @z @x void usage_error() @y void usage_error @,P1H(void) @z @x Tell kpathsea about our name and set some key parameters. @= { @y @= { kpse_set_progname(argv[0]); kpse_init_format(kpse_cweb_format); file_open_mode = kpse_format_info[kpse_cweb_format].binmode ? FOPEN_RBIN_MODE : FOPEN_R_MODE; @z @x void usage_help(); void print_version_and_exit(); @y void usage_help @,P1H(void); void print_version_and_exit @,P2H(string, string); @z @x void usage_help() @y void usage_help @,P1H(void) @z @x void print_version_and_exit(name, version) string name, version; { printf ("%s %s\n", name, version); puts ("Copyright (C) 2002 Julian Gilbey."); puts ("There is NO warranty. This is free software. See the source"); puts ("code of CTIE for redistribution conditions."); exit (0); } @y void print_version_and_exit @,P2C(string, name, string, version) { extern KPSEDLL string kpathsea_version_string; /* from kpathsea/version.c */ printf ("%s %s\n", name, version); puts (kpathsea_version_string); puts ("Copyright (C) 2002 Julian Gilbey."); puts ("Kpathsea is copyright (C) 1999 Free Software Foundation, Inc."); puts ("There is NO warranty. This is free software."); puts ("Redistribution of this software is covered by the terms of"); puts ("both the CTIE copyright and the GNU General Public Licence."); puts ("For more information about these matters, see the files"); puts ("named COPYING and the CTIE source."); puts ("Primary authors of CTIE: Julian Gilbey."); puts ("Kpathsea written by Karl Berry and others.\n"); exit (0); } @z @x main(argc,argv) int argc; string *argv; @y int main @,P2C(int, argc, string *, argv) @z @x @* System-dependent changes. This section should be replaced, if necessary, by changes to the program that are necessary to make \.{CTIE} work at a particular installation. It is usually best to design your change file so that all changes to previous modules preserve the module numbering; then everybody's version will be consistent with the printed program. More extensive changes, which introduce new modules, can be inserted here; then only the index itself will get a new module number. @^system dependencies@> @y @* System-dependent changes. We modify the program to use the \.{kpathsea} library. We need to include the headers first. @= #include @ A global variable for the file read mode. @= string file_open_mode; @z