|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T U
Length: 59348 (0xe7d4) Types: TextFile Notes: Uncompressed file
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦c319c2751⟧ »unix3.0/TeX3.0.tar.Z« └─⟦036c765ac⟧ └─⟦28cc16162⟧ »TeX3.0/BibTeX.inputs/pascal_bibtex.shar.Z« └─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89 └─⟦28cc16162⟧ »./tex82/LaTeX/LaTeXbibtex/pascal_bibtex.shar.Z« └─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦63303ae94⟧ »unix3.14/TeX3.14.tar.Z« └─⟦c58930e5c⟧ └─⟦28cc16162⟧ »TeX3.14/BibTeX.inputs/pascal_bibtex.shar.Z« └─⟦this⟧
# This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #-----cut here-----cut here-----cut here-----cut here----- #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # Makefile.BSD4_n # Makefile.PYR # Makefile.SUN # Makefile.SYS_V # Setup.PYR # Setup.SUN # Setup.SYS_V # Setup.VAX # bibext.BSD4_n.c # bibext.PYR.c # bibext.h # bibsep.SYS_V.sed # bibtex.BSD4_n.ch # bibtex.PYR.ch # bibtex.SYS_V.ch # makebib.SYS_V # This archive created: Fri Jul 22 15:50:21 1988 cat << \SHAR_EOF > Makefile.BSD4_n # # Makefile for BibTeX # # Note: The -J option on the 'pc' commands below is the only way to # 'pc' to use the -J option to the assembler (which makes it # do the sensible thing with branches). This flag is not # documented, which is correct, since 'pc' should really be # using it all of the time... (Grrr..) # BINDIR=/usr/stanford/bin PC = pc PCLIB = PFLAGS= -J -w CFLAGS= -O -I../.. .SUFFIXES: .SUFFIXES: .o .p .c .ch .ch.o: tangle $*.web $*.ch $(PC) $(PFLAGS) -c $*.p .ch.p: tangle $*.web $*.ch pxp -O $*.p > tmp mv tmp $*.p .p.o: $(PC) $(PFLAGS) -c $*.p all: bibtex install: bibtex mv bibtex $(BINDIR) bibtex: bibtex.o bibext.o $(PC) $(PFLAGS) -o bibtex bibtex.o bibext.o $(PCLIB) bibtex.o: bibtex.p bibext.h bibtex.p: bibtex.web bibext.o: bibext.c ../../h00vars.h ../../texpaths.h clean: rm -f bibtex.p bibtex.o bibtex.pool rm -f bibext.o SHAR_EOF cat << \SHAR_EOF > Makefile.PYR # # Makefile for BibTeX # # Note: The -J option on the 'pc' commands below is the only way to # 'pc' to use the -J option to the assembler (which makes it # do the sensible thing with branches). This flag is not # documented, which is correct, since 'pc' should really be # using it all of the time... (Grrr..) # BINDIR=/usr/stanford/bin PC = pascal PCLIB = PFLAGS= -T4/bin/nas CFLAGS= -O -I../.. .SUFFIXES: .SUFFIXES: .o .p .c .ch .ch.o: tangle $*.web $*.ch $(PC) $(PFLAGS) -c $*.p .ch.p: tangle $*.web $*.ch sed 's/others:/otherwise:/' < $*.p > tmp mv tmp $*.p .p.o: $(PC) $(PFLAGS) -c $*.p all: bibtex install: bibtex mv bibtex $(BINDIR) bibtex: bibtex.o bibext.o $(PC) $(PFLAGS) -o bibtex bibtex.o bibext.o $(PCLIB) bibtex.o: bibtex.p bibext.h bibtex.p: bibtex.web bibext.o: bibext.c ../../h00vars.h ../../texpaths.h clean: rm -f bibtex.p bibtex.o bibtex.pool rm -f bibext.o SHAR_EOF cat << \SHAR_EOF > Makefile.SUN # # Makefile for BibTeX # # BINDIR=/usr/stanford/bin PC = pc PCLIB = PFLAGS= -w CFLAGS= -O -I../.. .SUFFIXES: .SUFFIXES: .o .p .c .ch .ch.o: tangle $*.web $*.ch $(PC) $(PFLAGS) -c $*.p .ch.p: tangle $*.web $*.ch pxp -O $*.p > tmp mv tmp $*.p .p.o: $(PC) $(PFLAGS) -c $*.p all: bibtex install: bibtex mv bibtex $(BINDIR) bibtex: bibtex.o bibext.o $(PC) $(PFLAGS) -o bibtex bibtex.o bibext.o $(PCLIB) bibtex.o: bibtex.p bibext.h bibtex.p: bibtex.web bibext.o: bibext.c ../../h00vars.h ../../texpaths.h clean: rm -f bibtex.p bibtex.o bibtex.pool rm -f bibext.o SHAR_EOF cat << \SHAR_EOF > Makefile.SYS_V # # Makefile for BibTeX # # #BINDIR=/usr/stanford/bin BINDIR=/usr/local/bin PC = pc PCLIB = PFLAGS= -w -Tr CFLAGS= -O -I../.. .SUFFIXES: .SUFFIXES: .o .p .c .ch .ch.o: tangle $*.web $*.ch $(PC) $(PFLAGS) -c $*.p .ch.p: tangle $*.web $*.ch pxp -O -L140 $*.p > tmp mv tmp $*.p .p.o: $(PC) $(PFLAGS) -c $*.p all: bibtex install: bibtex mv bibtex $(BINDIR) bibtex: bibtex.p bibext.o makebib bibtex.o: bibtex.p bibext.h bibtex.p: bibtex.web bibext.o: bibext.c ../../h00vars.h ../../texpaths.h clean: rm -f bibtex.p bibtex.o bibtex.pool rm -f bibext.o bibtex?.? SHAR_EOF cat << \SHAR_EOF > Setup.PYR # /bin/sh # arrange things in the ./LaTeX/LaTeXbibtex area for compilation on # Pyramid OSx machines cp Makefile.PYR Makefile cp bibext.PYR.c bibext.c cp bibtex.PYR.ch bibtex.ch SHAR_EOF cat << \SHAR_EOF > Setup.SUN #!/bin/sh # arrange things in the ./tex82/LaTeX/LaTeXbibtex area for compilation on # SUN2 or SUN3 (largely 4.2/3BSD but no longer called that) cp Makefile.SUN Makefile cp bibext.BSD4_n.c bibext.c cp bibtex.BSD4_n.ch bibtex.ch SHAR_EOF cat << \SHAR_EOF > Setup.SYS_V #!/bin/sh # cp Makefile.SYS_V Makefile cp bibsep.SYS_V.sed bibsep.sed cp bibtex.SYS_V.ch bibtex.ch cp makebib.SYS_V makebib SHAR_EOF cat << \SHAR_EOF > Setup.VAX #!/bin/sh # arrange things in the ./LaTeX/LaTeXbibtex area for compilation on # Vax 4.2/3BSD cp Makefile.BSD4_n Makefile cp bibext.BSD4_n.c bibext.c cp bibtex.BSD4_n.ch bibtex.ch SHAR_EOF cat << \SHAR_EOF > bibext.BSD4_n.c /* external procedures for use with BibTeX */ #include "texpaths.h" #include "h00vars.h" char inputpath[MAXINPATHCHARS] = defaultinputpath; char *getenv(); /* * setpaths is called to set up the arrays inputpath as follows: * if the user's environment has a value for TEXINPUTS then use it; * appropriate value, then use it; otherwise, leave the current value of * the array (which will be the default path) */ setpaths() { register char *envpath; if ((envpath = getenv("TEXINPUTS")) != NULL) copypath(inputpath,envpath,MAXINPATHCHARS); } /* * copypath(s1,s2,n) copies at most n characters (including the null) * from string s2 to string s1, giving an error message for paths * that are too long. */ copypath(s1,s2,n) register char *s1,*s2; register int n; { while ((*s1++ = *s2++) != '\0') if (--n == 0) { fprintf(stderr, "! Environment search path is too big\n"); *--s1 = '\0'; return; /* let user continue with truncated path */ } } extern char buffer[],xord[]; extern short last; /* pointer into buffer */ /* * lineread reads from the Pascal text file with iorec pointer filep * into buffer[0], buffer[1],..., buffer[last-1] (and setting "last"). * Characters are read until a newline is found (which isn't put in the * buffer) or until the next character would go into buffer[lastlim]. * The characters need to be translated, so really xord[c] is put into * the buffer when c is read. * If end-of-file is encountered, the funit field of *filep is set * appropriately. */ lineread(filep, lastlim) struct iorec *filep; int lastlim; { register c; register char *cs; /* pointer into buffer where next char goes */ register FILE *iop; /* stdio-style FILE pointer */ int l; /* how many more chars are allowed before buffer overflow */ char *bf; /* hold address of buffer[0] */ iop = filep->fbuf; bf = cs = &(buffer[0]); l = lastlim; /* overflow when next char would go into buffer[lastlim] */ while (--l>=0 && (c = getc(iop))>=0 && c!='\n') *cs++ = xord[c]; if (c<=0) filep->funit |= EOFF; /* we hit end-of-file */ last = cs-bf; } #define filenamesize 1024 /* should agree with initex.ch */ extern char nameoffile[],realnameoffile[]; /* these have size filenamesize */ /* * testaccess(amode,filepath) * * Test whether or not the file whose name is in the global nameoffile * can be opened for reading (if mode=READACCESS) * or writing (if mode=WRITEACCESS). * * The filepath argument is one of the ...FILEPATH constants defined below. * If the filename given in nameoffile does not begin with '/', we try * prepending all the ':'-separated areanames in the appropriate path to the * filename until access can be made, if it ever can. * * The realnameoffile global array will contain the name that yielded an * access success. */ #define READACCESS 4 #define WRITEACCESS 2 #define NOFILEPATH 0 #define INPUTFILEPATH 1 bool testaccess(amode,filepath) int amode,filepath; { register bool ok; register char *p; char *curpathplace; int f; switch(filepath) { case NOFILEPATH: curpathplace = NULL; break; case INPUTFILEPATH: curpathplace = inputpath; break; } if (nameoffile[0]=='/') /* file name has absolute path */ curpathplace = NULL; do { packrealnameoffile(&curpathplace); if (amode==READACCESS) /* use system call "access" to see if we could read it */ if (access(realnameoffile,READACCESS)==0) ok = TRUE; else ok = FALSE; else { /* WRITEACCESS: use creat to see if we could create it, but close the file again if we're OK, to let pc open it for real */ f = creat(realnameoffile,0666); if (f>=0) ok = TRUE; else ok = FALSE; if (ok) close(f); } } while (!ok && curpathplace != NULL); if (ok) { /* pad realnameoffile with blanks, as Pascal wants */ for (p = realnameoffile; *p != '\0'; p++) /* nothing: find end of string */ ; while (p < &(realnameoffile[filenamesize])) *p++ = ' '; } return (ok); } /* * packrealnameoffile(cpp) makes realnameoffile contain the directory at *cpp, * followed by '/', followed by the characters in nameoffile up until the * first blank there, and finally a '\0'. The cpp pointer is left pointing * at the next directory in the path. * But: if *cpp == NULL, then we are supposed to use nameoffile as is. */ packrealnameoffile(cpp) char **cpp; { register char *p,*realname; realname = realnameoffile; if ((p = *cpp)!=NULL) { while ((*p != ':') && (*p != '\0')) { *realname++ = *p++; if (realname == &(realnameoffile[filenamesize-1])) break; } if (*p == '\0') *cpp = NULL; /* at end of path now */ else *cpp = p+1; /* else get past ':' */ *realname++ = '/'; /* separate the area from the name to follow */ } /* now append nameoffile to realname... */ p = nameoffile; while (*p != ' ') { if (realname >= &(realnameoffile[filenamesize-1])) { fprintf(stderr,"! Full file name is too long\n"); break; } *realname++ = *p++; } *realname = '\0'; } /* ** testeof(filep) ** ** Test whether or not the Pascal text file with iorec pointer filep ** has reached end-of-file (when the only I/O on it is done with ** lineread, above). ** We may have to read the next character and unget it to see if perhaps ** the end-of-file is next. */ bool testeof(filep) register struct iorec *filep; { register char c; register FILE *iop; /* stdio-style FILE pointer */ if (filep->funit & EOFF) return(TRUE); else { /* check to see if next is EOF */ iop = filep->fbuf; c = getc(iop); if (c<0) return(TRUE); else { ungetc(c,iop); return(FALSE); } } } SHAR_EOF cat << \SHAR_EOF > bibext.PYR.c /* external procedures for use with BibTeX */ #include "texpaths.h" #include "h00vars.h" char inputpath[MAXINPATHCHARS] = defaultinputpath; char *getenv(); /* * setpaths is called to set up the arrays inputpath as follows: * if the user's environment has a value for TEXINPUTS then use it; * appropriate value, then use it; otherwise, leave the current value of * the array (which will be the default path) */ setpaths() { register char *envpath; if ((envpath = getenv("TEXINPUTS")) != NULL) copypath(inputpath,envpath,MAXINPATHCHARS); } /* * copypath(s1,s2,n) copies at most n characters (including the null) * from string s2 to string s1, giving an error message for paths * that are too long. */ copypath(s1,s2,n) register char *s1,*s2; register int n; { while ((*s1++ = *s2++) != '\0') if (--n == 0) { fprintf(stderr, "! Environment search path is too big\n"); *--s1 = '\0'; return; /* let user continue with truncated path */ } } extern int buffer[],xord[]; extern int last; /* pointer into buffer */ /* * lineread reads from the Pascal text file with iorec pointer filep * into buffer[0], buffer[1],..., buffer[last-1] (and setting "last"). * Characters are read until a newline is found (which isn't put in the * buffer) or until the next character would go into buffer[lastlim]. * The characters need to be translated, so really xord[c] is put into * the buffer when c is read. * If end-of-file is encountered, the funit field of *filep is set * appropriately. */ lineread(filep, lastlim) struct iorec *filep; int lastlim; { register c; register int *cs; /* pointer into buffer where next char goes */ register FILE *iop; /* stdio-style FILE pointer */ int l; /* how many more chars are allowed before buffer overflow */ int *bf; /* hold address of buffer[0] */ iop = filep->fbuf; bf = cs = &(buffer[0]); l = lastlim; /* overflow when next char would go into buffer[lastlim] */ while (--l>=0 && (c = getc(iop))>=0 && c!='\n') *cs++ = xord[c]; if (c<=0) filep->funit |= EOFF; /* we hit end-of-file */ last = cs-bf; } #define filenamesize 1024 /* should agree with initex.ch */ extern char nameoffile[],realnameoffile[]; /* these have size filenamesize */ /* * testaccess(amode,filepath) * * Test whether or not the file whose name is in the global nameoffile * can be opened for reading (if mode=READACCESS) * or writing (if mode=WRITEACCESS). * * The filepath argument is one of the ...FILEPATH constants defined below. * If the filename given in nameoffile does not begin with '/', we try * prepending all the ':'-separated areanames in the appropriate path to the * filename until access can be made, if it ever can. * * The realnameoffile global array will contain the name that yielded an * access success. */ #define READACCESS 4 #define WRITEACCESS 2 #define NOFILEPATH 0 #define INPUTFILEPATH 1 bool testaccess(amode,filepath) int amode,filepath; { register bool ok; register char *p; char *curpathplace; int f; switch(filepath) { case NOFILEPATH: curpathplace = NULL; break; case INPUTFILEPATH: curpathplace = inputpath; break; } if (nameoffile[0]=='/') /* file name has absolute path */ curpathplace = NULL; do { packrealnameoffile(&curpathplace); if (amode==READACCESS) /* use system call "access" to see if we could read it */ if (access(realnameoffile,READACCESS)==0) ok = TRUE; else ok = FALSE; else { /* WRITEACCESS: use creat to see if we could create it, but close the file again if we're OK, to let pc open it for real */ f = creat(realnameoffile,0666); if (f>=0) ok = TRUE; else ok = FALSE; if (ok) close(f); } } while (!ok && curpathplace != NULL); if (ok) { /* pad realnameoffile with blanks, as Pascal wants */ for (p = realnameoffile; *p != '\0'; p++) /* nothing: find end of string */ ; while (p < &(realnameoffile[filenamesize])) *p++ = ' '; } return (ok); } /* * packrealnameoffile(cpp) makes realnameoffile contain the directory at *cpp, * followed by '/', followed by the characters in nameoffile up until the * first blank there, and finally a '\0'. The cpp pointer is left pointing * at the next directory in the path. * But: if *cpp == NULL, then we are supposed to use nameoffile as is. */ packrealnameoffile(cpp) char **cpp; { register char *p,*realname; realname = realnameoffile; if ((p = *cpp)!=NULL) { while ((*p != ':') && (*p != '\0')) { *realname++ = *p++; if (realname == &(realnameoffile[filenamesize-1])) break; } if (*p == '\0') *cpp = NULL; /* at end of path now */ else *cpp = p+1; /* else get past ':' */ *realname++ = '/'; /* separate the area from the name to follow */ } /* now append nameoffile to realname... */ p = nameoffile; while (*p != ' ') { if (realname >= &(realnameoffile[filenamesize-1])) { fprintf(stderr,"! Full file name is too long\n"); break; } *realname++ = *p++; } *realname = '\0'; } /* ** testeof(filep) ** ** Test whether or not the Pascal text file with iorec pointer filep ** has reached end-of-file (when the only I/O on it is done with ** lineread, above). ** We may have to read the next character and unget it to see if perhaps ** the end-of-file is next. */ bool testeof(filep) register struct iorec *filep; { register char c; register FILE *iop; /* stdio-style FILE pointer */ if (filep->funit & EOFF) return(TRUE); else { /* check to see if next is EOF */ iop = filep->fbuf; c = getc(iop); if (c<0) return(TRUE); else { ungetc(c,iop); return(FALSE); } } } SHAR_EOF cat << \SHAR_EOF > bibext.h procedure setpaths; external; function testaccess(accessmode:integer; filepath:integer): boolean; external; function testeof(var f: text): boolean; external; procedure lineread(var f: text; lastlim: integer); external; SHAR_EOF cat << \SHAR_EOF > bibsep.SYS_V.sed /^ procedure/{ s/$/ external;/w bibtex1.h s/^\( procedure [^(;]*\).*/\1;/ } /^ function/{ s/$/ external;/w bibtex1.h s/^\( function [^(:]*\).*/\1;/ } /^program/,/^const/{ /^const/b co w bibtex0.h d } :co /^const/,/^ function inputln/{ /^ function inputln/b t1 w bibtex1.h d } :t1 /^ function inputln/,/^ procedure xinttochr/{ /^ procedure xinttochr/b t2 /^ function inputln/s/^/#include "bibtex1.h"\ / w bibtex1.p d } :t2 /^ procedure xinttochr/,${ /^ procedure xinttochr/s/^/#include "bibtex0.h"\ #include "bibtex1.h"\ / w bibtex2.p d } SHAR_EOF cat << \SHAR_EOF > bibtex.BSD4_n.ch % Change file for BibTeX for Berkeley UNIX, by H. Trickey % History: % 5/28/84 Initial implementation, version 0.41 of BibTeX % 7/1/84 Version 0.41a of BibTeX. % 12/17/84 Version 0.97c of BibTeX. % 2/12/85 Version 0.98c of BibTeX. % 2/25/85 Newer Version 0.98c of BibTeX % 3/25/85 Version 0.98f of BibTeX % 5/23/85 Version 0.98i of BibTeX % 2/6/88 Version 0.99a of BibTeX (PAM) % 2/16/88 Version 0.99c of BibTeX (PAM) @x banner @d banner=='This is BibTeX, Version 0.99c' {printed when the program starts} @y @d banner=='This is BibTeX, Version 0.99c for Berkeley UNIX' {printed when the program starts} @z @x terminal @d term_out == tty @d term_in == tty @y @d term_out == output @d term_in == input @z @x debug..gubed, stat..tats @d debug == @{ { remove the `|@{|' when debugging } @d gubed == @t@>@} { remove the `|@}|' when debugging } @f debug == begin @f gubed == end @# @d stat == @{ { remove the `|@{|' when keeping statistics } @d tats == @t@>@} { remove the `|@}|' when keeping statistics } @f stat == begin @f tats == end @y @d debug == @{ { remove the `|@{|' when debugging } @d gubed == @t@>@} { remove the `|@}|' when debugging } @f debug == begin @f gubed == end @# @d stat == @{ { remove the `|@{|' when keeping statistic } @d tats == @t@>@} { remove the `|@}|' when keeping statistic } @f stat==begin @f tats==end @z @x program header program BibTEX; {all files are opened dynamically} label close_up_shop,@!exit_program @<Labels in the outer block@>; const @<Constants in the outer block@> type @<Types in the outer block@> var @<Globals in the outer block@>@; @y program BibTEX(input,output); label close_up_shop,@!exit_program @<Labels in the outer block@>; const @<Constants in the outer block@> type @<Types in the outer block@> var @<Globals in the outer block@> @\@=#include "bibext.h"@>@\ {declarations for external C procedures} @z @x compiler directives @{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead} @!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging} @y @=(*C-*)@> {no range check, catch arithmetic overflow, no debug overhead} @!debug @=(*C+*)@>@+ gubed {but turn everything on when debugging} @z @x increase buf_size @!buf_size=1000; {maximum number of characters in an input line (or string)} @y @!buf_size=3000; {maximum number of characters in an input line (or string)} @z @x increase pool_size @!pool_size=65000; {maximum number of characters in strings} @y @!pool_size=200000; {maximum number of characters in strings} @z @x increase file_name_size @d file_name_size=40 {file names shouldn't be longer than this} @y @d file_name_size=1024 {file names shouldn't be longer than this} @z @x alpha_file type @!alpha_file=packed file of text_char; {files that contain textual data} @y @!alpha_file=text; {files that contain textual data} @z @x declare real_name_of_file |name_of_file|. \BibTeX\ does no case conversion for file names. @<Globals in the outer block@>= @!name_of_file:packed array[1..file_name_size] of char; {on some systems this is a \&{record} variable} @y |name_of_file|. \BibTeX\ does no case conversion for file names. The Berkeley UNIX version uses search paths to look for files to open. We use |real_name_of_file| to hold the |name_of_file| with a directory name from the path in front of it. @<Globals in the outer block@>= @!name_of_file,@!real_name_of_file:packed array[1..file_name_size] of char; @z @x opening files The \ph\ compiler with which the present version of \TeX\ was prepared has extended the rules of \PASCAL\ in a very convenient way. To open file~|f|, we can write $$\vbox{\halign{#\hfil\qquad&#\hfil\cr |reset(f,@t\\{name}@>,'/O')|&for input;\cr |rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$ The `\\{name}' parameter, which is of type `\ignorespaces|packed array[@t\<\\{any}>@>] of text_char|', stands for the name of the external file that is being opened for input or output. Blank spaces that might appear in \\{name} are ignored. The `\.{/O}' parameter tells the operating system not to issue its own error messages if something goes wrong. If a file of the specified name cannot be found, or if such a file cannot be opened for some other reason (e.g., someone may already be trying to write the same file), we will have |@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows \TeX\ to undertake appropriate corrective action. \TeX's file-opening procedures return |false| if no file identified by |name_of_file| could be opened. @d reset_OK(#)==erstat(#)=0 @d rewrite_OK(#)==erstat(#)=0 @<Procedures and functions for file-system interacting@>= function erstat(var f:file):integer; extern; {in the runtime library} @#@t\2@> function a_open_in(var f:alpha_file):boolean; {open a text file for input} begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f); end; @# function a_open_out(var f:alpha_file):boolean; {open a text file for output} begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f); end; @y @ The \ph\ compiler with which the present version of \TeX\ was prepared has extended the rules of \PASCAL\ in a very convenient way for file opening. Berkeley {\mc UNIX} \PASCAL\ isn't nearly as nice as \ph. Normally, it bombs out if a file open fails. An external C procedure, |test_access| is used to check whether or not the open will work. It is declared in the ``ext.h'' include file, and it returns |true| or |false|. The |name_of_file| global holds the file name whose access is to be tested. The first parameter for |test_access| is the access mode, one of |read_access_mode| or |write_access_mode|. We also implement path searching in |test_access|: its second parameter is one of the ``file path'' constants defined below. If |name_of_file| doesn't start with |'/'| then |test_access| tries prepending pathnames from the appropriate path list until success or the end of path list is reached. On return, |real_name_of_file| contains the original name with the path that succeeded (if any) prepended. It is the name used in the various open procedures. Path searching is not done for output files. @d read_access_mode=4 {``read'' mode for |test_access|} @d write_access_mode=2 {``write'' mode for |test_access|} @d no_file_path=0 {no path searching should be done} @d input_file_path=1 {path specifier for input files} @<Procedures and functions for file-system interacting@>= function a_open_in(var f:alpha_file):boolean; {open a text file for input} var @!ok:boolean; begin if test_access(read_access_mode,input_file_path) then begin reset(f,real_name_of_file); ok:=true@+end else ok:=false; a_open_in:=ok; end; @# function a_open_out(var f:alpha_file):boolean; {open a text file for output} var @!ok:boolean; begin if test_access(write_access_mode,no_file_path) then begin rewrite(f,real_name_of_file); ok:=true @+end else ok:=false; a_open_out:=ok; end; @z @x closing files Files can be closed with the \ph\ routine `|close(f)|', which should be used when all input or output with respect to |f| has been completed. This makes |f| available to be opened again, if desired; and if |f| was used for output, the |close| operation makes the corresponding external file appear on the user's area, ready to be read. @<Procedures and functions for file-system interacting@>= procedure a_close(var f:alpha_file); {close a text file} begin close(f); end; @y Files can be closed with the \ph\ routine `|close(f)|', which should be used when all input or output with respect to |f| has been completed. With the pc library, files will be automatically closed when the program stops and when one reopens them. @<Procedures and functions for file-system interacting@>= procedure a_close(var f:alpha_file); {close a text file} begin do_nothing; end; @z @x faster input_ln Standard \PASCAL\ says that a file should have |eoln| immediately before |eof|, but \BibTeX\ needs only a weaker restriction: If |eof| occurs in the middle of a line, the system function |eoln| should return a |true| result (even though |f^| will be undefined). @<Procedures and functions for all file I/O, error messages, and such@>= function input_ln(var f:alpha_file) : boolean; {inputs the next line or returns |false|} label loop_exit; begin last:=0; if (eof(f)) then input_ln:=false else begin while (not eoln(f)) do begin if (last >= buf_size) then buffer_overflow; buffer[last]:=xord[f^]; get(f); incr(last); end; get(f); while (last > 0) do {remove trailing |white_space|} if (lex_class[buffer[last-1]] = white_space) then decr(last) else goto loop_exit; loop_exit: input_ln:=true; end; end; @y With Berkeley {\mc UNIX} we call an external C procedure, |line_read|. That routine fills |buffer| from |0| onwards with the |xord|'ed values of the next line, setting |last| appropriately. It will stop if |last=buf_size|, and the following will cause an ``overflow'' abort. If one uses |input_ln| on a file, the normal |read| and |get| routines shouldn't be used, nor the |eof| and |eoln| tests. End of file can be tested with the external function |test_eof|. @<Procedures and functions for all file I/O, error messages, and such@>= function input_ln(var f:alpha_file) : boolean; {inputs the next line or returns |false|} label loop_exit; begin last:=0; if test_eof(f) then input_ln:=false else begin line_read(f,buf_size); if last>=buf_size then overflow('buffer size ',buf_size); while (last > 0) do {remove trailing |white_space|} if lex_class[buffer[last-1]] = white_space then decr(last) else goto loop_exit; loop_exit: input_ln:=true; end; end; @z @x getting top-level name: it comes from command line These modules read the name of the top-level \.{.aux} file. Some systems will try to find this on the command line; if it's not there it will come from the user's terminal. In either case, the name goes into the |char| array |name_of_file|, and the files relevant to this name are opened. @d aux_found=41 {go here when the \.{.aux} name is legit} @d aux_not_found=46 {go here when it's not} @y These modules read the name of the top-level \.{.aux} file. Some systems will try to find this on the command line; if it's not there it will come from the user's terminal. In either case, the name goes into the |char| array |name_of_file|, and the files relevant to this name are opened. @z @x redirect goto from |sam_you_made_the_file_name_too_long| @d sam_you_made_the_file_name_too_long == begin sam_too_long_file_name_print; goto aux_not_found; end @y @d sam_you_made_the_file_name_too_long == begin sam_too_long_file_name_print; goto exit_program end @z @x redirect goto from |sam_you_made_the_file_name_wrong| @d sam_you_made_the_file_name_wrong == begin sam_wrong_file_name_print; goto aux_not_found; end @y @d sam_you_made_the_file_name_wrong == begin sam_wrong_file_name_print; goto exit_program; end @z @x reading the command line This procedure consists of a loop that reads and processes a (nonnull) \.{.aux} file name. It's this module and the next two that must be changed on those systems using command-line arguments. Note: The |term_out| and |term_in| files are system dependent. @<Procedures and functions for the reading and processing of input files@>= procedure get_the_top_level_aux_file_name; label aux_found,@!aux_not_found; var @<Variables for possible command-line processing@>@/ begin check_cmnd_line := false; {many systems will change this} loop begin if (check_cmnd_line) then @<Process a possible command line@> else begin write (term_out,'Please type input file name (no extension)--'); if (eoln(term_in)) then {so the first |read| works} read_ln (term_in); aux_name_length := 0; while (not eoln(term_in)) do begin if (aux_name_length = file_name_size) then begin while (not eoln(term_in)) do {discard the rest of the line} get(term_in); sam_you_made_the_file_name_too_long; end; incr(aux_name_length); name_of_file[aux_name_length] := term_in^; get(term_in); end; end; @<Handle this \.{.aux} name@>; aux_not_found: check_cmnd_line := false; end; aux_found: {now we're ready to read the \.{.aux} file} end; @y This module gets the file name from the UNIX command line, adds the various extensions, and tries to open the files with the resulting name. If there is a problem, just stop. @<Procedures and functions for the reading and processing of input files@>= procedure get_the_top_level_aux_file_name; begin setpaths; {sets up things for path searching} if argc <> 2 then begin write_ln(term_out,'Usage: bibtex <top-level-aux-file (no extension)>'); goto exit_program; end; aux_name_length:=1; argv(1,name_of_file); while (name_of_file[aux_name_length]<>' ')and (aux_name_length<file_name_size) do incr(aux_name_length); decr(aux_name_length); @<Handle this \.{.aux} name@>; end; @z @x goto aux_found; @y @z @x eof-->test_eof while (not eof(cur_bib_file)) do @y while (not test_eof(cur_bib_file)) do @z SHAR_EOF cat << \SHAR_EOF > bibtex.PYR.ch % Change file for BibTeX for Berkeley UNIX, by H. Trickey % History: % 5/28/84 Initial implementation, version 0.41 of BibTeX % 7/1/84 Version 0.41a of BibTeX. % 12/17/84 Version 0.97c of BibTeX. % 2/12/85 Version 0.98c of BibTeX. % 2/25/85 Newer Version 0.98c of BibTeX % 3/25/85 Version 0.98f of BibTeX % 5/23/85 Version 0.98i of BibTeX % 12/24/87 (SWS)Corrected for Pyramid 4.0 Pascal compiler % 2/6/88 Version 0.99a of BibTeX (PAM) % 2/16/88 Version 0.99c of BibTeX (PAM) @x banner @d banner=='This is BibTeX, Version 0.99c' {printed when the program starts} @y @d banner=='This is BibTeX, Version 0.99c for Berkeley UNIX' {printed when the program starts} @z @x term_out-->output Terminal output goes to the file |term_out|, while terminal input comes from |term_in|. On our system, these (system-dependent) files are already opened at the beginning of the program, and have the same real name. @d term_out == tty @d term_in == tty @y Terminal output goes to the (system-dependent) file |term_out|, while terminal input comes from |term_in|. On our system, they are already opened at the beginning of the program, and have the same real name. We define |term_out| to be |output|. |term_in| shouldn't be needed. @d term_out == output @z @x debug..gubed, stat..tats @d debug == @{ { remove the `|@{|' when debugging } @d gubed == @t@>@} { remove the `|@}|' when debugging } @f debug == begin @f gubed == end @# @d stat == @{ { remove the `|@{|' when keeping statistics } @d tats == @t@>@} { remove the `|@}|' when keeping statistics } @f stat == begin @f tats == end @y @d debug == @{ { remove the `|@{|' when debugging } @d gubed == @t@>@} { remove the `|@}|' when debugging } @f debug == begin @f gubed == end @# @d stat == @{ { remove the `|@{|' when keeping statistic } @d tats == @t@>@} { remove the `|@}|' when keeping statistic } @f stat==begin @f tats==end @z @x program header program BibTEX; {all files are opened dynamically} label close_up_shop,@!exit_program @<Labels in the outer block@>; const @<Constants in the outer block@> type @<Types in the outer block@> var @<Globals in the outer block@>@; @y program BibTEX(input,output); label close_up_shop,@!exit_program @<Labels in the outer block@>; const @<Constants in the outer block@> type @<Types in the outer block@> var @<Globals in the outer block@> @\@=#include "bibext.h"@>@\ {declarations for external C procedures} @z @x compiler directives @{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead} @!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging} @y @=(*C-*)@> {no range check, catch arithmetic overflow, no debug overhead} @!debug @=(*C+*)@>@+ gubed {but turn everything on when debugging} @z @x increase buf_size @!buf_size=1000; {maximum number of characters in an input line (or string)} @y @!buf_size=3000; {maximum number of characters in an input line (or string)} @z @x increase pool_size @!pool_size=65000; {maximum number of characters in strings} @y @!pool_size=200000; {maximum number of characters in strings} @z @x increase file_name_size @d file_name_size=40 {file names shouldn't be longer than this} @y @d file_name_size=1024 {file names shouldn't be longer than this} @z @x alpha_file type @!alpha_file=packed file of text_char; {files that contain textual data} @y @!alpha_file=text; {files that contain textual data} @z @x declare real_name_of_file |name_of_file|. \BibTeX\ does no case conversion for file names. @<Globals in the outer block@>= @!name_of_file:packed array[1..file_name_size] of char; {on some systems this is a \&{record} variable} @y |name_of_file|. \BibTeX\ does no case conversion for file names. The Berkeley UNIX version uses search paths to look for files to open. We use |real_name_of_file| to hold the |name_of_file| with a directory name from the path in front of it. @<Globals in the outer block@>= @!name_of_file,@!real_name_of_file:packed array[1..file_name_size] of char; @z @x opening files The \ph\ compiler with which the present version of \TeX\ was prepared has extended the rules of \PASCAL\ in a very convenient way. To open file~|f|, we can write $$\vbox{\halign{#\hfil\qquad&#\hfil\cr |reset(f,@t\\{name}@>,'/O')|&for input;\cr |rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$ The `\\{name}' parameter, which is of type `\ignorespaces|packed array[@t\<\\{any}>@>] of text_char|', stands for the name of the external file that is being opened for input or output. Blank spaces that might appear in \\{name} are ignored. The `\.{/O}' parameter tells the operating system not to issue its own error messages if something goes wrong. If a file of the specified name cannot be found, or if such a file cannot be opened for some other reason (e.g., someone may already be trying to write the same file), we will have |@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows \TeX\ to undertake appropriate corrective action. \TeX's file-opening procedures return |false| if no file identified by |name_of_file| could be opened. @d reset_OK(#)==erstat(#)=0 @d rewrite_OK(#)==erstat(#)=0 @<Procedures and functions for file-system interacting@>= function erstat(var f:file):integer; extern; {in the runtime library} @#@t\2@> function a_open_in(var f:alpha_file):boolean; {open a text file for input} begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f); end; @# function a_open_out(var f:alpha_file):boolean; {open a text file for output} begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f); end; @y @ The \ph\ compiler with which the present version of \TeX\ was prepared has extended the rules of \PASCAL\ in a very convenient way for file opening. Berkeley {\mc UNIX} \PASCAL\ isn't nearly as nice as \ph. Normally, it bombs out if a file open fails. An external C procedure, |test_access| is used to check whether or not the open will work. It is declared in the ``ext.h'' include file, and it returns |true| or |false|. The |name_of_file| global holds the file name whose access is to be tested. The first parameter for |test_access| is the access mode, one of |read_access_mode| or |write_access_mode|. We also implement path searching in |test_access|: its second parameter is one of the ``file path'' constants defined below. If |name_of_file| doesn't start with |'/'| then |test_access| tries prepending pathnames from the appropriate path list until success or the end of path list is reached. On return, |real_name_of_file| contains the original name with the path that succeeded (if any) prepended. It is the name used in the various open procedures. Path searching is not done for output files. @d read_access_mode=4 {``read'' mode for |test_access|} @d write_access_mode=2 {``write'' mode for |test_access|} @d no_file_path=0 {no path searching should be done} @d input_file_path=1 {path specifier for input files} @<Procedures and functions for file-system interacting@>= function a_open_in(var f:alpha_file):boolean; {open a text file for input} var @!ok:boolean; begin if test_access(read_access_mode,input_file_path) then begin reset(f,real_name_of_file); ok:=true@+end else ok:=false; a_open_in:=ok; end; @# function a_open_out(var f:alpha_file):boolean; {open a text file for output} var @!ok:boolean; begin if test_access(write_access_mode,no_file_path) then begin rewrite(f,real_name_of_file); ok:=true @+end else ok:=false; a_open_out:=ok; end; @z @x closing files Files can be closed with the \ph\ routine `|close(f)|', which should be used when all input or output with respect to |f| has been completed. This makes |f| available to be opened again, if desired; and if |f| was used for output, the |close| operation makes the corresponding external file appear on the user's area, ready to be read. @<Procedures and functions for file-system interacting@>= procedure a_close(var f:alpha_file); {close a text file} begin close(f); end; @y Files can be closed with the \ph\ routine `|close(f)|', which should be used when all input or output with respect to |f| has been completed. With the pc library, files will be automatically closed when the program stops and when one reopens them. @<Procedures and functions for file-system interacting@>= procedure a_close(var f:alpha_file); {close a text file} begin do_nothing; end; @z @x faster input_ln Standard \PASCAL\ says that a file should have |eoln| immediately before |eof|, but \BibTeX\ needs only a weaker restriction: If |eof| occurs in the middle of a line, the system function |eoln| should return a |true| result (even though |f^| will be undefined). @<Procedures and functions for all file I/O, error messages, and such@>= function input_ln(var f:alpha_file) : boolean; {inputs the next line or returns |false|} label loop_exit; begin last:=0; if (eof(f)) then input_ln:=false else begin while (not eoln(f)) do begin if (last >= buf_size) then buffer_overflow; buffer[last]:=xord[f^]; get(f); incr(last); end; get(f); while (last > 0) do {remove trailing |white_space|} if (lex_class[buffer[last-1]] = white_space) then decr(last) else goto loop_exit; loop_exit: input_ln:=true; end; end; @y With Berkeley {\mc UNIX} we call an external C procedure, |line_read|. That routine fills |buffer| from |0| onwards with the |xord|'ed values of the next line, setting |last| appropriately. It will stop if |last=buf_size|, and the following will cause an ``overflow'' abort. If one uses |input_ln| on a file, the normal |read| and |get| routines shouldn't be used, nor the |eof| and |eoln| tests. End of file can be tested with the external function |test_eof|. @<Procedures and functions for all file I/O, error messages, and such@>= function input_ln(var f:alpha_file) : boolean; {inputs the next line or returns |false|} label loop_exit; begin last:=0; if test_eof(f) then input_ln:=false else begin line_read(f,buf_size); if last>=buf_size then overflow('buffer size ',buf_size); while (last > 0) do {remove trailing |white_space|} if lex_class[buffer[last-1]] = white_space then decr(last) else goto loop_exit; loop_exit: input_ln:=true; end; end; @z @x getting top-level name: it comes from command line These modules read the name of the top-level \.{.aux} file. Some systems will try to find this on the command line; if it's not there it will come from the user's terminal. In either case, the name goes into the |char| array |name_of_file|, and the files relevant to this name are opened. @d aux_found=41 {go here when the \.{.aux} name is legit} @d aux_not_found=46 {go here when it's not} @y These modules read the name of the top-level \.{.aux} file. Some systems will try to find this on the command line; if it's not there it will come from the user's terminal. In either case, the name goes into the |char| array |name_of_file|, and the files relevant to this name are opened. @z @x redirect goto from |sam_you_made_the_file_name_too_long| @d sam_you_made_the_file_name_too_long == begin sam_too_long_file_name_print; goto aux_not_found; end @y @d sam_you_made_the_file_name_too_long == begin sam_too_long_file_name_print; goto exit_program end @z @x redirect goto from |sam_you_made_the_file_name_wrong| @d sam_you_made_the_file_name_wrong == begin sam_wrong_file_name_print; goto aux_not_found; end @y @d sam_you_made_the_file_name_wrong == begin sam_wrong_file_name_print; goto exit_program; end @z @x reading the command line This procedure consists of a loop that reads and processes a (nonnull) \.{.aux} file name. It's this module and the next two that must be changed on those systems using command-line arguments. Note: The |term_out| and |term_in| files are system dependent. @<Procedures and functions for the reading and processing of input files@>= procedure get_the_top_level_aux_file_name; label aux_found,@!aux_not_found; var @<Variables for possible command-line processing@>@/ begin check_cmnd_line := false; {many systems will change this} loop begin if (check_cmnd_line) then @<Process a possible command line@> else begin write (term_out,'Please type input file name (no extension)--'); if (eoln(term_in)) then {so the first |read| works} read_ln (term_in); aux_name_length := 0; while (not eoln(term_in)) do begin if (aux_name_length = file_name_size) then begin while (not eoln(term_in)) do {discard the rest of the line} get(term_in); sam_you_made_the_file_name_too_long; end; incr(aux_name_length); name_of_file[aux_name_length] := term_in^; get(term_in); end; end; @<Handle this \.{.aux} name@>; aux_not_found: check_cmnd_line := false; end; aux_found: {now we're ready to read the \.{.aux} file} end; @y This module gets the file name from the UNIX command line, adds the various extensions, and tries to open the files with the resulting name. If there is a problem, just stop. @<Procedures and functions for the reading and processing of input files@>= procedure get_the_top_level_aux_file_name; begin setpaths; {sets up things for path searching} if argc <> 2 then begin write_ln(term_out,'Usage: bibtex <top-level-aux-file (no extension)>'); goto exit_program; end; aux_name_length:=1; argv(1,name_of_file); while (name_of_file[aux_name_length]<>' ')and (aux_name_length<file_name_size) do incr(aux_name_length); decr(aux_name_length); @<Handle this \.{.aux} name@>; end; @z @x goto aux_found; @y @z @x eof-->test_eof while (not eof(cur_bib_file)) do @y while (not test_eof(cur_bib_file)) do @z SHAR_EOF cat << \SHAR_EOF > bibtex.SYS_V.ch % Change file for BibTeX for System V UNIX. % based on Berkeley UNIX Change file, by H. Trickey % History: % 5/28/84 Initial implementation, version 0.41 of BibTeX % 7/1/84 Version 0.41a of BibTeX. % 12/17/84 Version 0.97c of BibTeX. % 2/12/85 Version 0.98c of BibTeX. % 2/25/85 Newer Version 0.98c of BibTeX % 3/25/85 Version 0.98f of BibTeX % 5/23/85 Version 0.98i of BibTeX % 3/23/87 Mods for System V (lks) % 2/6/88 Version 0.99a of BibTeX (PAM) % 2/16/88 Version 0.99c of BibTeX (PAM) @x banner @d banner=='This is BibTeX, Version 0.99c' {printed when the program starts} @y @d banner=='This is BibTeX, Version 0.99c for System V UNIX' {printed when the program starts} @z @x terminal @d term_out == tty @d term_in == tty @y @d term_out == output @d term_in == input @z @x debug..gubed, stat..tats @d debug == @{ { remove the `|@{|' when debugging } @d gubed == @t@>@} { remove the `|@}|' when debugging } @f debug == begin @f gubed == end @# @d stat == @{ { remove the `|@{|' when keeping statistics } @d tats == @t@>@} { remove the `|@}|' when keeping statistics } @f stat == begin @f tats == end @y @d debug == @{ { remove the `|@{|' when debugging } @d gubed == @t@>@} { remove the `|@}|' when debugging } @f debug == begin @f gubed == end @# @d stat == @{ { remove the `|@{|' when keeping statistic } @d tats == @t@>@} { remove the `|@}|' when keeping statistic } @f stat==begin @f tats==end @z @x |log_file| and terminal. @y |log_file| and terminal. @d UNIXexit==e@&x@&i@&t @z @x program header program BibTEX; {all files are opened dynamically} label close_up_shop,@!exit_program @<Labels in the outer block@>; const @<Constants in the outer block@> type @<Types in the outer block@> var @<Globals in the outer block@>@; @y program BibTEX(input,output); label close_up_shop,@!exit_program @<Labels in the outer block@>; const @<Constants in the outer block@> type @<Types in the outer block@> var @<Globals in the outer block@> @\@=#include "bibext.h"@>@\ {declarations for external C procedures} @z @x exit_program: @y exit_program: UNIXexit(0); @z @x goto exit_program; @y UNIXexit(1); @z @x increase buf_size @!buf_size=1000; {maximum number of characters in an input line (or string)} @y @!buf_size=3000; {maximum number of characters in an input line (or string)} @z @x increase pool_size @!pool_size=65000; {maximum number of characters in strings} @y @!pool_size=200000; {maximum number of characters in strings} @z @x increase file_name_size @d file_name_size=40 {file names shouldn't be longer than this} @y @d file_name_size=1024 {file names shouldn't be longer than this} @z @x alpha_file type @!alpha_file=packed file of text_char; {files that contain textual data} @y @!alpha_file=text; {files that contain textual data} @z @x declare real_name_of_file |name_of_file|. \BibTeX\ does no case conversion for file names. @<Globals in the outer block@>= @!name_of_file:packed array[1..file_name_size] of char; {on some systems this is a \&{record} variable} @y |name_of_file|. \BibTeX\ does no case conversion for file names. The System V UNIX version uses search paths to look for files to open. We use |real_name_of_file| to hold the |name_of_file| with a directory name from the path in front of it. @<Globals in the outer block@>= @!name_of_file,@!real_name_of_file:packed array[1..file_name_size] of char; @z @x opening files The \ph\ compiler with which the present version of \TeX\ was prepared has extended the rules of \PASCAL\ in a very convenient way. To open file~|f|, we can write $$\vbox{\halign{#\hfil\qquad&#\hfil\cr |reset(f,@t\\{name}@>,'/O')|&for input;\cr |rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$ The `\\{name}' parameter, which is of type `\ignorespaces|packed array[@t\<\\{any}>@>] of text_char|', stands for the name of the external file that is being opened for input or output. Blank spaces that might appear in \\{name} are ignored. The `\.{/O}' parameter tells the operating system not to issue its own error messages if something goes wrong. If a file of the specified name cannot be found, or if such a file cannot be opened for some other reason (e.g., someone may already be trying to write the same file), we will have |@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows \TeX\ to undertake appropriate corrective action. \TeX's file-opening procedures return |false| if no file identified by |name_of_file| could be opened. @d reset_OK(#)==erstat(#)=0 @d rewrite_OK(#)==erstat(#)=0 @<Procedures and functions for file-system interacting@>= function erstat(var f:file):integer; extern; {in the runtime library} @#@t\2@> function a_open_in(var f:alpha_file):boolean; {open a text file for input} begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f); end; @# function a_open_out(var f:alpha_file):boolean; {open a text file for output} begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f); end; @y @ The \ph\ compiler with which the present version of \TeX\ was prepared has extended the rules of \PASCAL\ in a very convenient way for file opening. System V {\mc UNIX} \PASCAL\ isn't nearly as nice as \ph. Normally, it bombs out if a file open fails. An external C procedure, |test_access| is used to check whether or not the open will work. It is declared in the ``ext.h'' include file, and it returns |true| or |false|. The |name_of_file| global holds the file name whose access is to be tested. The first parameter for |test_access| is the access mode, one of |read_access_mode| or |write_access_mode|. We also implement path searching in |test_access|: its second parameter is one of the ``file path'' constants defined below. If |name_of_file| doesn't start with |'/'| then |test_access| tries prepending pathnames from the appropriate path list until success or the end of path list is reached. On return, |real_name_of_file| contains the original name with the path that succeeded (if any) prepended. It is the name used in the various open procedures. Path searching is not done for output files. @d read_access_mode=4 {``read'' mode for |test_access|} @d write_access_mode=2 {``write'' mode for |test_access|} @d no_file_path=0 {no path searching should be done} @d input_file_path=1 {path specifier for input files} @<Procedures and functions for file-system interacting@>= function a_open_in(var f:alpha_file):boolean; {open a text file for input} var @!ok:boolean; begin if test_access(read_access_mode,input_file_path) then begin reset(f,real_name_of_file); ok:=true@+end else ok:=false; a_open_in:=ok; end; @# function a_open_out(var f:alpha_file):boolean; {open a text file for output} var @!ok:boolean; begin if test_access(write_access_mode,no_file_path) then begin rewrite(f,real_name_of_file); ok:=true @+end else ok:=false; a_open_out:=ok; end; @z @x closing files Files can be closed with the \ph\ routine `|close(f)|', which should be used when all input or output with respect to |f| has been completed. This makes |f| available to be opened again, if desired; and if |f| was used for output, the |close| operation makes the corresponding external file appear on the user's area, ready to be read. @<Procedures and functions for file-system interacting@>= procedure a_close(var f:alpha_file); {close a text file} begin close(f); end; @y Files can be closed with the \ph\ routine `|close(f)|', which should be used when all input or output with respect to |f| has been completed. With the pc library, files will be automatically closed when the program stops and when one reopens them. @<Procedures and functions for file-system interacting@>= procedure a_close(var f:alpha_file); {close a text file} begin do_nothing; end; @z % remove non-local goto's (allows source to separated in pieces) @x @d confusion(#)==begin {fatal error---close up shop} print (#); print_confusion; goto close_up_shop; end @y @d confusion(#)==begin {fatal error---close up shop} print_ln(#); trace_and_stat_printing; a_close(log_file); UNIXexit(1); end @z @x faster input_ln Standard \PASCAL\ says that a file should have |eoln| immediately before |eof|, but \BibTeX\ needs only a weaker restriction: If |eof| occurs in the middle of a line, the system function |eoln| should return a |true| result (even though |f^| will be undefined). @<Procedures and functions for all file I/O, error messages, and such@>= function input_ln(var f:alpha_file) : boolean; {inputs the next line or returns |false|} label loop_exit; begin last:=0; if (eof(f)) then input_ln:=false else begin while (not eoln(f)) do begin if (last >= buf_size) then buffer_overflow; buffer[last]:=xord[f^]; get(f); incr(last); end; get(f); while (last > 0) do {remove trailing |white_space|} if (lex_class[buffer[last-1]] = white_space) then decr(last) else goto loop_exit; loop_exit: input_ln:=true; end; end; @y With System V {\mc UNIX} we call an external C procedure, |line_read|. That routine fills |buffer| from |0| onwards with the |xord|'ed values of the next line, setting |last| appropriately. It will stop if |last=buf_size|, and the following will cause an ``overflow'' abort. If one uses |input_ln| on a file, the normal |read| and |get| routines shouldn't be used, nor the |eof| and |eoln| tests. End of file can be tested with the external function |test_eof|. @<Procedures and functions for all file I/O, error messages, and such@>= function input_ln(var f:alpha_file) : boolean; {inputs the next line or returns |false|} label loop_exit; begin last:=0; if test_eof(f) then input_ln:=false else begin line_read(f,buf_size); if last>=buf_size then overflow('buffer size ',buf_size); while (last > 0) do {remove trailing |white_space|} if lex_class[buffer[last-1]] = white_space then decr(last) else goto loop_exit; loop_exit: input_ln:=true; end; end; @z @x getting top-level name: it comes from command line These modules read the name of the top-level \.{.aux} file. Some systems will try to find this on the command line; if it's not there it will come from the user's terminal. In either case, the name goes into the |char| array |name_of_file|, and the files relevant to this name are opened. @d aux_found=41 {go here when the \.{.aux} name is legit} @d aux_not_found=46 {go here when it's not} @y These modules read the name of the top-level \.{.aux} file. Some systems will try to find this on the command line; if it's not there it will come from the user's terminal. In either case, the name goes into the |char| array |name_of_file|, and the files relevant to this name are opened. @z @x redirect goto from |sam_you_made_the_file_name_too_long| @d sam_you_made_the_file_name_too_long == begin sam_too_long_file_name_print; goto aux_not_found; end @y @d sam_you_made_the_file_name_too_long == begin sam_too_long_file_name_print; UNIXexit(1) end @z @x redirect goto from |sam_you_made_the_file_name_wrong| @d sam_you_made_the_file_name_wrong == begin sam_wrong_file_name_print; goto aux_not_found; end @y @d sam_you_made_the_file_name_wrong == begin sam_wrong_file_name_print; UNIXexit(1); end @z @x reading the command line This procedure consists of a loop that reads and processes a (nonnull) \.{.aux} file name. It's this module and the next two that must be changed on those systems using command-line arguments. Note: The |term_out| and |term_in| files are system dependent. @<Procedures and functions for the reading and processing of input files@>= procedure get_the_top_level_aux_file_name; label aux_found,@!aux_not_found; var @<Variables for possible command-line processing@>@/ begin check_cmnd_line := false; {many systems will change this} loop begin if (check_cmnd_line) then @<Process a possible command line@> else begin write (term_out,'Please type input file name (no extension)--'); if (eoln(term_in)) then {so the first |read| works} read_ln (term_in); aux_name_length := 0; while (not eoln(term_in)) do begin if (aux_name_length = file_name_size) then begin while (not eoln(term_in)) do {discard the rest of the line} get(term_in); sam_you_made_the_file_name_too_long; end; incr(aux_name_length); name_of_file[aux_name_length] := term_in^; get(term_in); end; end; @<Handle this \.{.aux} name@>; aux_not_found: check_cmnd_line := false; end; aux_found: {now we're ready to read the \.{.aux} file} end; @y This module gets the file name from the UNIX command line, adds the various extensions, and tries to open the files with the resulting name. If there is a problem, just stop. @<Procedures and functions for the reading and processing of input files@>= procedure get_the_top_level_aux_file_name; begin setpaths; {sets up things for path searching} if argc <> 2 then begin write_ln(term_out,'Usage: bibtex <top-level-aux-file (no extension)>'); UNIXexit(1); end; aux_name_length:=1; argv(2,name_of_file); while (name_of_file[aux_name_length]<>' ')and (aux_name_length<file_name_size) do incr(aux_name_length); decr(aux_name_length); @<Handle this \.{.aux} name@>; end; @z @x goto aux_found; @y @z % eliminate non-local goto's (yucch) @x @!bst_line_num : integer; {line number of the \.{.bst} file} @y @!bst_line_num : integer; {line number of the \.{.bst} file} @!bst_done_flag: boolean; @z @x procedure bst_err_print_and_look_for_blank_line; @y procedure bst_err_print_and_look_for_blank_line; label exit; @z @x goto bst_done @y begin bst_done_flag:=true; return end @z @x end; @y exit: end; @z @x if (bst_str = 0) then {there's no \.{.bst} file to read} @y bst_done_flag:=false; if (bst_str = 0) then {there's no \.{.bst} file to read} @z @x get_bst_command_and_process; @y get_bst_command_and_process; if bst_done_flag then goto bst_done; @z @x eof-->test_eof while (not eof(cur_bib_file)) do @y while (not test_eof(cur_bib_file)) do @z SHAR_EOF cat << \SHAR_EOF > makebib.SYS_V set -x # change the following to remove intermediate files RM=echo # definitions needed for Pascal compilation PC0=/usr/lib/pc0 PC1=/usr/lib/pc1 PC2=/usr/lib/pc2 # compile with no range check PC0OPTS="-T r" # where assembler temporaries are put TMPDIR=/usr/tmp export TMPDIR name=bibtex # break up the monolithic pascal source into # six pieces. this prevents the System V Pascal # compiler or assembler from running out of internal # table space. sed -f bibsep.sed <$name.p # simulate pc -c on each individual piece. # we don't use pc because it insists on placing temporaries # in /tmp, and we don't have much disk space there. # see also the definition of TMPDIR above. for i in 1 2 do piece=${name}$i $PC0 -o $piece.0 $PC0OPTS $piece.p case $? in 0) $PC1 <$piece.0 >$piece.s $PC2 <$piece.s >$piece.0 as -o $piece.o $piece.0 ;; 1) $PC1 <$piece.0 >$piece.s # can not run optimizer as -o $piece.o $piece.s ;; esac $RM $piece.0 $piece.s done pc -o bibtex bibtex2.o bibtex1.o bibext.o SHAR_EOF # End of shell archive exit 0