								-*-Web-*-
This file, COMMON-P.CH, is part of CWEB-p. It is a changefile written by
Hans-Hermann Bode (HHBODE@@DOSUNI1.BITNET or
hhbode@@dosuni1.rz.uni-osnabrueck.de) for COMMON.W that provides changes
appropriate for ANSI-C compilers and for the Turbo-C++ compiler. The latter
will become effective only if the symbol __TURBOC__ is defined, which
automatically is the case when compiled with Turbo C++.
Additional changes appropriate for the SAS/C 6.0 compiler were made by
Andreas Scherer and are based on ideas of Carsten Steger. These
will become effective only if the symbol __SASC is defined, which
automatically is the case when compiled with SAS/C 6.0 or higher.

This program is distributed WITHOUT ANY WARRANTY, express or implied.

The following copyright notice extends to this changefile only, not to the
masterfile.

Copyright (C) 1991, 1992 Hans-Hermann Bode

The following copyright notice extends to the SAS/C specific changes only,
not to the masterfile.

Copyright (C) 1991 Carsten Steger
Copyright (C) 1993 Andreas Scherer

Permission is granted to make and distribute verbatim copies of this
document 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
document 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.

Version history:

Version	Date		Author	Comment
a1/t1	10 Oct 1991	H2B	First attempt for COMMON.W 2.0.
p2	13 Feb 1992	H2B	Updated for COMMON.W 2.1, ANSI and Turbo
				changefiles merged together.
p3	16 Apr 1992	H2B	Updated for COMMON.W 2.2, change option for
				|@@i| completed.
p4	22 Jun 1992	H2B	Updated for COMMON.W 2.4, getting INCLUDEDIR
				from environment variable CWEBINCLUDE.
p5	19 Jul 1992	H2B	string.h included, usage message extended.
p5a	24 Jul 1992	KG	adaptions for other ANSI C compiler
p5b	28 Jul 1992	H2B	Remaining headers converted to ANSI style.
p5c	30 Jul 1992	KG	removed comments used after #endif
p6	06 Sep 1992	H2B	Updated for COMMON.W 2.7.
p6a     15 Mar 1993     AS      adapions for SAS/C 6.0 compiler

Extensions for use with other C compiler by Klaus Guntermann (KG),
TH Darmstadt (guntermann@@iti.informatik.th-darmstadt.de).
Mainly just modified all headers of prototyped functions.

------------------------------------------------------------------------------
@x l.2
% This program by Silvio Levy is based on a program by D. E. Knuth.
% It is distributed WITHOUT ANY WARRANTY, express or implied.
% Version 2.4 --- Don Knuth, June 1992

% Copyright (C) 1987,1990 Silvio Levy and Donald E. Knuth
@y
% This program by Silvio Levy is based on a program by D. E. Knuth.
% ANSI-C conforming changes and Turbo-C++ implementation are made by
% Hans-Hermann Bode.
% The program is distributed WITHOUT ANY WARRANTY, express or implied.
% Version 2.4 --- Don Knuth, June 1992
% Version 2.4 [p5] --- Hans-Hermann Bode, July 1992
% Version 2.4 [p5a] --- Klaus Guntermann, July 1992
% Version 2.4 [p5b] --- Hans-Hermann Bode, July 1992
% Version 2.4 [p5c] --- Klaus Guntermann, July 1992
% Version 2.7 [p6] --- Hans-Hermann Bode, September 1992
% Version 2.7 [p6a] --- Andreas Scherer, March 1993

% Copyright (C) 1987,1990 Silvio Levy and Donald E. Knuth

% Changes conforming to ANSI C and Turbo C++ are
% Copyright (C) 1991, 1992 Hans-Hermann Bode
% Changes conforming to SAS/C 6.0 are
% Copyright (C) 1991 Carsten Steger
% Copyright (C) 1993 Andreas Scherer
% See the changefile COMMON.CH for more information.
@z
------------------------------------------------------------------------------
@x l.19
\def\title{Common code for CTANGLE and CWEAVE (Version 2.7)}
@y
\def\title{Common code for CTANGLE and CWEAVE (Version 2.7 [p6a])}
@z
------------------------------------------------------------------------------
@x l.24
  \centerline{(Version 2.7)}
@y
  \centerline{(Version 2.7 [p6a])}
