-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+ X`09perror("Can't create symbol for subprocess command"); X`09exit(EXIT_ERR); X`09`7D X if (0 == (1&(vaxc$errno = lib$spawn(&cmd, &null, 0, &17, 0, &pid)))) X`09`7B X`09errno = EVMSERR; X`09perror("Can't spawn subprocess"); X`09exit(EXIT_ERR); X`09`7D X#ifdef DEBUG X fprintf(stderr, "%s\n", command); X#endif X fprintf(stderr, "%08X\n", pid); X return(EXIT_OK); X`7D X`0C X/* got this off net.sources */ X X#ifdef`09VMS X#define`09index`09strchr X#endif`09/*VMS*/ X X/* X * get option letter from argument vector X */ Xint`09opterr = 1,`09`09/* useless, never set or used */ X`09optind = 1,`09`09/* index into parent argv vector */ X`09optopt;`09`09`09/* character checked for validity */ Xchar`09*optarg;`09`09/* argument associated with option */ X X#define BADCH`09(int)'?' X#define EMSG`09"" X#define tell(s)`09fputs(*nargv,stderr);fputs(s,stderr); \ X`09`09fputc(optopt,stderr);fputc('\n',stderr);return(BADCH); X Xgetopt(nargc,nargv,ostr) Xint`09nargc; Xchar`09**nargv, X`09*ostr; X`7B X`09static char`09*place = EMSG;`09/* option letter processing */ X`09register char`09*oli;`09`09/* option letter list index */ X`09char`09*index(); X X`09if(!*place) `7B`09`09`09/* update scanning pointer */ X`09`09if(optind >= nargc `7C`7C *(place = nargv`5Boptind`5D) != '-' `7C`7C ! V*++place) return(EOF); X`09`09if (*place == '-') `7B`09/* found "--" */ X`09`09`09++optind; X`09`09`09return(EOF); X`09`09`7D X`09`7D`09`09`09`09/* option letter okay? */ X`09if ((optopt = (int)*place++) == (int)':' `7C`7C !(oli = index(ostr,optopt V))) `7B X`09`09if(!*place) ++optind; X`09`09tell(": illegal option -- "); X`09`7D X`09if (*++oli != ':') `7B`09`09/* don't need argument */ X`09`09optarg = NULL; X`09`09if (!*place) ++optind; X`09`7D X`09else `7B`09`09`09`09/* need an argument */ X`09`09if (*place) optarg = place;`09/* no white space */ X`09`09else if (nargc <= ++optind) `7B`09/* no arg */ X`09`09`09place = EMSG; X`09`09`09tell(": option requires an argument -- "); X`09`09`7D X`09 `09else optarg = nargv`5Boptind`5D;`09/* white space */ X`09`09place = EMSG; X`09`09++optind; X`09`7D X`09return(optopt);`09`09`09/* dump back option letter */ X`7D $ CALL UNPACK [.SRC]ARGPROC.C;1 303622112 $ create 'f' X$ cc/object=`5B-.bld`5D diff X$ cc/object=`5B-.bld`5D argproc X$ link/notrace/exec=`5B-.bld`5D `5B-.bld`5Ddiff,`5B-.bld`5Dargproc,sys$input V:/opt Xsys$share:vaxcrtl.exe/share $ CALL UNPACK [.SRC]BUILD_DIFF.COM;2 2081124049 $ create 'f' X$ on error then goto oops X$ cc /obj=`5B-.bld`5D patch.c X$ cc /obj=`5B-.bld`5D inp.c X$ cc /obj=`5B-.bld`5D util.c X$ cc /obj=`5B-.bld`5D version.c X$ cc /obj=`5B-.bld`5D pch.c X$ cc /obj=`5B-.bld`5D argproc.c X$! X$ link/notrace/exec=`5B-.bld`5D - X`5B-.bld`5Dpatch,`5B-.bld`5Dinp,`5B-.bld`5Dutil,`5B-.bld`5Dversion,`5B-.bld` V5Dpch,- X`5B-.bld`5Dargproc,sys$input:/opt Xsys$share:vaxcrtl.exe/share X$ write sys$output "Patch built successfully." X$ exit X$! X$ oops: X$ write sys$output "Errors in build." $ CALL UNPACK [.SRC]BUILD_PATCH.COM;3 1648977705 $ create 'f' X/* $Header: common.h,v 2.0 86/09/17 15:36:39 lwall Exp $ X * X * $Log:`09common.h,v $ X * Revision 2.0 86/09/17 15:36:39 lwall X * Baseline for netwide release. X *`20 X */ X X#define DEBUGGING X X#include "config.h" X X/* shut lint up about the following when return value ignored */ X X#define Signal (void)signal X#ifdef VMS X#define Unlink (void)delete X#define unlink delete X#else X#define Unlink (void)unlink X#endif X#define Lseek (void)lseek X#define Fseek (void)fseek X#define Fstat (void)fstat X#define Pclose (void)pclose X#define Close (void)close X#define Fclose (void)fclose X#define Fflush (void)fflush X#define Sprintf (void)sprintf X#define Mktemp (void)mktemp X#define Strcpy (void)strcpy X#define Strcat (void)strcat X X#ifdef VMS X#include ctype X#include signal X#include stdio X#include assert X#include types X#include stat X#else X#include X#include X#include X#include X#include X#include X#endif X X/* constants */ X X#define TRUE (1) X#define FALSE (0) X X#define MAXHUNKSIZE 100000`09`09/* is this enough lines? */ X#define INITHUNKMAX 125`09`09`09/* initial dynamic allocation size */ X#define MAXLINELEN 1024 X#define BUFFERSIZE 1024 X#define ORIGEXT ".orig" X#define SCCSPREFIX "s." X#define GET "get -e %s" X#define RCSSUFFIX ",v" X#define CHECKOUT "co -l %s" X X/* handy definitions */ X X#define Null(t) ((t)0) X#define Nullch Null(char *) X#define Nullfp Null(FILE *) X#define Nulline Null(LINENUM) X X#define Ctl(ch) ((ch) & 037) X X#define strNE(s1,s2) (strcmp(s1, s2)) X#define strEQ(s1,s2) (!strcmp(s1, s2)) X#define strnNE(s1,s2,l) (strncmp(s1, s2, l)) X#define strnEQ(s1,s2,l) (!strncmp(s1, s2, l)) X X/* typedefs */ X Xtypedef char bool; Xtypedef long LINENUM;`09`09`09/* must be signed */ Xtypedef unsigned MEM;`09`09`09/* what to feed malloc */ X X/* globals */ X XEXT int Argc;`09`09`09`09/* guess */ XEXT char **Argv; XEXT int Argc_last;`09`09`09/* for restarting plan_b */ XEXT char **Argv_last; X XEXT struct stat filestat;`09`09/* file statistics area */ XEXT int filemode INIT(0644); X XEXT char buf`5BMAXLINELEN`5D;`09`09/* general purpose buffer */ XEXT FILE *ofp INIT(Nullfp);`09`09/* output file pointer */ XEXT FILE *rejfp INIT(Nullfp);`09`09/* reject file pointer */ X XEXT bool using_plan_a INIT(TRUE);`09/* try to keep everything in memory */ XEXT bool out_of_mem INIT(FALSE);`09/* ran out of memory in plan a */ X X#define MAXFILEC 2 XEXT int filec INIT(0);`09`09`09/* how many file arguments? */ XEXT char *filearg`5BMAXFILEC`5D; XEXT bool ok_to_create_file INIT(FALSE); XEXT char *bestguess INIT(Nullch);`09/* guess at correct filename */ X XEXT char *outname INIT(Nullch); XEXT char rejname`5B128`5D; X XEXT char *origext INIT(Nullch); X X#ifdef VMS Xchar TMPOUTNAME`5B`5D = "sys$scratch:patchoXXXXXX"; Xchar TMPINNAME`5B`5D = "sys$scratch:patchiXXXXXX"; Xchar TMPREJNAME`5B`5D = "sys$scratch:patchrXXXXXX"; Xchar TMPPATNAME`5B`5D = "sys$scratch:patchpXXXXXX"; X#else XEXT char TMPOUTNAME`5B`5D INIT("/tmp/patchoXXXXXX"); XEXT char TMPINNAME`5B`5D INIT("/tmp/patchiXXXXXX");`09/* might want /usr/tmp V here */ XEXT char TMPREJNAME`5B`5D INIT("/tmp/patchrXXXXXX"); XEXT char TMPPATNAME`5B`5D INIT("/tmp/patchpXXXXXX"); X#endif X XEXT bool toutkeep INIT(FALSE); XEXT bool trejkeep INIT(FALSE); X XEXT LINENUM last_offset INIT(0); X#ifdef DEBUGGING XEXT int debug INIT(0); X#endif XEXT LINENUM maxfuzz INIT(2); XEXT bool force INIT(FALSE); XEXT bool verbose INIT(TRUE); XEXT bool reverse INIT(FALSE); XEXT bool noreverse INIT(FALSE); XEXT bool skip_rest_of_patch INIT(FALSE); XEXT int strippath INIT(957); XEXT bool canonicalize INIT(FALSE); X X#define CONTEXT_DIFF 1 X#define NORMAL_DIFF 2 X#define ED_DIFF 3 X#define NEW_CONTEXT_DIFF 4 XEXT int diff_type INIT(0); X XEXT bool do_defines INIT(FALSE);`09/* patch using ifdef, ifndef, etc. */ XEXT char if_defined`5B128`5D;`09`09/* #ifdef xyzzy */ XEXT char not_defined`5B128`5D;`09`09/* #ifndef xyzzy */ XEXT char else_defined`5B`5D INIT("#else\n");/* #else */ XEXT char end_defined`5B128`5D;`09`09/* #endif xyzzy */ X XEXT char *revision INIT(Nullch);`09/* prerequisite revision, if any */ X Xchar *malloc(); Xchar *realloc(); Xchar *strcpy(); Xchar *strcat(); Xlong atol(); Xlong lseek(); Xchar *mktemp(); $ CALL UNPACK [.SRC]COMMON.H;1 1450187579 $ create 'f' X/* config.h X * This file was produced by running the Configure script. X * Feel free to modify any of this as the need arises. X */ X X X#define`09`09EUNICE`09`09/* no file linking? */ X#define`09`09VMS`09`09/* other assorted ickies? */ X X#define`09`09index strchr`09/* cultural */ X#define`09`09rindex strrchr`09/* differences? */ X X#/*undef`09void int`09/* is void to be avoided? */ X X/* How many register declarations are paid attention to? */ X X#define Reg1 register`09`09/**/ X#define Reg2 register`09`09/**/ X#define Reg3 register`09`09/**/ X#define Reg4 register`09`09/**/ X#define Reg5 register`09`09/**/ X#define Reg6 register`09`09/**/ X#define Reg7 `09`09/**/ X#define Reg8 `09`09/**/ X#define Reg9 `09`09/**/ X#define Reg10 `09`09/**/ X#define Reg11 `09`09/**/ X#define Reg12 `09`09/**/ X#define Reg13 `09`09/**/ X#define Reg14 `09`09/**/ X#define Reg15 `09`09/**/ X#define Reg16 `09`09/**/ X $ CALL UNPACK [.SRC]CONFIG.H;1 688866093 $ create 'f' X/* X * diff.c - public domain context diff program X * X * This is pd-diff from comp.sources.misc. X */ X X#ifdef TURBO X#include X#include X#include X#include X#include X#include X X#else `20 X X#ifdef VMS X X#include ssdef X#include stsdef X#include stdio X#include ctype X#define IO_SUCCESS -1 X#define IO_ERROR 1 X X#else X X#include X#include X X#endif /* vms */ X X#endif /* TURBO */ X X#define EOS `090 X#ifdef unix Xchar temfile`5BL_tmpnam`5D; Xchar *tmpnam(); X#define TEMPFILE (temfile`5B0`5D? temfile: (tmpnam(temfile), temfile)) X#else /* unix */ X#define TEMPFILE "diff.tmp" X#endif /* unix */ X#define TRUE `091 X#define FALSE `090 X X#ifdef pdp11 X#define short int X#endif /* pdp11 */ X Xtypedef struct candidate `7B X`09int b;`09`09`09/* Line in fileB `09 */ X`09int a;`09`09`09/* Line in fileA `09 */ X`09int link;`09`09/* Previous candidate `09 */ X`7D CANDIDATE; X Xtypedef struct line `7B X`09unsigned short hash;`09`09/* Hash value etc. `09 */ X`09short serial;`09`09/* Line number `09 */ X`7D LINE; X XLINE *file`5B2`5D;`09`09/* Hash/line for total file */ X#define fileA file`5B0`5D X#define fileB file`5B1`5D X XLINE *sfile`5B2`5D;`09`09/* Hash/line after prefix */ X#define sfileA sfile`5B0`5D X#define sfileB sfile`5B1`5D X Xint len`5B2`5D;`09`09`09/* Actual lines in each file */ X#define lenA len`5B0`5D X#define lenB len`5B1`5D X Xint slen`5B2`5D;`09`09/* Squished lengths `09 */ X#define slenA slen`5B0`5D X#define slenB slen`5B1`5D X Xint prefix;`09`09`09/* Identical lines at start */ Xint suffix;`09`09`09/* Identical lenes at end */ X XFILE *infd`5B2`5D = `7BNULL, NULL`7D;`09/* Input file identifiers V */ XFILE *tempfd;`09`09`09/* Temp for input redirection */ X Xextern long ftell(); Xextern FILE *fopen(); X X#ifdef TURBO Xextern void *malloc(); X#else /* !TURBO */ Xextern char *malloc(); X#endif /* TURBO */ X Xchar *fgetss(); Xunsigned short hash(); X X#ifdef`09AMIGA X/* Define these types for Amiga C */ Xchar *savptr; Xint savsiz; Xchar *wrk; Xchar *wrk2; Xint cpysiz; X#endif /* AMIGA */ X X/* X * The following vectors overlay the area defined by fileA X */ X Xshort *class;`09`09`09/* Unsorted line numbers */ Xint *klist;`09`09`09/* Index of element in clist */ XCANDIDATE *clist;`09`09`09/* Storage pool for candidates */ Xint clength = 0;`09/* Number of active candidates */ X#define`09CSIZE_INC 50`09`09`09/* How many to allocate each time we have to V */ Xint csize = CSIZE_INC;`09`09/* Current size of storage pool */ X Xint *match;`09`09`09/* Longest subsequence `09 */ Xlong *oldseek;`09`09/* Seek position in file A */ X X/* X * The following vectors overlay the area defined by fileB X */ X Xshort *member;`09`09`09/* Concatenated equiv. classes */ Xlong *newseek;`09`09/* Seek position in file B */ Xchar *textb;`09`09`09/* Input from file2 for check */ X X/* X * Global variables X */ X Xint eflag = FALSE;`09/* Edit script requested */ Xint bflag = FALSE;`09/* Blank supress requested */ Xint cflag = FALSE;`09/* Context printout `09 */ Xint iflag = FALSE;`09/* Ignore case requested */ Xchar text`5B257`5D;`09`09/* Input line from file1 */ Xextern char *myalloc();`09`09/* Storage allocator `09 */ X Xextern char *compact();`09`09/* Storage compactor `09 */ X X#ifdef DEBUG X#ifndef OSK X#define TIMING X#endif /* OSK */ X#endif /* DEBUG */ X#ifdef TIMING Xextern long time(); Xextern char *4532mend; Xlong totaltime; Xlong sectiontime; Xchar *mstart; X#endif /* TIMING */ Xvoid`09`09`09free(); Xvoid`09`09`09exit(); X#ifndef OSK Xvoid`09`09`09perror(); X#endif /* OSK */ X X/* X * Diff main program X */ X Xmain(argc, argv) X`09int argc; X`09char **argv; X`7B X`09register int i; X`09register char *ap; X X#ifdef OSK X`09extern int _memmins; X`09_memmins = 16 * 1024;`09`09/* tell OSK we will malloc a lot */ X#endif /* OSK */ X#ifdef TIMING X`09sectiontime = time(&totaltime); X#endif /* TIMING */ X X#ifdef VMS X`09getredirection(&argc, &argv); X#endif X`09while (argc > 1 && *(ap = argv`5B1`5D) == '-' && *++ap != EOS) `7B X`09`09while (*ap != EOS) `7B X`09`09`09switch ((*ap++)) `7B X`09`09`09case 'b': X`09`09`09`09bflag++; X`09`09`09`09break; X X`09`09`09case 'c': X`09`09`09`09if (*ap > '0' && *ap <= '9') X`09`09`09`09`09cflag = *ap++ - '0'; X`09`09`09`09else X`09`09`09`09`09cflag = 3; X`09`09`09`09break; X X`09`09`09case 'e': X`09`09`09`09eflag++; X`09`09`09`09break; X X`09`09`09case 'i': X`09`09`09`09iflag++; X`09`09`09`09break; X X`09`09`09default: X`09`09`09`09fprintf(stderr, X`09`09`09`09`09`09"Warning, bad option '%c'\n", X`09`09`09`09`09`09ap`5B-1`5D); X`09`09`09`09break; X`09`09`09`7D X`09`09`7D X`09`09argc--; X`09`09argv++; X`09`7D X X#ifdef VMS X`09/* For VMS, we allow comparison of a particular version of a file X`09 AND the version immediately preeceding it. This is implied by X`09 simply mentioning the single file name. */ X`09if (argc == 2) `7B X`09`09if (argv`5B0`5D = previous_version(argv`5B1`5D)) `7B X`09`09`09--argv; X`09`09`09++argc; X`09`09`7D X`09`7D X#endif X`09if (argc != 3) X`09`09error("Usage: diff `5B-options`5D file1 file2"); X`09if (cflag && eflag) `7B X`09`09fprintf(stderr, X`09`09`09`09"Warning, -c and -e are incompatible, -c supressed.\n"); X`09`09cflag = FALSE; X`09`7D X`09argv++; X`09for (i = 0; i <= 1; i++) `7B X`09`09if (argv`5Bi`5D`5B0`5D == '-' && argv`5Bi`5D`5B1`5D == EOS) `7B X`09`09`09infd`5Bi`5D = stdin; X`09`09`09if ((tempfd = fopen(TEMPFILE, "w")) == NULL) X`09`09`09`09cant(TEMPFILE, "work", 1); X`09`09`7D else `7B X`09`09`09infd`5Bi`5D = fopen(argv`5Bi`5D, "r" X#ifdef VMS X`09`09`09`09`09`09 , "mbc=64", "mbf=2" X#endif X`09`09`09`09`09`09`09); X`09`09`7D X`09`7D X X`09if (infd`5B0`5D == stdin && infd`5B1`5D == stdin) X`09`09error("Can't diff two things both on standard input."); X X`09if (infd`5B0`5D == NULL && infd`5B1`5D == NULL) `7B X`09`09cant(argv`5B0`5D, "input", 0); X`09`09cant(argv`5B1`5D, "input", 1); X`09`7D X#ifdef VMS X`09if (infd`5B1`5D == NULL) X`09`09opendir(1, &argv`5B1`5D, infd`5B0`5D); X`09else if (infd`5B0`5D == NULL) X`09`09opendir(0, &argv`5B0`5D, infd`5B1`5D); X#endif /* vms */ X`09for (i = 0; i <= 1; i++) X`09`09if (!infd`5Bi`5D) X`09`09`09cant(argv`5Bi`5D, "input", 2);`09`09/* Fatal error */ X X`09/* X`09 * Read input, building hash tables.`20 X`09 */ X`09input(0); X`09input(1); X`09squish(); X#ifdef DEBUG X`09printf("before sort\n"); X`09for (i = 1; i <= slenA; i++) X`09`09printf("sfileA`5B%d`5D = %6d %06o\n", X`09`09`09 i, sfileA`5Bi`5D.serial, sfileA`5Bi`5D.hash); X`09for (i = 1; i <= slenB; i++) X`09`09printf("sfileB`5B%d`5D = %6d %06o\n", X`09`09`09 i, sfileB`5Bi`5D.serial, sfileB`5Bi`5D.hash); X#endif /* DEBUG */ X`09sort(sfileA, slenA); X`09sort(sfileB, slenB); X#ifdef TIMING X`09ptime("input"); X#endif /* TIMING */ X#ifdef DEBUG X`09printf("after sort\n"); X`09for (i = 1; i <= slenA; i++) X`09`09printf("sfileA`5B%d`5D = %6d %06o\n", X`09`09`09 i, sfileA`5Bi`5D.serial, sfileB`5Bi`5D.hash); X`09for (i = 1; i <= slenB; i++) X`09`09printf("sfileB`5B%d`5D = %6d %06o\n", X`09`09`09 i, sfileB`5Bi`5D.serial, sfileB`5Bi`5D.hash); X#endif /* DEBUG */ X X`09/* X`09 * Build equivalence classes.`20 X`09 */ X`09member = (short *) fileB; X`09equiv(); X`09member = (short *) compact((char *) member, (slenB + 2) * sizeof(int), X`09`09`09`09`09`09`09 "squeezing member vector"); X X`09/* X`09 * Reorder equivalence classes into array class`5B`5D`20 X`09 */ X`09class = (short *) fileA; X`09unsort(); X`09class = (short *) compact((char *) class, (slenA + 2) * sizeof(int), X`09`09`09`09`09`09`09 "compacting class vector"); X#ifdef TIMING X`09ptime("equiv/unsort"); X#endif /* TIMING */ X X`09/* X`09 * Find longest subsequences`20 X`09 */ X`09klist = (int *) myalloc((slenA + 2) * sizeof(int), "klist"); X`09clist = (CANDIDATE *) myalloc(csize * sizeof(CANDIDATE), "clist"); X`09i = subseq(); X#ifndef OSK X`09free((char *) member); X`09free((char *) class); X#else /* OSK */ X`09free((char *) member - sizeof(int)); X`09free((char *) class - sizeof(int)); X#endif /* OSK */ X`09match = (int *) myalloc((lenA + 2) * sizeof(int), "match"); X`09unravel(klist`5Bi`5D); X#ifndef OSK X`09free((char *) clist); X`09free((char *) klist); X#else /* OSK */ X`09free((char *) clist - sizeof(int)); X`09free((char *) klist - sizeof(int)); X#endif /* OSK */ X#ifdef TIMING X`09ptime("subsequence/unravel"); X#endif /* TIMING */ X X`09/* X`09 * Check for fortuitous matches and output differences`20 X`09 */ X`09oldseek = (long *) myalloc((lenA + 2) * sizeof(*oldseek), "oldseek"); X`09newseek = (long *) myalloc((lenB + 2) * sizeof(*newseek), "newseek"); X`09textb = myalloc(sizeof text, "textbuffer"); X`09if (check(argv`5B0`5D, argv`5B1`5D)) X`09`09fprintf(stderr, "Spurious match, output is not optimal\n"); X#ifdef TIMING X`09ptime("check"); X#endif /* TIMING */ X`09output(argv`5B0`5D, argv`5B1`5D); X#ifdef TIMING X`09ptime("output"); X`09printf("%ld seconds required\n", sectiontime - totaltime); X#endif /* TIMING */ X`09if (tempfd != NULL) `7B X`09`09fclose(tempfd); X#ifdef unix X`09`09unlink(TEMPFILE); X#else /* !unix */ X#ifdef OSK X`09`09unlink(TEMPFILE); X#else /* OSK */ X#ifdef MSC`09`09`09`09`09`09/* MSC 4.0 does not understand disjunctive X`09`09`09`09`09`09`09`09 * #if's. */ X`09`09unlink(TEMPFILE); X#else /* MSC */ X`09`09remove(TEMPFILE); X#endif /* MSC */ X#endif /* OSK */ X#endif /* unxi */ X`09`7D X#ifdef VMS X`09exit(0); X#else X`09return(IO_SUCCESS); X#endif X`7D X X X/* X * Read the file, building hash table X */ X Xinput(which) X`09int which;`09`09/* 0 or 1 to redefine infd`5B`5D */ X`7B X`09register LINE *lentry; X`09register int linect = 0; X`09FILE *fd; X#define`09LSIZE_INC 200`09`09`09/* # of line entries to alloc at once */ X`09int lsize = LSIZE_INC; X X`09lentry = (LINE *) myalloc(sizeof(LINE) * (lsize + 3), "line"); X`09fd = infd`5Bwhich`5D; X`09while (!getline(fd, text)) `7B X`09`09if (++linect >= lsize) `7B X`09`09`09lsize += 200; X`09`09`09lentry = (LINE *) compact((char *) lentry, X`09`09`09`09`09`09`09`09`09 (lsize + 3) * sizeof(LINE), X`09`09`09`09`09`09`09`09`09 "extending line vector"); X`09`09`7D X`09`09lentry`5Blinect`5D.hash = hash(text); X`09`7D X X`09/* X`09 * If input was from stdin ("-" command), finish off the temp file.`20 X`09 */ X`09if (fd == stdin) `7B X`09`09fclose(tempfd); X`09`09tempfd = infd`5Bwhich`5D = fopen(TEMPFILE, "r"); X`09`7D X X`09/* X`09 * If we wanted to be stingy with memory, we could realloc lentry down to X`09 * its exact size (+3 for some odd reason) here. No need? `20 X`09 */ X`09len`5Bwhich`5D = linect; X`09file`5Bwhich`5D = lentry; X`7D X X X/* X * Look for initial and trailing sequences that have identical hash values. X * Don't bother building them into the candidate vector. X */ X Xsquish() X`7B X`09register int i; X`09register LINE *ap; X`09register LINE *bp; X`09int j; X`09int k; X X`09/* X`09 * prefix -> first line (from start) that doesn't hash identically`20 X`09 */ X`09i = 0; X`09ap = &fileA`5B1`5D; X`09bp = &fileB`5B1`5D; X`09while (i < lenA && i < lenB && ap->hash == bp->hash) `7B X`09`09i++; X`09`09ap++; X`09`09bp++; X`09`7D X`09prefix = i; X X`09/* X`09 * suffix -> first line (from end) that doesn't hash identically`20 X`09 */ X`09j = lenA - i; X`09k = lenB - i; X`09ap = &fileA`5BlenA`5D; X`09bp = &fileB`5BlenB`5D; X`09i = 0; X`09while (i < j && i < k && ap->hash == bp->hash) `7B X`09`09i++; X`09`09ap--; X`09`09bp--; X`09`7D X`09suffix = i; X X`09/* X`09 * Tuck the counts away`20 X`09 */ X`09for (k = 0; k <= 1; k++) `7B X`09`09sfile`5Bk`5D = file`5Bk`5D + prefix; X`09`09j = slen`5Bk`5D = len`5Bk`5D - prefix - suffix; X X`09`09for (i = 0, ap = sfile`5Bk`5D; i <= slen`5Bk`5D; i++, ap++) `7B X`09`09`09ap->serial = i; X`09`09`7D X`09`7D X`7D X X X/* X * Sort hash entries X */ X Xsort(vector, vecsize) X`09LINE *vector;`09`09/* What to sort `09 */ X`09int vecsize;`09/* How many to sort `09 */ X`7B X`09register int j; X`09register LINE *aim; X`09register LINE *ai; X`09int mid; X`09int k; X`09LINE work; X X`09for (j = 1; j <= vecsize; j *= 2); X`09mid = (j - 1); X`09while ((mid /= 2) != 0) `7B X`09`09k = vecsize - mid; X`09`09for (j = 1; j <= k; j++) `7B X`09`09`09for (ai = &vector`5Bj`5D; ai > vector; ai -= mid) `7B X`09`09`09`09aim = &ai`5Bmid`5D; X`09`09`09`09if (aim < ai) X`09`09`09`09`09break;`09`09/* ?? Why ?? `09 */ X`09`09`09`09if (aim->hash > ai->hash `7C`7C X`09`09`09`09`09aim->hash == ai->hash && X`09`09`09`09`09aim->serial > ai->serial) X`09`09`09`09`09break; X`09`09`09`09work.hash = ai->hash; X`09`09`09`09ai->hash = aim->hash; X`09`09`09`09aim->hash = work.hash; X`09`09`09`09work.serial = ai->serial; X`09`09`09`09ai->serial = aim->serial; X`09`09`09`09aim->serial = work.serial; X`09`09`09`7D X`09`09`7D X`09`7D X`7D X X X/* X * Build equivalence class vector X */ X Xequiv() X`7B X`09register LINE *ap; X`09union `7B X`09`09LINE *bp; X`09`09short *mp; X`09`7D r; X`09register int j; X`09LINE *atop; X X#ifdef DEBUG X`09printf("equiv entry\n"); X`09for (j = 1; j <= slenA; j++) X`09`09printf("sfileA`5B%d`5D = %6d %06o\n", X`09`09`09 j, sfileA`5Bj`5D.serial, sfileA`5Bj`5D.hash); X`09for (j = 1; j <= slenB; j++) X`09`09printf("sfileB`5B%d`5D = %6d %06o\n", X`09`09`09 j, sfileB`5Bj`5D.serial, sfileB`5Bj`5D.hash); X#endif /* DEBUG */ X`09j = 1; X`09ap = &sfileA`5B1`5D; X`09r.bp = &sfileB`5B1`5D; X`09atop = &sfileA`5BslenA`5D; X`09while (ap <= atop && j <= slenB) `7B X`09`09if (ap->hash < r.bp->hash) `7B X`09`09`09ap->hash = 0; X`09`09`09ap++; X`09`09`7D else if (ap->hash == r.bp->hash) `7B X`09`09`09ap->hash = j; X`09`09`09ap++; X`09`09`7D else `7B X`09`09`09r.bp++; X`09`09`09j++; X`09`09`7D X`09`7D X`09while (ap <= atop) `7B X`09`09ap->hash = 0; X`09`09ap++; X`09`7D X`09sfileB`5BslenB + 1`5D.hash = 0; X#ifdef DEBUG X`09printf("equiv exit\n"); X`09for (j = 1; j <= slenA; j++) X`09`09printf("sfileA`5B%d`5D = %6d %06o\n", X`09`09`09 j, sfileA`5Bj`5D.serial, sfileA`5Bj`5D.hash); X`09for (j = 1; j <= slenB; j++) X`09`09printf("sfileB`5B%d`5D = %6d %06o\n", X`09`09`09 j, sfileB`5Bj`5D.serial, sfileB`5Bj`5D.hash); X#endif /* DEBUG */ X`09ap = &sfileB`5B0`5D; X`09atop = &sfileB`5BslenB`5D; X`09r.mp = &member`5B0`5D; X`09while (++ap <= atop) `7B X`09`09r.mp++; X`09`09*r.mp = -(ap->serial); X`09`09while (ap`5B1`5D.hash == ap->hash) `7B X`09`09`09ap++; X`09`09`09r.mp++; X`09`09`09*r.mp = ap->serial; X`09`09`7D X`09`7D X`09r.mp`5B1`5D = -1; X#ifdef DEBUG X`09for (j = 0; j <= slenB; j++) X`09`09printf("member`5B%d`5D = %d\n", j, member`5Bj`5D); X#endif /* DEBUG */ X`7D X X X/* X * Build class vector X */ X Xunsort() X`7B X`09register int *temp; X`09register int *tp; X`09union `7B X`09`09LINE *ap; X`09`09short *cp; X`09`7D u; X`09LINE *evec; X`09short *eclass; X#ifdef DEBUG X`09int i; X#endif /* DEBUG */ X X`09temp = (int *) myalloc((slenA + 1) * sizeof(int), "unsort scratch"); X`09u.ap = &sfileA`5B1`5D; X`09evec = &sfileA`5BslenA`5D; X`09while (u.ap <= evec) `7B X#ifdef DEBUG X`09`09printf("temp`5B%2d`5D := %06o\n", u.ap->serial, u.ap->hash); X#endif /* DEBUG */ X`09`09temp`5Bu.ap->serial`5D = u.ap->hash; X`09`09u.ap++; X`09`7D X X`09/* X`09 * Copy into class vector and free work space`20 X`09 */ X`09u.cp = &class`5B1`5D; X`09eclass = &class`5BslenA`5D; X`09tp = &temp`5B1`5D; X`09while (u.cp <= eclass) X`09`09*u.cp++ = *tp++; X#ifndef OSK X`09free((char *) temp); X#else /* OSK */ X`09free((char *) temp - sizeof(int)); X#endif /* OSK */ X#ifdef DEBUG X`09printf("unsort exit\n"); X`09for (i = 1; i <= slenA; i++) X`09`09printf("class`5B%d`5D = %d %06o\n", i, class`5Bi`5D, class`5Bi`5D); X#endif /* DEBUG */ X`7D X X X/* X * Generate maximum common subsequence chain in clist`5B`5D X */ X Xsubseq() X`7B X`09int a; X`09register unsigned ktop; X`09register int b; X`09register int s; X`09unsigned r; X`09int i; X`09int cand; X X`09klist`5B0`5D = newcand(0, 0, -1); X`09klist`5B1`5D = newcand(slenA + 1, slenB + 1, -1); X`09ktop = 1;`09`09`09`09`09/* -> guard entry */ X`09for (a = 1; a <= slenA; a++) `7B X X`09`09/* X`09`09 * For each non-zero element in fileA ...`20 X`09`09 */ X`09`09if ((i = class`5Ba`5D) == 0) X`09`09`09continue; X`09`09cand = klist`5B0`5D;`09`09/* No candidate now */ X`09`09r = 0;`09`09`09`09`09/* Current r-candidate */ X`09`09do `7B X#ifdef DEBUG X`09`09`09printf("a = %d, i = %d, b = %d\n", a, i, member`5Bi`5D); X#endif /* DEBUG */ X X`09`09`09/* X`09`09`09 * Perform the merge algorithm`20 X`09`09`09 */ X`09`09`09if ((b = member`5Bi`5D) < 0) X`09`09`09`09b = -b; X#ifdef DEBUG X`09`09`09printf("search(%d, %d, %d) -> %d\n", X`09`09`09`09 r, ktop, b, search(r, ktop, b)); X#endif /* DEBUG */ X`09`09`09if ((s = search(r, ktop, b)) != 0) `7B X`09`09`09`09if (clist`5Bklist`5Bs`5D`5D.b > b) `7B X`09`09`09`09`09klist`5Br`5D = cand; X`09`09`09`09`09r = s; X`09`09`09`09`09cand = newcand(a, b, klist`5Bs - 1`5D); X#ifdef DEBUG X`09`09`09`09`09dumpklist(ktop, "klist`5Bs-1`5D->b > b"); X#endif /* DEBUG */ X`09`09`09`09`7D X`09`09`09`09if (s >= ktop) `7B X`09`09`09`09`09klist`5Bktop + 1`5D = klist`5Bktop`5D; X`09`09`09`09`09ktop++; X#ifdef DEBUG X`09`09`09`09`09klist`5Br`5D = cand; X`09`09`09`09`09dumpklist(ktop, "extend"); X#endif /* DEBUG */ X`09`09`09`09`09break; X`09`09`09`09`7D X`09`09`09`7D X`09`09`7D while (member`5B++i`5D > 0); X`09`09klist`5Br`5D = cand; X`09`7D X#ifdef DEBUG X`09printf("last entry = %d\n", ktop - 1); X#endif /* DEBUG */ X`09return (ktop - 1);`09`09`09/* Last entry found */ X`7D X X Xint Xnewcand(a, b, pred) X`09int a;`09`09`09/* Line in fileA `09 */ X`09int b;`09`09`09/* Line in fileB `09 */ X`09int pred;`09`09/* Link to predecessor, index in cand`5B`5D * V/ X`7B X`09register CANDIDATE *new; X X`09clength++; X`09if (++clength >= csize) `7B X`09`09csize += CSIZE_INC; X`09`09clist = (CANDIDATE *) compact((char *) clist, X`09`09`09`09`09`09`09`09`09 csize * sizeof(CANDIDATE), X`09`09`09`09`09`09`09`09`09 "extending clist"); X`09`7D X`09new = &clist`5Bclength - 1`5D; X`09new->a = a; X`09new->b = b; X`09new->link = pred; X`09return (clength - 1); X`7D X X X/* X * Search klist`5Blow..top`5D (inclusive) for b. If klist`5Blow`5D->b >= b, X * return zero. Else return s such that klist`5Bs-1`5D->b < b and X * klist`5Bs`5D->b >= b. Note that the algorithm presupposes the two X * preset "fence" elements, (0, 0) and (slenA, slenB). X */ X Xsearch(low, high, b) X`09register unsigned low; X`09register unsigned high; X`09register int b; X`7B X`09register int temp; X`09register unsigned mid; X X`09if (clist`5Bklist`5Blow`5D`5D.b >= b) X`09`09return (0); X`09while ((mid = (low + high) / 2) > low) `7B X`09`09if ((temp = clist`5Bklist`5Bmid`5D`5D.b) > b) X`09`09`09high = mid; X`09`09else if (temp < b) X`09`09`09low = mid; X`09`09else `7B X`09`09`09return (mid); X`09`09`7D X`09`7D X`09return (mid + 1); X`7D X X Xunravel(k) X`09register int k; X`7B X`09register int i; X`09register CANDIDATE *cp; X`09int first_trailer; X`09int difference; X X`09first_trailer = lenA - suffix; X`09difference = lenB - lenA; X#ifdef DEBUG X`09printf("first trailer = %d, difference = %d\n", X`09`09 first_trailer, difference); X#endif /* DEBUG */ X`09for (i = 0; i <= lenA; i++) `7B X`09`09match`5Bi`5D = (i <= prefix) ? i X`09`09`09: (i > first_trailer) ? i + difference X`09`09`09: 0; X`09`7D X#ifdef DEBUG X`09printf("unravel\n"); X#endif /* DEBUG */ X`09while (k != -1) `7B X`09`09cp = &clist`5Bk`5D; X#ifdef DEBUG X`09`09if (k < 0 `7C`7C k >= clength) X`09`09`09error("Illegal link -> %d", k); X`09`09printf("match`5B%d`5D := %d\n", cp->a + prefix, cp->b + prefix); X#endif /* DEBUG */ X`09`09match`5Bcp->a + prefix`5D = cp->b + prefix; X`09`09k = cp->link; X`09`7D X`7D X X X/* X * Check for hash matches (jackpots) and collect random access indices to X * the two files. X * X * It should be possible to avoid doing most of the ftell's by noticing X * that we are not doing a context diff and noticing that if a line X * compares equal to the other file, we will not ever need to know its X * file position. FIXME. X */ X Xcheck(fileAname, fileBname) X`09char *fileAname; X`09char *fileBname; X`7B X`09register int a;`09`09`09/* Current line in file A */ X`09register int b;`09`09`09/* Current line in file B */ X`09int jackpot; X X`09b = 1; X`09fclose(infd`5B0`5D); X`09infd`5B0`5D = fopen(fileAname, "r" X#ifdef VMS X`09`09`09`09 , "mbc=64", "mbf=2" X#endif X`09`09`09`09`09); X`09infd`5B1`5D = fopen(fileBname, "r" X#ifdef VMS X`09`09`09`09 , "mbc=64", "mbf=2" X#endif X`09`09`09`09`09); X/* X * See above; these would be over-written on VMS anyway. X */ X X#ifndef vms X`09oldseek`5B0`5D = ftell(infd`5B0`5D); X`09newseek`5B0`5D = ftell(infd`5B1`5D); X#endif /* vms */ X X`09jackpot = 0; X#ifdef DEBUG X`09printf("match vector\n"); X`09for (a = 0; a <= lenA; a++) X`09`09printf("match`5B%d`5D = %d\n", a, match`5Ba`5D); X#endif /* DEBUG */ X`09for (a = 1; a <= lenA; a++) `7B X`09`09if (match`5Ba`5D == 0) `7B X`09`09`09/* Unique line in A */ X`09`09`09oldseek`5Ba`5D = ftell(infd`5B0`5D); X`09`09`09getline(infd`5B0`5D, text); X`09`09`09continue; X`09`09`7D X`09`09while (b < match`5Ba`5D) `7B X`09`09`09/* Skip over unique lines in B */ X`09`09`09newseek`5Bb`5D = ftell(infd`5B1`5D); X`09`09`09getline(infd`5B1`5D, textb); X`09`09`09b++; X`09`09`7D X X`09`09/* X`09`09 * Compare the two, supposedly matching, lines. Unless we are going X`09`09 * to print these lines, don't bother to remember where they are. We X`09`09 * only print matching lines if a context diff is happening, or if a X`09`09 * jackpot occurs.`20 X`09`09 */ X`09`09if (cflag) `7B X`09`09`09oldseek`5Ba`5D = ftell(infd`5B0`5D); X`09`09`09newseek`5Bb`5D = ftell(infd`5B1`5D); X`09`09`7D X`09`09getline(infd`5B0`5D, text); X`09`09getline(infd`5B1`5D, textb); X`09`09if (!streq(text, textb)) `7B X`09`09`09fprintf(stderr, "Spurious match:\n"); X`09`09`09fprintf(stderr, "line %d in %s, \"%s\"\n", X`09`09`09`09`09a, fileAname, text); X`09`09`09fprintf(stderr, "line %d in %s, \"%s\"\n", X`09`09`09`09`09b, fileBname, textb); X`09`09`09match`5Ba`5D = 0; X`09`09`09jackpot++; X`09`09`7D X`09`09b++; X`09`7D X`09for (; b <= lenB; b++) `7B X`09`09newseek`5Bb`5D = ftell(infd`5B1`5D); X`09`09getline(infd`5B1`5D, textb); X`09`7D X/* X * The logical converse to the code up above, for NON-VMS systems, to X * store away an fseek() pointer at the beginning of the file. For VMS, X * we need one at EOF... X */ X X#ifdef VMS X`09oldseek`5BlenA`5D = ftell(infd`5B0`5D); X`09getline(infd`5B0`5D, text);`09`09/* Will hit EOF... */ X`09newseek`5BlenB`5D = ftell(infd`5B1`5D); X`09getline(infd`5B1`5D, textb);`09/* Will hit EOF... */ X#endif /* vms */ X X`09return (jackpot); X`7D X X Xoutput(fileAname, fileBname) X`09char *fileAname, *fileBname; X`7B X`09register int astart; X`09register int aend = 0; X`09int bstart; X`09register int bend; X X`09rewind(infd`5B0`5D); X`09rewind(infd`5B1`5D); X`09match`5B0`5D = 0; X`09match`5BlenA + 1`5D = lenB + 1; X`09if (!eflag) `7B X`09`09if (cflag) `7B X X`09`09`09/* X`09`09`09 * Should include ctime style dates after the file names, but X`09`09`09 * this would be non-trivial on OSK. Perhaps there should be a X`09`09`09 * special case for stdin.`20 X`09`09`09 */ X`09`09`09printf("*** %s\n--- %s\n", fileAname, fileBname); X`09`09`7D X X`09`09/* X`09`09 * Normal printout`20 X`09`09 */ X`09`09for (astart = 1; astart <= lenA; astart = aend + 1) `7B X X`09`09`09/* X`09`09`09 * New subsequence, skip over matching stuff`20 X`09`09`09 */ X`09`09`09while (astart <= lenA X`09`09`09`09 && match`5Bastart`5D == (match`5Bastart - 1`5D + 1)) X`09`09`09`09astart++; X X`09`09`09/* X`09`09`09 * Found a difference, setup range and print it`20 X`09`09`09 */ X`09`09`09bstart = match`5Bastart - 1`5D + 1; X`09`09`09aend = astart - 1; X`09`09`09while (aend < lenA && match`5Baend + 1`5D == 0) X`09`09`09`09aend++; X`09`09`09bend = match`5Baend + 1`5D - 1; X`09`09`09match`5Baend`5D = bend; X`09`09`09change(astart, aend, bstart, bend); X`09`09`7D X`09`7D else `7B X X`09`09/* X`09`09 * Edit script output -- differences are output "backwards" for the X`09`09 * benefit of a line-oriented editor.`20 X`09`09 */ X`09`09for (aend = lenA; aend >= 1; aend = astart - 1) `7B X`09`09`09while (aend >= 1 X`09`09`09`09 && match`5Baend`5D == (match`5Baend + 1`5D - 1) X`09`09`09`09 && match`5Baend`5D != 0) X`09`09`09`09aend--; X`09`09`09bend = match`5Baend + 1`5D - 1; X`09`09`09astart = aend + 1; X`09`09`09while (astart > 1 && match`5Bastart - 1`5D == 0) X`09`09`09`09astart--; X`09`09`09bstart = match`5Bastart - 1`5D + 1; X`09`09`09match`5Bastart`5D = bstart; X`09`09`09change(astart, aend, bstart, bend); X`09`09`7D X`09`7D X`09if (lenA == 0) X`09`09change(1, 0, 1, lenB); X`7D X X X/* X * Output a change entry: fileA`5Bastart..aend`5D changed to fileB`5Bbstart. V.bend`5D X */ X Xchange(astart, aend, bstart, bend) X`09int astart; X`09int aend; X`09int bstart; X`09int bend; X`7B X`09char c; X X`09/* X`09 * This catches a "dummy" last entry`20 X`09 */ X`09if (astart > aend && bstart > bend) X`09`09return; X`09c = (astart > aend) ? 'a' : (bstart > bend) ? 'd' : 'c'; X`09if (cflag) X`09`09fputs("**************\n*** ", stdout); X X`09if (c == 'a' && !cflag) X`09`09range(astart - 1, astart - 1, 0);`09`09/* Addition: just print one X`09`09`09`09`09`09`09`09`09`09`09`09 * odd # */ X`09else X`09`09range(astart, aend, 0);`09/* Print both, if different */ X`09if (!cflag) `7B X`09`09putchar(c); X`09`09if (!eflag) `7B X`09`09`09if (c == 'd') X`09`09`09`09range(bstart - 1, bstart - 1, 1);`09`09/* Deletion: just print X`09`09`09`09`09`09`09`09`09`09`09`09`09`09 * one odd # */ X`09`09`09else X`09`09`09`09range(bstart, bend, 1);`09/* Print both, if different */ X`09`09`7D X`09`7D X`09putchar('\n'); X`09if ((!eflag && c != 'a') `7C`7C cflag) `7B X`09`09fetch(oldseek, astart, aend, lenA, infd`5B0`5D, X`09`09`09 cflag ? (c == 'd' ? "- " : "! ") : "< "); X`09`09if (cflag) `7B X`09`09`09fputs("--- ", stdout); X`09`09`09range(bstart, bend, 1); X`09`09`09fputs(" -----\n", stdout); X`09`09`7D else if (astart <= aend && bstart <= bend) X`09`09`09printf("---\n"); X`09`7D X`09fetch(newseek, bstart, bend, lenB, infd`5B1`5D, X`09`09 cflag ? (c == 'a' ? "+ " : "! ") : (eflag ? "" : "> ")); X`09if (eflag && bstart <= bend) X`09`09printf(".\n"); X`7D X X X/* X * Print a range X */ X Xrange(from, to, w) X`09int from; X`09int to; X`09int w; X`7B X`09if (cflag) `7B X`09`09if ((from -= cflag) <= 0) X`09`09`09from = 1; X`09`09if ((to += cflag) > len`5Bw`5D) X`09`09`09to = len`5Bw`5D; X`09`7D X`09if (to > from) `7B X`09`09printf("%d,%d", from, to); X`09`7D else if (to < from) `7B X`09`09printf("%d,%d", to, from); X`09`7D else `7B X`09`09printf("%d", from); X`09`7D X`7D X X X/* X * Print the appropriate text X */ X Xfetch(seekvec, start, end, trueend, fd, pfx) X`09long *seekvec; X`09register int start; X`09register int end; X`09int trueend; X`09FILE *fd; X`09char *pfx; X`7B X`09register int i; X`09register int first; X`09register int last; X X`09if (cflag) `7B X`09`09if ((first = start - cflag) <= 0) X`09`09`09first = 1; X`09`09if ((last = end + cflag) > trueend) X`09`09`09last = trueend; X`09`7D else `7B X`09`09first = start; X`09`09last = end; X`09`7D X`09if (fseek(fd, seekvec`5Bfirst`5D, 0) != 0) `7B X`09`09printf("?Can't read line %d at %08lx (hex) in file%c\n", X`09`09`09 start, seekvec`5Bfirst`5D, X`09`09`09 (fd == infd`5B0`5D) ? 'A' : 'B'); X`09`7D else `7B X`09`09for (i = first; i <= last; i++) `7B X`09`09`09if (fgetss(text, sizeof text, fd) == NULL) `7B X`09`09`09`09printf("** Unexpected end of file\n"); X`09`09`09`09break; X`09`09`09`7D X#ifdef DEBUG X`09`09`09printf("%5d: %s%s\n", i, pfx, text); X#else /* !DEBUG */ X`09`09`09fputs((cflag && (i < start `7C`7C i > end)) ? " " : pfx, stdout); X`09`09`09fputs(text, stdout); X`09`09`09putchar('\n'); X#endif /* DEBUG */ X`09`09`7D X`09`7D X`7D X X X/* X * Input routine, read one line to buffer`5B`5D, return TRUE on eof, else FA VLSE. X * The terminating newline is always removed. If "-b" was given, trailing X * whitespace (blanks and tabs) are removed and strings of blanks and X * tabs are replaced by a single blank. Getline() does all hacking for X * redirected input files. X */ X Xint Xgetline(fd, buffer) X`09FILE *fd; X`09char *buffer; X`7B X`09register char *top; X`09register char *fromp; X`09register char c; X X`09if (fgetss(buffer, sizeof text, fd) == NULL) `7B X`09`09*buffer = EOS; X`09`09return (TRUE); X`09`7D X`09if (fd == stdin) X`09`09fputss(buffer, tempfd); X`09if (bflag `7C`7C iflag) `7B X`09`09top = buffer; X`09`09fromp = buffer; X`09`09while ((c = *fromp++) != EOS) `7B X`09`09`09if (bflag && (c == ' ' `7C`7C c == '\t')) `7B X`09`09`09`09c = ' '; X`09`09`09`09while (*fromp == ' ' `7C`7C *fromp == '\t') X`09`09`09`09`09fromp++; X`09`09`09`7D X`09`09`09if (iflag) X`09`09`09`09c = tolower(c); X`09`09`09*top++ = c; X`09`09`7D X`09`09if (bflag && top`5B-1`5D == ' ') X`09`09`09top--; X`09`09*top = EOS; X`09`7D X`09return (FALSE); X`7D X X Xstatic unsigned short crc16a`5B`5D = `7B X`09`09`09`09`09`09`09`09 0000000, 0140301, 0140601, 0000500, X`09`09`09`09`09`09`09`09 0141401, 0001700, 0001200, 0141101, X`09`09`09`09`09`09`09`09 0143001, 0003300, 0003600, 0143501, X`09`09`09`09`09`09`09`09 0002400, 0142701, 0142201, 0002100, X`7D; X Xstatic unsigned short crc16b`5B`5D = `7B X`09`09`09`09`09`09`09`09 0000000, 0146001, 0154001, 0012000, X`09`09`09`09`09`09`09`09 0170001, 0036000, 0024000, 0162001, X`09`09`09`09`09`09`09`09 0120001, 0066000, 0074000, 0132001, X`09`09`09`09`09`09`09`09 0050000, 0116001, 0104001, 0043000, X`7D; X X X/* X * Return the CRC16 hash code for the buffer X * Algorithm from Stu Wecker (Digital memo 130-959-002-00). X */ X Xunsigned short Xhash(buffer) X`09char *buffer; X`7B X`09register unsigned short crc; X`09register char *tp; X`09register short temp; X X`09crc = 0; X`09for (tp = buffer; *tp != EOS;) `7B X`09`09temp = *tp++ `5E crc;`09`09/* XOR crc with new char */ X`09`09crc = (crc >> 8) X`09`09`09`5E crc16a`5B(temp & 0017)`5D X`09`09`09`5E crc16b`5B(temp & 0360) >> 4`5D; X`09`7D X#ifdef DEBUG_ALL X`09printf("%06o: %s\n", (crc == 0) ? 1 : crc, buffer); X#endif /* DEBUG_ALL */ X`09return ((crc == 0) ? (unsigned short) 1 : crc); X`7D X X X#ifdef VMS Xopendir(which, arg, okfd) X`09int which;`09`09/* Which file to open (0 or 1) `09 */ X`09char **arg;`09`09/* File name argument, &argv`5Bwhich`5D */ X`09FILE *okfd;`09`09/* File name (already open) `09 */ X`7B X`09char defaultname`5B512`5D; X`09char *c; X X`09fgetname(okfd, text); X`09if (c = strrchr(text, ';')) X`09`09*c = '\0'; X`09for (c=text; *c; ++c) X`09`09if (isupper(*c)) X`09`09`09*c = _tolower(*c); X`09sprintf(defaultname, "dna=%s", text); X X`09if ((infd`5Bwhich`5D = fopen(*arg, "r", defaultname, "mbc=64", "mbf=2")) V == NULL) X`09`09cant(*arg, "constructed input", 1); X`09fgetname(infd`5Bwhich`5D, text); X`09*arg = malloc(strlen(text)+1); X`09strcpy(*arg, text); X`7D X Xprevious_version(file) X`09char *file; X`7B X`09FILE *f; X`09static char`09name`5B256`5D; X`09char `09`09*p; X`09int`09`09version; X X`09if (NULL == (f = fopen(file, "r"))) X`09`09return(NULL); X`09fgetname(f, name); X`09fclose(f); X`09p = strrchr(name, ';'); X`09version = strtol(p+1, NULL, 0); X`09while (--version) `7B X`09`09sprintf(p+1, "%d", version); X`09`09if (f = fopen(name, "r")) `7B X`09`09`09fclose(f); X`09`09`09return(name); X`09`09`7D X`09`7D X`09return(NULL); X`7D`09 X X/* Amiga C doesn't have all these extensions for directory... */ X#endif /* vms */ X X X/* X * Allocate or crash. X */ X Xchar * Xmyalloc(amount, why) X`09unsigned amount; X`09char *why; X`7B X`09register char *pointer; X X#ifdef OSK X`09amount += sizeof(int); X#endif /* OSK */ X`09if ((pointer = malloc((unsigned) amount)) == NULL) X`09`09noroom(why); X#ifdef OSK X`09*((int *) pointer) = amount; X`09pointer += sizeof(int); X#ifdef DEBUG X`09fprintf(stderr, "Myalloc: %d at %06o\n", amount, pointer); X#endif /* DEBUG */ X#endif /* OSK */ X#ifdef`09AMIGA X`09savsiz = amount; X`09savptr = pointer; X#endif /* AMIGA */ X X`09return (pointer); X`7D X X X/* X * Reallocate pointer, compacting storage X * X * The "compacting storage" part is probably not relevant any more. X * There used to be horrid code here that malloc'd one byte and freed X * it at magic times, to cause garbage collection of the freespace X * or something. It's safely gone now, you didn't have to see it. X *`09-- John Gilmore, Nebula Consultants, Sept 26, 1986 X */ X Xchar * Xcompact(pointer, new_amount, why) X`09char *pointer; X`09unsigned new_amount; X`09char *why; X`7B X`09register char *new_pointer; X X#ifndef AMIGA X#ifndef OSK X#ifdef TURBO X`09extern void *realloc(); X#else /* !TURBO */ X`09extern char *realloc(); X#endif /* TURBO */ X X`09if ((new_pointer = realloc(pointer, (unsigned) new_amount)) == NULL) `7B X`09`09noroom(why); X`09`7D X#else /* OSK */ X`09register int old_amount; X`09new_amount += sizeof(int); X`09if ((new_pointer = malloc(new_amount)) == NULL) X`09`09noroom(why); X`09*(int *) new_pointer = new_amount; X`09new_pointer += sizeof(int); X`09old_amount = *(((int *) pointer) - 1); X`09/* _strass is like bcopy with the first two arguments reversted */ X`09_strass(new_pointer, pointer, (new_amount <= old_amount ? X`09`09`09`09`09`09`09`09 new_amount : old_amount) - sizeof(int)); X#ifdef DEBUG X`09fprintf(stderr, "compact %d to %d from %06o to %06o\n", X`09`09`09old_amount, new_amount, pointer, new_pointer); X#endif /* DEBUG */ X`09free(pointer - sizeof(int)); X#endif /* OSK */ X#else /* AMIGA */ X X`09/* X`09 * This routine is heavily dependent on C storage allocator hacks For X`09 * Amiga, we can't rely on storage being left alone "up to" the boundary X`09 * of allocation as in VMS or RSX. Therefore we have to be different here X`09 * and allocate a new larger segment, then free the old one. Messy but X`09 * hopefully it will work.`20 X`09 */ X`09extern char *malloc(); X X`09/* No realloc(). Do a malloc and copy it. */ X`09if ((new_pointer = malloc((unsigned) new_amount)) == NULL) `7B X`09`09noroom(why); X`09`7D X /* This MUST assume the program calls compact using the old pointer as the X last call of malloc... Reason is that RSX version is really simpleminded * V/ X`09cpysiz = savsiz; X /* Complain if deallocate area not same as last allocate area */ X`09if (savptr != pointer) X`09`09bogus(why); X`09wrk2 = new_pointer; X`09for (wrk = pointer; cpysiz > 0; cpysiz--) `7B X /* copy data to new area */ X`09`09*wrk2++ = *wrk++; X`09`7D X /* when done, free old memory area. */ X`09free(pointer); X#endif /* AMIGA */ X X#ifndef OSK X#ifdef DEBUG X`09if (new_pointer != pointer) `7B X`09`09fprintf(stderr, "moved from %06o to %06o\n", X`09`09`09`09pointer, new_pointer); X`09`7D X/* rdump(new_pointer, why); X*/ X#endif /* DEBUG */ X#endif /* OSK */ X`09return (new_pointer); X`7D X X Xnoroom(why) X`09char *why; X`7B X`09fprintf(stderr, "?DIFF-F-out of room when %s\n", why); X`09exit(IO_ERROR); X`7D X X X#ifdef`09AMIGA Xbogus(why) X`09char *why; X`7B X`09fprintf(stderr, "?DIFF-F-invalid compaction when %s\n", why); X`09exit(IO_ERROR); X`7D X#endif`09/* AMIGA */ X X X#ifdef DEBUG X/* X * Dump memory block X */ X Xrdump(pointer, why) X`09int *pointer; X`09char *why; X`7B X`09int *last; X`09int count; X X`09last = ((int **) pointer)`5B-1`5D; X`09fprintf(stderr, "dump %s of %06o -> %06o, %d words", X`09`09`09why, pointer, last, last - pointer); X`09last = (int *) (((int) last) & `7E1); X`09for (count = 0; pointer < last; ++count) `7B X`09`09if ((count & 07) == 0) `7B X`09`09`09fprintf(stderr, "\n%06o", pointer); X`09`09`7D X`09`09fprintf(stderr, "\t%06o", *pointer); X`09`09pointer++; X`09`7D X`09fprintf(stderr, "\n"); X`7D X#endif /* DEBUG */ X X X/* X * Can't open file message X */ X Xcant(filename, what, fatalflag) X`09char *filename; X`09char *what; X`09int fatalflag; X`7B X`09fprintf(stderr, "Can't open %s file \"%s\": ", what, filename); X#ifndef`09OSK X`09perror(""); X#else X`09prerr(0, errno); X#endif X`09if (fatalflag) `7B X`09`09exit(fatalflag); X`09`7D X`7D X X X#ifdef DEBUG Xdump(d_linep, d_len, d_which) X`09LINE *d_linep; X`09int`09`09`09`09d_len; X`09int`09`09`09`09d_which; X`7B X`09register int i; X X`09printf("Dump of file%c, %d elements\n", "AB"`5Bd_which`5D, d_len); X`09printf("linep @ %06o\n", d_linep); X`09for (i = 0; i <= d_len; i++) `7B X`09`09printf("%3d %6d %06o\n", i, X`09`09`09 d_linep`5Bi`5D.serial, d_linep`5Bi`5D.hash); X`09`7D X`7D X X X/* X * Dump klist X */ X Xdumpklist(kmax, why) X`09int kmax; X`09char *why; X`7B X`09register int i; X`09register CANDIDATE *cp; X`09register int count; X X`09printf("\nklist`5B0..%d`5D %s, clength = %d\n", kmax, why, clength); X`09for (i = 0; i <= kmax; i++) `7B +-+-+-+-+-+-+-+- END OF PART 2 +-+-+-+-+-+-+-+-