@z
------------------------------------------------------------------------------
@x l.28
Copyright \copyright\ 1987,\thinspace1990 Silvio Levy and Donald E. Knuth
@y
Copyright \copyright\ 1987,\thinspace1990 Silvio Levy and Donald E. Knuth
\smallskip\noindent
Copyright \copyright\ 1991,\thinspace1992 Hans-Hermann Bode
\smallskip\noindent
Copyright \copyright\ 1991 Carsten Steger
Copyright \copyright\ 1993 Andreas Scherer
@z
------------------------------------------------------------------------------
Activate this, if only the changed modules should be printed.
x l.42
\let\maybe=\iftrue
y
\let\maybe=\iffalse
z
------------------------------------------------------------------------------
@x l.57
@<Include files@>@/
@y
@<Include files@>@/
@<Macro definitions@>@/
@z
------------------------------------------------------------------------------
Some compilers warn about an extra ';' ...
@x l. 60
@<Functions@>;
@y
@<Functions@>@;
@z
------------------------------------------------------------------------------
@x l.87
common_init()
@y
void common_init(void)
@z
------------------------------------------------------------------------------
@x l.162
input_ln(fp) /* copies a line into |buffer| or returns 0 */
FILE *fp; /* what file to read from */
@y
static boolean input_ln(FILE *fp) /* copies a line into |buffer| or returns 0 */
/* |fp|: what file to read from */
@z
------------------------------------------------------------------------------
@x l.239
prime_the_change_buffer()
@y
static void prime_the_change_buffer(void)
@z
------------------------------------------------------------------------------
@x l.268
@ We do not allow includes in a change file, so as to avoid confusion.
@y
@ We do not allow includes in a change file, so as to avoid confusion.
Actually, the following check will be applied to comment lines in the change
file only, since otherwise \.{@@i} commands could never be changed.
@z
------------------------------------------------------------------------------
@x l.319
check_change() /* switches to |change_file| if the buffers match */
@y
static void check_change(void) /* switches to |change_file| if the buffers match */
@z
------------------------------------------------------------------------------
@x l.375
reset_input()
@y
void reset_input(void)
@z
------------------------------------------------------------------------------
@x l.421
get_line() /* inputs the next line */
@y
boolean get_line(void) /* inputs the next line */
@z
------------------------------------------------------------------------------
@x l.432
  return (!input_has_ended);
@y
  return ((boolean)!input_has_ended);
@z
------------------------------------------------------------------------------
@x l.443
defined at compile time. The remainder of the line after the file name
@y
defined at compile time; this prefix is got from the environment variable
\.{CWEBINCLUDE}. The remainder of the line after the file name
@z
------------------------------------------------------------------------------
Use environment variable CWEBINCLUDE instead of a static string if
INCLUDEDIR is defined.
@x l.459
strcpy(cur_file_name,INCLUDEDIR);
@y
strcpy(cur_file_name,getenv("CWEBINCLUDE"));
@z
------------------------------------------------------------------------------
ANSI C compilers warn about text behind an #endif
this happens twice in common.w. Suppress it by commenting it out.
@x l. 464
#endif INCLUDEDIR
@y
#endif /* INCLUDEDIR */
@z
------------------------------------------------------------------------------
... and
@x l. 472
#endif INCLUDEDIR
@y
#endif /* INCLUDEDIR */
@z
------------------------------------------------------------------------------
We like to be able to change @@i commands, also.
@x l.514
      @<Check for erron...@>;
@y
@z
------------------------------------------------------------------------------
@x l.530
check_complete(){
@y
void check_complete(void){
@z
------------------------------------------------------------------------------
@x l.555
  char *byte_start; /* beginning of the name in |byte_mem| */
@y
  char HUGE *byte_start; /* beginning of the name in |byte_mem| */
@z
------------------------------------------------------------------------------
@x l.558
typedef name_info *name_pointer; /* pointer into array of |name_info|s */
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| */
@y
typedef name_info HUGE *name_pointer; /* pointer into array of |name_info|s */
#ifdef __TURBOC__
char HUGE *byte_mem; /* characters of names */
char HUGE *byte_mem_end; /* end of |byte_mem| */
name_info HUGE *name_dir; /* information about names */
name_pointer name_dir_end; /* end of |name_dir| */
#else
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| */
#endif
@z
------------------------------------------------------------------------------
@x l.579
char *byte_ptr; /* first unused position in |byte_mem| */
@y
char HUGE *byte_ptr; /* first unused position in |byte_mem| */
@z
------------------------------------------------------------------------------
@x l.582
name_dir->byte_start=byte_ptr=byte_mem; /* position zero in both arrays */
@y
#ifdef __TURBOC__
byte_mem=allocsafe(max_bytes,sizeof(*byte_mem));
byte_mem_end=byte_mem+max_bytes-1;
name_dir=allocsafe(max_names,sizeof(*name_dir));
name_dir_end=name_dir+max_names-1;
#endif
name_dir->byte_start=byte_ptr=byte_mem; /* position zero in both arrays */
@z
------------------------------------------------------------------------------
@x l.592
struct name_info *link;
@y
struct name_info HUGE *link;
@z
------------------------------------------------------------------------------
In the following, the parameter t must be of type char to be accordant with
CWEAVE.
@x l.618
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 */
sixteen_bits t; /* the |ilk|; used by \.{WEAVE} only */
@y
id_lookup(char *first,char *last,char t)
/* looks up a string in the identifier table */
/* |first|: first character of string */
/* |last|:  last character of string plus one */
/* |t|:     the |ilk|; used by \.{WEAVE} only */
@z
------------------------------------------------------------------------------
@x l.683
  struct name_info *Rlink; /* right link in binary search tree for module
@y
  struct name_info HUGE *Rlink; /* right link in binary search tree for module
@z
------------------------------------------------------------------------------
This change is also for accordance of COMMON and CWEAVE.
@x l.685
  sixteen_bits Ilk; /* used by identifiers in \.{WEAVE} only */
@y
  char Ilk; /* used by identifiers in \.{WEAVE} only */
@z
------------------------------------------------------------------------------
Prototypes are listed in a separate section.
@x l.707
@<Other...@>=
name_pointer install_node();
@y
@z
------------------------------------------------------------------------------
@x l.711
mod_lookup(k,l) /* finds module name */
char *k; /* first character of name */
char *l; /* last character of name */
@y
mod_lookup(char *k,char *l) /* finds module name */
/* |k|: first character of name */
/* |l|: last character of name */
@z
------------------------------------------------------------------------------
@x l.736
web_strcmp(j,j1,k,k1) /* fuller comparison than |strcmp| */
char *j; /* beginning of first string */
char *j1; /* end of first string plus one */
char *k; /* beginning of second string */
char *k1; /* end of second string plus one */
@y
static short web_strcmp(char *j, char *j1, char HUGE *k, char HUGE *k1)
/* fuller comparison than |strcmp| */
/* |j|: beginning of first string */
/* |j1|: end of first string plus one */
/* |k|: beginning of second string */
/* |k1|: end of second string plus one */
@z
------------------------------------------------------------------------------
@x l.759
install_node(parent,c,j,name_len) /* install a new node in the tree */
name_pointer parent; /* parent of new node */
int c; /* right or left? */
char *j; /* where replacement text starts */
int name_len; /* length of replacement text */
@y
static install_node(name_pointer parent, int c, char *j, int name_len)
/* install a new node in the tree */
/* |parent|: parent of new node */
/* |c|:right or left? */
/* |j|: where replacement text starts */
/* |name_len|: length of replacement text */
@z
------------------------------------------------------------------------------
@x l.783
prefix_lookup(k,l) /* finds module name given a prefix */
char *k; /* first char of prefix */
char *l; /* last char of prefix */
@y
prefix_lookup(char *k,char *l) /* finds module name given a prefix */
/* |k|: first char of prefix */
/* |l|: last char of prefix */
@z
------------------------------------------------------------------------------
@x l.822
char *equiv_or_xref; /* info corresponding to names */
@y
char HUGE *equiv_or_xref; /* info corresponding to names */
@z
------------------------------------------------------------------------------
@x l.852
err_print(s) /* prints `\..' and location of error message */
char *s;
@y
void err_print(char *s) /* prints `\..' and location of error message */
@z
------------------------------------------------------------------------------
@x l.918
wrap_up() {
@y
void wrap_up(void) {
@z
------------------------------------------------------------------------------
AMIGA specific changes by Andreas Scherer based on ideas of Carsten Steger.
@x l.947
@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? */
@y
@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? */
@d use_amiga_keywords flags['a'] /* should Amiga/SAS C keywords be used? */
@d use_german_macros flags['g'] /* should the output be German? */
@z
----------------------------------------------------------------------
@x l.957
boolean flags[128]; /* an option for each 7-bit code */
@y
boolean flags[256]; /* an option for each 8-bit code */
@z
------------------------------------------------------------------------------
@x l.963
@<Set the default options common to \.{TANGLE} and \.{WEAVE}@>=
show_banner=show_happiness=show_progress=1;
@y
@<Set the default options common to \.{TANGLE} and \.{WEAVE}@>=
show_banner=show_happiness=show_progress=
#ifdef __SASC
use_amiga_keywords=
#endif
use_german_macros=1;
@z
----------------------------------------------------------------------
@x l.975
An omitted change file argument means that |"/dev/null"| should be used,
@y
An omitted change file argument means that |"/dev/null"| or---on {\mc
MS-DOS} systems---|"nul"| or---on {\mc AMIGA} systems---|"NIL:"| should be
used,
@z
------------------------------------------------------------------------------
@x l.982
scan_args()
@y
static void scan_args(void)
@z
------------------------------------------------------------------------------
@x l.1008
  if (!found_change) strcpy(change_file_name,"/dev/null");
@y
#if defined( __TURBOC__ )
  if (!found_change) strcpy(change_file_name,"nul");
#elif defined( __SASC )
  if (!found_change) strcpy(change_file_name,"NIL:");
#else
  if (!found_change) strcpy(change_file_name,"/dev/null");
#endif
@z
------------------------------------------------------------------------------
@x l.1069
  fatal(
"! Usage: ctangle [options] webfile[.w] [changefile[.ch] [outfile[.c]]]\n"
   ,"")@;
else fatal(
"! Usage: cweave [options] webfile[.w] [changefile[.ch] [outfile[.tex]]]\n"
   ,"");
@y
  fatal(
"! Usage: ctangle [options] webfile[.w] [changefile[.ch] [outfile[.c]]]\n"
"Options are (+ turns on, - turns off, default in brackets):\n"
"b print banner line [+]\n"
"h print happy message [+]\n"
"p give progress reports [+]\n"
"s show statistics (only when compiled with STAT defined) [-]\n"
   ,"")@;
#ifdef __SASC
else fatal(
"! Usage: cweave [options] webfile[.w] [changefile[.ch] [outfile[.tex]]]\n"
"Options are (+ turns on, - turns off, default in brackets):\n"
"b print banner line [+]\n"
"f force line breaks [+]\n"
"h print happy message [+]\n"
"p give progress reports [+]\n"
"a use AMIGA specific keywords [+]\n"
"g use German macros as of ccwebmacg.tex [+]\n"
"s show statistics (only when compiled with STAT defined) [-]\n"
"x include indexes and table of contents [+]\n"
   ,"");
#else
else fatal(
"! Usage: cweave [options] webfile[.w] [changefile[.ch] [outfile[.tex]]]\n"
"Options are (+ turns on, - turns off, default in brackets):\n"
"b print banner line [+]\n"
"f force line breaks [+]\n"
"h print happy message [+]\n"
"p give progress reports [+]\n"
"g use German macros as of ccwebmacg.tex [+]\n"
"s show statistics (only when compiled with STAT defined) [-]\n"
"x include indexes and table of contents [+]\n"
   ,"");
#endif
@z
------------------------------------------------------------------------------
@x l.1116
@* Index.
@y
@*Memory allocation. Due to restrictions of most {\mc MS-DOS} compilers,
large arrays will be allocated dynamically rather than statically. In the {\mc
Turbo-C} implementation the |farcalloc| function provides a way to allocate
more than 64~KByte of data. The |allocsafe| function tries to carry out an
allocation of |nunits| blocks of size |unitsz| by calling |farcalloc| and takes
a safe method, when this fails: the program will be aborted.
@^system dependencies@>

@<Functions@>=
#ifdef __TURBOC__
void far *allocsafe (unsigned long nunits,unsigned long unitsz)
{
  void far *p = farcalloc(nunits,unitsz);
  if (p==NULL) fatal("","! Memory allocation failure");
@.Memory allocation failure@>
  return p;
}
#endif

@ @<Include...@>=
#ifdef __TURBOC__
#include <alloc.h>
#endif

@ To deal with such allocated data areas |huge| pointers will be used in the
{\mc Turbo-C} implementation.

@f far int
@f huge int
@f HUGE int

@<Macro...@>=
#ifdef __TURBOC__
#define HUGE huge
#else
#define HUGE
#endif
@^system dependencies@>

@*Function declarations. Here are declarations, conforming to {\mc ANSI~C}, of
all functions in this code that appear in |"common.h"| and thus should
agree with \.{TANGLE} and \.{WEAVE}.

@<Other...@>=
#ifdef __SASC /* I don't know, which form is correct */
typedef unsigned char eight_bits;
#else
typedef char unsigned eight_bits;
#endif
void common_init(void);
extern void print_stats(void);
name_pointer id_lookup(char *first,char *last,char t);
name_pointer mod_lookup(char *k,char *l);
name_pointer prefix_lookup(char *k,char *l);
extern boolean names_match(name_pointer p, char *first, int l, eight_bits t);
extern void init_p(name_pointer p, eight_bits t);
extern void init_node(name_pointer p);
void err_print(char *s);
void wrap_up(void);
void reset_input(void);
boolean get_line(void);
void check_complete(void);
#ifdef __TURBOC__
static void far *allocsafe(unsigned long nunits, unsigned long unitsz);
@^system dependencies@>
#endif

@ The following functions are private to |"common.w"|.

@<Other...@>=
static boolean input_ln(FILE *fp);
static void prime_the_change_buffer(void);
static void check_change(void);
static name_pointer install_node(name_pointer parent, int c, char *j, int name_len);
static short web_strcmp(char *j, char *j1, char HUGE *k, char HUGE *k1);
static void scan_args(void);

@ Finally, we include \.{stdlib.h} that contains the prototype for the
|getenv| function used above and \.{string.h} for |strncmp|, |strncpy|,
|strcpy|, and |strlen|.

@<Include...@>=
#include <stdlib.h>
#include <string.h>

@* Index.
@z
------------------------------------------------------------------------------
