home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume2 / pd-cdiff-patch < prev    next >
Internet Message Format  |  1991-08-07  |  36KB

  1. From: mike2@lcuxa.UUCP
  2. Newsgroups: comp.sources.misc
  3. Subject: v02i059: Patch for pd-cdiff (MS C, probably others)
  4. Message-ID: <7242@ncoast.UUCP>
  5. Date: 18 Feb 88 02:35:18 GMT
  6. Approved: allbery@ncoast.UUCP
  7.  
  8. Comp.sources.misc: Volume 2, Issue 59
  9. Submitted-By: <mike2@lcuxa.UUCP>
  10. Archive-Name: pd-cdiff-patch
  11.  
  12. [Nested shars?  That's a new one.  ++bsa]
  13.  
  14. Neil Dixon uncovered a flaw in the logic of the cdiff program that
  15. was distributed early in January, and which was redistributed with
  16. changes to make it compilable in Turbo C.  I've tested his patch
  17. both on the Unix SysVr2 version and on the PC, and have not found
  18. any errors.  Conversely, the earlier version when compiled in MSC
  19. 4.0 (but, for some reason, not when compiled in TC 1.5) would
  20. sporadically come up with "read" errors.  Since it now works in MSC as
  21. well as TC, I've included the appropriate ifdefs for both compilers,
  22. and have incorporated Neil's patch.  (This was for clarity.  The line
  23. numbers in his patch did not correspond precisely to the line numbers
  24. in the distributed code.)  Both the patch as sent to me and the
  25. revised code are contained below.
  26.  
  27. As before, I did not write this code.  I merely ported it, and of
  28. course make no warranties whatsoever.
  29.  
  30. -------------------------CUT HERE-------------------------------
  31. #!/bin/sh
  32. echo extracting cdiff.pat ...
  33. cat >cdiff.pat <<xzyyz
  34. >From rutgers!mimsy.umd.edu!uunet!mcvax!esatst!neil  Wed Feb  3 10:48:40 1988 
  35. Message-Id: <22649.8802021606@esatst.yc.estec.nl>
  36. To: bellcore!lcuxa!mike2
  37. Subject: patch for PD context diff.
  38. Date: Tue, 02 Feb 88 17:06:29 +0100
  39. From: Neil Dixon <rutgers!mimsy.umd.edu!uunet!mcvax!esatst!neil>
  40.  
  41. When running the PD context diff program recently submitted to comp.sources.misc
  42. we get a 'Can't read ...' error, when not performing a context diff. Here's the
  43. simple patch.
  44.  
  45. Regards,
  46.     Neil Dixon.
  47.         
  48.  
  49. Neil Dixon <neil@yc.estec.nl> UUCP:  ...!mcvax!esatst!neil,
  50. Thermal Control & Life Support Division (YCV) 
  51. European Space Research and Technology Centre (ESTEC),
  52. Noordwijk, The Netherlands.
  53. Phone:    +31 1719 84013
  54.  
  55.  
  56. #! /bin/sh
  57. # This is a shell archive, meaning:
  58. # 1. Remove everything above the #! /bin/sh line.
  59. # 2. Save the resulting text in a file.
  60. # 3. Execute the file with /bin/sh (not csh) to create the files:
  61. #    cdiff.patch
  62. # This archive created: Tue Feb  2 17:05:14 1988
  63. export PATH; PATH=/bin:$PATH
  64. if test -f 'cdiff.patch'
  65. then
  66.     echo shar: will not over-write existing file "'cdiff.patch'"
  67. else
  68. cat << \SHAR_EOF > 'cdiff.patch'
  69. *** cdiff.c
  70. --- cdiff.c.orig
  71. **************
  72. *** 935,942
  73.       }
  74.     }
  75.     putchar('\n');
  76. !   if ((!eflag && c != 'a') || cflag) {
  77. !       fetch(oldseek, astart , aend, lenA, infd[0], 
  78.           cflag ? (c=='d' ? "- " : "! ") : "< ");
  79.       if (cflag) {
  80.         fputs("--- ", stdout);
  81. --- 937,944 -----
  82.       }
  83.     }
  84.     putchar('\n');
  85. !   if (!eflag) {
  86. !       fetch(oldseek, astart, aend, lenA, infd[0], 
  87.           cflag ? (c=='d' ? "- " : "! ") : "< ");
  88.       if (cflag) {
  89.         fputs("--- ", stdout);
  90. SHAR_EOF
  91. fi # end of overwriting check
  92. #    End of shell archive
  93. exit 0
  94. xzyyz
  95. echo extracting cdiff2.c ...
  96. cat >cdiff2.c <<xzyyz
  97. /* Change the following as appropriate */
  98. #undef vms
  99. #undef TURBO           /*  Note:  Use the small model in TC, and
  100.                invoke optimization for speed, registers,
  101.                and jumps.  Even so, it still runs slowly! */
  102. #undef pdp11
  103. #undef OSK
  104. #undef DEBUG
  105. #undef unix 
  106. #define MSC 1          /*  Note: The source compiles properly on
  107.             *  MSC 4.0 (small model).  I have no idea
  108.             *  whether it will work on 5.0          */
  109.  
  110. #ifdef TURBO
  111. #include <alloc.h>
  112. #include <errno.h>
  113. #include <process.h>
  114. #include <stdio.h>
  115. #include <stdlib.h>
  116. #include <string.h>
  117.  
  118. #else
  119. #include <stdio.h>
  120. #include <ctype.h>
  121. #endif
  122.  
  123. #ifdef vms
  124. #include      <ssdef.h>
  125. #include      <stsdef.h>
  126. #define  IO_SUCCESS  (SS$_NORMAL | STS$M_INHIB_MSG)
  127. #define  IO_ERROR  SS$_ABORT
  128. #endif
  129. /*
  130.  * Note: IO_SUCCESS and IO_ERROR are defined in the Decus C stdio.h file
  131.  */
  132. #ifndef  IO_SUCCESS
  133. #define  IO_SUCCESS  0
  134. #endif
  135. #ifndef  IO_ERROR
  136. #define  IO_ERROR  1
  137. #endif
  138.  
  139. #define  EOS      0
  140. #ifdef unix
  141. char temfile[L_tmpnam];
  142. char *tmpnam();
  143. #define  TEMPFILE  (temfile[0]? temfile: (tmpnam(temfile), temfile))
  144. #else
  145. #define  TEMPFILE  "diff.tmp"
  146. #endif
  147. #define  TRUE      1
  148. #define  FALSE      0
  149.  
  150. #ifdef  pdp11
  151. #define  short  int
  152. #endif
  153.  
  154. typedef struct candidate {
  155.   int  b;        /* Line in fileB      */
  156.   int  a;        /* Line in fileA      */
  157.   int  link;        /* Previous candidate      */
  158. } CANDIDATE;
  159.  
  160. typedef struct line {
  161.   unsigned short  hash;      /* Hash value etc.      */
  162.   short      serial;      /* Line number        */
  163. } LINE;
  164.  
  165. LINE  *file[2];        /* Hash/line for total file  */
  166. #define  fileA  file[0]
  167. #define  fileB  file[1]
  168.  
  169. LINE  *sfile[2];        /* Hash/line after prefix  */
  170. #define  sfileA  sfile[0]
  171. #define  sfileB  sfile[1]
  172.  
  173. int  len[2];            /* Actual lines in each file  */
  174. #define  lenA  len[0]
  175. #define  lenB  len[1]
  176.  
  177. int  slen[2];        /* Squished lengths      */
  178. #define  slenA  slen[0]
  179. #define  slenB  slen[1]
  180.  
  181. int  prefix;            /* Identical lines at start  */
  182. int  suffix;            /* Identical lenes at end  */
  183.  
  184. FILE  *infd[2] = { NULL, NULL };  /* Input file identifiers  */
  185. FILE  *tempfd;        /* Temp for input redirection  */
  186.  
  187. extern long  ftell();
  188. extern FILE *fopen();
  189.  
  190. #ifdef TURBO
  191. extern void *malloc();
  192. #else
  193. extern char *malloc();
  194. #endif
  195.  
  196. char    *fgetss();
  197. unsigned short      hash();
  198.  
  199. #ifdef    AMIGA
  200. /* Define these types for Amiga C */
  201. char    *savptr;
  202. int    savsiz;
  203. char    *wrk;
  204. char    *wrk2;
  205. int    cpysiz;
  206. #endif
  207. /*
  208.  * The following vectors overlay the area defined by fileA
  209.  */
  210.  
  211. short      *class;      /* Unsorted line numbers  */
  212. int      *klist;      /* Index of element in clist  */
  213. CANDIDATE  *clist;      /* Storage pool for candidates  */
  214. int      clength = 0;      /* Number of active candidates  */
  215. #define    CSIZE_INC 50    /* How many to allocate each time we have to */
  216. int    csize = CSIZE_INC; /* Current size of storage pool */
  217.  
  218. int      *match;        /* Longest subsequence      */
  219. long      *oldseek;      /* Seek position in file A  */
  220.  
  221. /*
  222.  * The following vectors overlay the area defined by fileB
  223.  */
  224.  
  225. short      *member;      /* Concatenated equiv. classes  */
  226. long      *newseek;      /* Seek position in file B  */
  227. char      *textb;        /* Input from file2 for check  */
  228.  
  229. /*
  230.  * Global variables
  231.  */
  232.  
  233. int      eflag  = FALSE;  /* Edit script requested  */
  234. int      bflag  = FALSE;  /* Blank supress requested  */
  235. int      cflag  = FALSE;  /* Context printout      */
  236. int      iflag  = FALSE;  /* Ignore case requested  */
  237. char      text[257];      /* Input line from file1  */
  238. extern char  *myalloc();      /* Storage allocator      */
  239.  
  240. extern char  *compact();      /* Storage compactor      */
  241.  
  242. #ifdef  DEBUG
  243. #ifndef OSK
  244. #define  TIMING
  245. #endif
  246. #endif
  247. #ifdef  TIMING
  248. extern long  time();
  249. extern char  *$$mend;
  250. long      totaltime;
  251. long      sectiontime;
  252. char      *mstart;
  253. #endif
  254.  
  255. main(argc, argv)
  256. int      argc;
  257. char      **argv;
  258. /*
  259.  * Diff main program
  260.  */
  261. {
  262.   register int  i;
  263.   register char  *ap;
  264.  
  265. #ifdef OSK
  266.   extern int _memmins;
  267.   _memmins = 16 * 1024;            /* tell OSK we will malloc a lot */
  268. #endif
  269. #ifdef  TIMING
  270.   sectiontime = time(&totaltime);
  271. #endif
  272. #ifdef vms
  273.   argc = getredirection(argc,argv);
  274. #endif
  275.   while (argc > 1 && *(ap = argv[1]) == '-' && *++ap != EOS) {
  276.       while (*ap != EOS) {
  277.         switch ((*ap++)) {
  278.         case 'b':
  279.               bflag++;
  280.               break;
  281.  
  282.         case 'c':
  283.           if (*ap > '0' && *ap <= '9') cflag = *ap++ - '0';
  284.           else cflag = 3;
  285.           break;
  286.  
  287.         case 'e':
  288.               eflag++;
  289.               break;
  290.  
  291.         case 'i':
  292.               iflag++;
  293.               break;
  294.  
  295.         default:
  296.               fprintf(stderr,
  297.                   "Warning, bad option '%c'\n",
  298.                   ap[-1]);
  299.               break;
  300.         }
  301.       }
  302.       argc--;
  303.       argv++;
  304.   }
  305.  
  306.   if (argc != 3)
  307.       error("Usage: diff [-options] file1 file2");
  308.   if (cflag && eflag) {
  309.       fprintf(stderr,
  310.         "Warning, -c and -e are incompatible, -c supressed.\n");
  311.       cflag = FALSE;
  312.   }
  313.   argv++;
  314.   for (i = 0; i <= 1; i++) {
  315.       if (argv[i][0] == '-' && argv[i][1] == EOS) {
  316.         infd[i] = stdin;
  317.         if ((tempfd = fopen(TEMPFILE, "w")) == NULL)
  318.             cant(TEMPFILE, "work", 1);
  319.       }
  320.       else {
  321.         infd[i] = fopen(argv[i], "r");
  322.       if (!infd[i]) cant(argv[i], "input", 2);    /* Fatal error */
  323.       }
  324.   }
  325.  
  326.   if (infd[0] == stdin && infd[1] == stdin)
  327.     error("Can't diff two things both on standard input.");
  328.  
  329.   if (infd[0] == NULL && infd[1] == NULL) {
  330.       cant(argv[0], "input", 0);
  331.       cant(argv[1], "input", 1);
  332.   }
  333. #ifdef vms
  334.   else if (infd[1] == NULL)
  335.       opendir(1, &argv[1], infd[0]);
  336.   else if (infd[0] == NULL)
  337.       opendir(0, &argv[0], infd[1]);
  338. #endif
  339.  
  340.  /*
  341.    * Read input, building hash tables.
  342.    */
  343.   input(0);
  344.   input(1);
  345.   squish();
  346. #ifdef  DEBUG
  347.   printf("before sort\n");
  348.   for (i = 1; i <= slenA; i++)
  349.       printf("sfileA[%d] = %6d %06o\n",
  350.         i, sfileA[i].serial, sfileA[i].hash);
  351.   for (i = 1; i <= slenB; i++)
  352.       printf("sfileB[%d] = %6d %06o\n",
  353.         i, sfileB[i].serial, sfileB[i].hash);
  354. #endif
  355.   sort(sfileA, slenA);
  356.   sort(sfileB, slenB);
  357. #ifdef  TIMING
  358.   ptime("input");
  359. #endif
  360. #ifdef  DEBUG
  361.   printf("after sort\n");
  362.   for (i = 1; i <= slenA; i++)
  363.       printf("sfileA[%d] = %6d %06o\n",
  364.         i, sfileA[i].serial, sfileB[i].hash);
  365.   for (i = 1; i <= slenB; i++)
  366.       printf("sfileB[%d] = %6d %06o\n",
  367.         i, sfileB[i].serial, sfileB[i].hash);
  368. #endif
  369.   /*
  370.    * Build equivalence classes.
  371.    */
  372.   member = (short *)fileB;
  373.   equiv();
  374.   member = (short *)compact((char *)member, (slenB + 2) * sizeof (int),
  375.         "squeezing member vector");
  376.   /*
  377.    * Reorder equivalence classes into array class[]
  378.    */
  379.   class = (short *)fileA;
  380.   unsort();
  381.   class = (short *)compact((char *)class, (slenA + 2) * sizeof (int),
  382.         "compacting class vector");
  383. #ifdef  TIMING
  384.   ptime("equiv/unsort");
  385. #endif
  386.   /*
  387.     * Find longest subsequences
  388.    */
  389.   klist = (int *)myalloc((slenA + 2) * sizeof (int), "klist");
  390.   clist = (CANDIDATE *)myalloc(csize * sizeof (CANDIDATE), "clist");
  391.   i = subseq();
  392. #ifndef OSK
  393.   free((char *)member);
  394.   free((char *)class);
  395. #else
  396.   free((char *)member - sizeof(int));
  397.   free((char *)class - sizeof(int));
  398. #endif
  399.   match = (int *)myalloc((lenA + 2) * sizeof (int), "match");
  400.   unravel(klist[i]);
  401. #ifndef OSK
  402.   free((char *)clist);
  403.   free((char *)klist);
  404. #else
  405.   free((char *)clist - sizeof(int));
  406.   free((char *)klist - sizeof(int));
  407. #endif
  408. #ifdef  TIMING
  409.   ptime("subsequence/unravel");
  410. #endif
  411.   /*
  412.    * Check for fortuitous matches and output differences
  413.    */
  414.   oldseek = (long *)myalloc((lenA + 2) * sizeof (* oldseek), "oldseek");
  415.   newseek = (long *)myalloc((lenB + 2) * sizeof (* newseek), "newseek");
  416.   textb = myalloc(sizeof text, "textbuffer");
  417.   if (check(argv[0], argv[1]))
  418.       fprintf(stderr, "Spurious match, output is not optimal\n");
  419. #ifdef  TIMING
  420.   ptime("check");
  421. #endif
  422.   output(argv[0], argv[1]);
  423. #ifdef  TIMING
  424.   ptime("output");
  425.   printf("%ld seconds required\n", sectiontime - totaltime);
  426. #endif
  427.   if (tempfd != NULL) {
  428.       fclose(tempfd);
  429. #ifdef unix
  430.       unlink(TEMPFILE);
  431. #else
  432. #ifdef OSK
  433.     unlink(TEMPFILE);
  434. #else
  435. #ifdef MSC            /*  MSC 4.0 does not understand disjunctive
  436.                     #if's.  */
  437.     unlink(TEMPFILE);
  438. #else
  439.     remove(TEMPFILE);
  440. #endif
  441. #endif
  442. #endif
  443.   }
  444. }
  445.  
  446.  
  447. input(which)
  448. int      which;        /* 0 or 1 to redefine infd[]  */
  449. /*
  450.  * Read the file, building hash table
  451.  */
  452. {
  453.   register LINE      *lentry;
  454.   register int      linect = 0;
  455.   FILE        *fd;
  456. #define    LSIZE_INC 200    /* # of line entries to alloc at once */
  457.   int    lsize = LSIZE_INC;
  458.  
  459.   lentry = (LINE *)myalloc(sizeof(LINE) * (lsize+3), "line");
  460.   fd = infd[which];
  461.   while (!getline(fd, text)) {
  462.     if (++linect >= lsize) {
  463.         lsize += 200;
  464.         lentry = (LINE *)compact((char *)lentry,
  465.           (lsize + 3) * sizeof(LINE),
  466.           "extending line vector");
  467.     }
  468.       lentry[linect].hash = hash(text);
  469.   }
  470.   /*
  471.    * If input was from stdin ("-" command), finish off the temp file.
  472.    */
  473.   if (fd == stdin) {
  474.       fclose(tempfd);
  475.       tempfd = infd[which] = fopen(TEMPFILE, "r");
  476.   }
  477.   /* If we wanted to be stingy with memory, we could realloc lentry down
  478.    * to its exact size (+3 for some odd reason) here.  No need?  */
  479.   len[which] = linect;
  480.   file[which] = lentry;
  481. }
  482.  
  483. squish()
  484. /*
  485.  * Look for initial and trailing sequences that have identical hash values.
  486.  * Don't bother building them into the candidate vector.
  487.  */
  488. {
  489.   register int  i;
  490.   register LINE  *ap;
  491.   register LINE  *bp;
  492.   int      j;
  493.   int      k;
  494.  
  495.   /*
  496.    * prefix -> first line (from start) that doesn't hash identically
  497.    */
  498.   i = 0; ap = &fileA[1]; bp = &fileB[1];
  499.   while (i < lenA && i < lenB && ap->hash == bp->hash) {
  500.       i++; ap++; bp++;
  501.   }
  502.   prefix = i;
  503.   /*
  504.     * suffix -> first line (from end) that doesn't hash identically
  505.    */
  506.   j = lenA - i;
  507.   k = lenB - i;
  508.   ap = &fileA[lenA];
  509.   bp = &fileB[lenB];
  510.   i = 0;
  511.   while (i < j && i < k && ap->hash == bp->hash) {
  512.       i++; ap--; bp--;
  513.   }
  514.   suffix = i;
  515.   /*
  516.    * Tuck the counts away
  517.    */
  518.   for (k = 0; k <= 1; k++) {
  519.       sfile[k] = file[k] + prefix;
  520.       j = slen[k] = len[k] - prefix - suffix;
  521.  
  522.       for (i = 0, ap = sfile[k]; i <= slen[k]; i++, ap++) {
  523.         ap->serial = i;
  524.       }
  525.   }
  526. }
  527.  
  528. sort(vector, vecsize)
  529. LINE      *vector;      /* What to sort        */
  530. int      vecsize;      /* How many to sort      */
  531. /*
  532.  * Sort hash entries
  533.  */
  534. {
  535.   register int  j;
  536.   register LINE  *aim;
  537.   register LINE  *ai;
  538.   int      mid;  
  539.   int      k;
  540.   LINE      work;
  541.  
  542.   for (j = 1; j <= vecsize; j *= 2);
  543.   mid = (j - 1);
  544.   while ((mid /= 2) != 0) {
  545.       k = vecsize - mid;
  546.       for (j = 1; j <= k; j++) {
  547.         for (ai = &vector[j]; ai > vector; ai -= mid) {
  548.             aim = &ai[mid];
  549.             if (aim < ai)
  550.               break;  /* ?? Why ??      */
  551.             if (aim->hash > ai->hash ||
  552.                   aim->hash == ai->hash &&
  553.                   aim->serial > ai->serial)
  554.               break;
  555.             work.hash = ai->hash;
  556.             ai->hash = aim->hash;
  557.             aim->hash = work.hash;
  558.             work.serial = ai->serial;
  559.             ai->serial = aim->serial;
  560.             aim->serial = work.serial;
  561.         }
  562.       }
  563.   }
  564. }
  565.  
  566. equiv()
  567. /*
  568.  * Build equivalence class vector
  569.  */
  570. {
  571.   register LINE  *ap;
  572. #ifdef TURBO
  573.   union {
  574. #else
  575.   register union {
  576. #endif
  577.       LINE    *bp;
  578.       short    *mp;
  579.   } r;
  580.   register int  j;
  581.   LINE    *atop;
  582.  
  583. #ifdef  DEBUG
  584.   printf("equiv entry\n");
  585.   for (j = 1; j <= slenA; j++)
  586.       printf("sfileA[%d] = %6d %06o\n",
  587.             j, sfileA[j].serial, sfileA[j].hash);
  588.   for (j = 1; j <= slenB; j++)
  589.       printf("sfileB[%d] = %6d %06o\n",
  590.             j, sfileB[j].serial, sfileB[j].hash);
  591. #endif
  592.   j = 1;
  593.   ap = &sfileA[1];
  594.   r.bp = &sfileB[1];
  595.   atop = &sfileA[slenA];
  596.   while (ap <= atop && j <= slenB) {
  597.       if (ap->hash < r.bp->hash) {
  598.         ap->hash = 0;
  599.         ap++;
  600.       }
  601.       else if (ap->hash == r.bp->hash) {
  602.         ap->hash = j;
  603.         ap++;
  604.       }
  605.       else {
  606.         r.bp++;
  607.         j++;
  608.       }
  609.   }
  610.   while (ap <= atop) {
  611.       ap->hash = 0;
  612.       ap++;
  613.   }
  614.   sfileB[slenB + 1].hash = 0;
  615. #ifdef  DEBUG
  616.   printf("equiv exit\n");
  617.   for (j = 1; j <= slenA; j++)
  618.       printf("sfileA[%d] = %6d %06o\n",
  619.             j, sfileA[j].serial, sfileA[j].hash);
  620.   for (j = 1; j <= slenB; j++)
  621.       printf("sfileB[%d] = %6d %06o\n",
  622.             j, sfileB[j].serial, sfileB[j].hash);
  623. #endif
  624.   ap = &sfileB[0];
  625.   atop = &sfileB[slenB];
  626.   r.mp = &member[0];
  627.   while (++ap <= atop) {
  628.       r.mp++;
  629.       *r.mp = -(ap->serial);
  630.       while (ap[1].hash == ap->hash) {
  631.         ap++;
  632.         r.mp++;
  633.         *r.mp = ap->serial;
  634.       }
  635.   }
  636.   r.mp[1] = -1;
  637. #ifdef  DEBUG
  638.   for (j = 0; j <= slenB; j++)
  639.       printf("member[%d] = %d\n", j, member[j]);
  640. #endif
  641. }
  642.  
  643. unsort()
  644. /*
  645.  * Build class vector
  646.  */
  647. {
  648.   register int  *temp;
  649.   register int  *tp;
  650. #if TURBO
  651.   union {
  652. #else
  653.   register union {
  654. #endif
  655.       LINE    *ap;
  656.       short    *cp;
  657.   } u;
  658.   LINE    *evec;
  659.   short    *eclass;
  660. #ifdef  DEBUG
  661.   int      i;
  662. #endif
  663.  
  664.   temp = (int *)myalloc((slenA + 1) * sizeof(int), "unsort scratch");
  665.   u.ap = &sfileA[1];
  666.   evec = &sfileA[slenA];
  667.   while (u.ap <= evec) {
  668. #ifdef  DEBUG
  669.       printf("temp[%2d] := %06o\n", u.ap->serial, u.ap->hash);
  670. #endif
  671.       temp[u.ap->serial] = u.ap->hash;
  672.       u.ap++;
  673.   }
  674.   /*
  675.    * Copy into class vector and free work space
  676.    */
  677.   u.cp = &class[1];
  678.   eclass = &class[slenA];
  679.   tp = &temp[1];
  680.   while (u.cp <= eclass)
  681.       *u.cp++ = *tp++;
  682. #ifndef OSK
  683.   free((char *) temp);
  684. #else
  685.   free((char *)temp - sizeof(int));
  686. #endif
  687. #ifdef  DEBUG
  688.   printf("unsort exit\n");
  689.   for (i = 1; i <= slenA; i++)
  690.       printf("class[%d] = %d %06o\n", i, class[i], class[i]);
  691. #endif
  692. }
  693.  
  694. subseq()
  695. /*
  696.  * Generate maximum common subsequence chain in clist[]
  697.  */
  698. {
  699.   int        a;
  700.   register unsigned      ktop;
  701.   register int      b;
  702.   register int      s;
  703.   unsigned        r;
  704.   int        i;
  705.   int        cand;
  706.  
  707.   klist[0] = newcand(0, 0, -1);
  708.   klist[1] = newcand(slenA + 1, slenB + 1, -1);
  709.   ktop = 1;            /* -> guard entry  */
  710.   for (a = 1; a <= slenA; a++) {
  711.       /*
  712.        * For each non-zero element in fileA ...
  713.        */
  714.       if ((i = class[a]) == 0)
  715.         continue;
  716.       cand = klist[0];      /* No candidate now  */
  717.       r = 0;            /* Current r-candidate  */
  718.       do {
  719. #ifdef  DEBUG
  720.         printf("a = %d, i = %d, b = %d\n", a, i, member[i]);
  721. #endif
  722.         /*
  723.          * Perform the merge algorithm
  724.          */
  725.         if ((b = member[i]) < 0)
  726.             b = -b;
  727. #ifdef  DEBUG
  728.         printf("search(%d, %d, %d) -> %d\n",
  729.               r, ktop, b, search(r, ktop, b));
  730. #endif
  731.         if ((s = search(r, ktop, b)) != 0) {
  732.             if (clist[klist[s]].b > b) {
  733.               klist[r] = cand;
  734.               r = s;
  735.               cand = newcand(a, b, klist[s-1]);
  736. #ifdef  DEBUG
  737.               dumpklist(ktop, "klist[s-1]->b > b");
  738. #endif
  739.             }
  740.             if (s >= ktop) {
  741.               klist[ktop + 1] = klist[ktop];
  742.               ktop++;
  743. #ifdef  DEBUG
  744.               klist[r] = cand;
  745.               dumpklist(ktop, "extend");
  746. #endif
  747.               break;
  748.             }
  749.         }
  750.       } while (member[++i] > 0);
  751.     klist[r] = cand;
  752.   }
  753. #ifdef  DEBUG
  754.   printf("last entry = %d\n", ktop - 1);
  755. #endif
  756.   return(ktop - 1);        /* Last entry found  */
  757. }
  758.  
  759. int
  760. newcand(a, b, pred)
  761. int      a;      /* Line in fileA        */
  762. int      b;      /* Line in fileB        */
  763. int      pred;      /* Link to predecessor, index in cand[]  */
  764. {
  765.   register CANDIDATE  *new;
  766.  
  767.   clength++;
  768.   if (++clength >= csize) {
  769.     csize += CSIZE_INC;
  770.     clist = (CANDIDATE *)compact((char *)clist,
  771.           csize * sizeof (CANDIDATE),
  772.           "extending clist");
  773.   }
  774.   new = &clist[clength - 1];
  775.   new->a = a;
  776.   new->b = b;
  777.   new->link = pred;
  778.   return(clength - 1);
  779. }
  780.  
  781. search(low, high, b)
  782. register unsigned  low;
  783. register unsigned  high;
  784. register int  b;
  785. /*
  786.  * Search klist[low..top] (inclusive) for b.  If klist[low]->b >= b,
  787.  * return zero.  Else return s such that klist[s-1]->b < b and
  788.  * klist[s]->b >= b.  Note that the algorithm presupposes the two
  789.  * preset "fence" elements, (0, 0) and (slenA, slenB).
  790.  */
  791. {
  792.   register int      temp;
  793.   register unsigned      mid;
  794.  
  795.   if (clist[klist[low]].b >= b)
  796.       return(0);
  797.   while ((mid = (low + high) / 2) > low) {
  798.       if ((temp = clist[klist[mid]].b) > b)
  799.         high = mid;
  800.       else if (temp < b)
  801.         low = mid;
  802.       else {
  803.         return(mid);
  804.       }
  805.   }
  806.   return(mid + 1);
  807. }
  808.  
  809.  
  810. unravel(k)
  811. register int  k;
  812. {
  813.   register int      i;
  814.   register CANDIDATE  *cp;
  815.   int        first_trailer;
  816.   int        difference;
  817.  
  818.   first_trailer = lenA - suffix;
  819.   difference = lenB - lenA;
  820. #ifdef  DEBUG
  821.   printf("first trailer = %d, difference = %d\n",
  822.       first_trailer, difference);
  823. #endif
  824.   for (i = 0; i <= lenA; i++) {
  825.       match[i] = (i <= prefix) ? i
  826.         : (i > first_trailer) ? i + difference
  827.         : 0;
  828.   }
  829. #ifdef  DEBUG
  830.   printf("unravel\n");
  831. #endif
  832.   while (k != -1) {
  833.       cp = &clist[k];
  834. #ifdef  DEBUG
  835.       if (k < 0 || k >= clength)
  836.         error("Illegal link -> %d", k);
  837.       printf("match[%d] := %d\n", cp->a + prefix, cp->b + prefix);
  838. #endif
  839.       match[cp->a + prefix] = cp->b + prefix;
  840.       k = cp->link;
  841.   }
  842. }
  843.  
  844.  
  845. /*
  846.  * Check for hash matches (jackpots) and collect random access indices to
  847.  * the two files.
  848.  *
  849.  * It should be possible to avoid doing most of the ftell's by noticing
  850.  * that we are not doing a context diff and noticing that if a line
  851.  * compares equal to the other file, we will not ever need to know its
  852.  * file position.  FIXME.
  853.  */
  854. check(fileAname, fileBname)
  855. char      *fileAname;
  856. char      *fileBname;
  857. {
  858.   register int  a;      /* Current line in file A  */
  859.   register int  b;      /* Current line in file B  */
  860.   int      jackpot;
  861.  
  862. /*
  863.  * The VAX C ftell() returns the address of the CURRENT record, not the
  864.  * next one (as in DECUS C or, effectively, other C's).  Hence, the values
  865.  * are "off by one" in the array.  OFFSET compensates for this.
  866.  */
  867. #ifdef vms
  868. #define OFFSET (-1)
  869. #else
  870. #define OFFSET 0
  871. #endif
  872.  
  873.   b = 1;
  874.   rewind(infd[0]);
  875.   rewind(infd[1]);
  876. /*
  877.  * See above; these would be over-written on VMS anyway.
  878.  */
  879. #ifndef vms
  880.   oldseek[0] = ftell(infd[0]);
  881.   newseek[0] = ftell(infd[1]);
  882. #endif
  883.  
  884.   jackpot = 0;
  885. #ifdef  DEBUG
  886.   printf("match vector\n");
  887.   for (a = 0; a <= lenA; a++)
  888.       printf("match[%d] = %d\n", a, match[a]);
  889. #endif
  890.   for (a = 1; a <= lenA; a++) {
  891.       if (match[a] == 0) {
  892.       /* Unique line in A */
  893.         oldseek[a+OFFSET] = ftell(infd[0]);
  894.         getline(infd[0], text);
  895.         continue;  
  896.       }
  897.       while (b < match[a]) {
  898.       /* Skip over unique lines in B */
  899.         newseek[b+OFFSET] = ftell(infd[1]);
  900.         getline(infd[1], textb);
  901.         b++;
  902.       }
  903.  
  904.     /*
  905.      * Compare the two, supposedly matching, lines.
  906.      * Unless we are going to print these lines, don't bother to
  907.      * remember where they are.  We only print matching lines
  908.      * if a context diff is happening, or if a jackpot occurs.
  909.      */
  910.     if (cflag) {
  911.         oldseek[a+OFFSET] = ftell(infd[0]);
  912.         newseek[b+OFFSET] = ftell(infd[1]);
  913.     }
  914.       getline(infd[0], text);
  915.       getline(infd[1], textb);
  916.       if (!streq(text, textb)) {
  917.         fprintf(stderr,  "Spurious match:\n");
  918.         fprintf(stderr, "line %d in %s, \"%s\"\n",
  919.             a, fileAname, text);
  920.         fprintf(stderr, "line %d in %s, \"%s\"\n",
  921.             b, fileBname, textb);
  922.         match[a] = 0;
  923.         jackpot++;
  924.       }
  925.  
  926.       b++;
  927.   }
  928.   for (; b <= lenB; b++) {
  929.       newseek[b+OFFSET] = ftell(infd[1]);
  930.       getline(infd[1], textb);
  931.   }
  932. /*
  933.  * The logical converse to the code up above, for NON-VMS systems, to
  934.  * store away an fseek() pointer at the beginning of the file.  For VMS,
  935.  * we need one at EOF...
  936.  */
  937. #ifdef vms
  938.   oldseek[lenA] = ftell(infd[0]);
  939.   getline(infd[0],text);        /* Will hit EOF...  */
  940.   newseek[lenB] = ftell(infd[1]);
  941.   getline(infd[1],textb);        /* Will hit EOF...  */
  942. #endif
  943.  
  944.   return(jackpot);
  945. }
  946.  
  947. output(fileAname, fileBname)
  948. char *fileAname, *fileBname;
  949. {
  950.   register int  astart;
  951.   register int  aend = 0;
  952.   int      bstart;
  953.   register int  bend;
  954.  
  955.   rewind(infd[0]);
  956.   rewind(infd[1]);
  957.   match[0] = 0;
  958.   match[lenA+1] = lenB + 1;
  959.   if (!eflag) {
  960.     if (cflag) {
  961.         /*
  962.          * Should include ctime style dates after the file names, but
  963.          * this would be non-trivial on OSK.  Perhaps there should be
  964.          * a special case for stdin.
  965.          */
  966.         printf("*** %s\n--- %s\n", fileAname, fileBname);
  967.     }
  968.       /*
  969.        * Normal printout
  970.        */
  971.       for (astart = 1; astart <= lenA; astart = aend + 1) {
  972.         /*
  973.          * New subsequence, skip over matching stuff
  974.          */
  975.         while (astart <= lenA
  976.               && match[astart] == (match[astart - 1] + 1))
  977.             astart++;
  978.         /*
  979.          * Found a difference, setup range and print it
  980.          */
  981.         bstart = match[astart - 1] + 1;
  982.         aend = astart - 1;
  983.         while (aend < lenA && match[aend + 1] == 0)
  984.             aend++;
  985.         bend = match[aend + 1] - 1;
  986.         match[aend] = bend;
  987.         change(astart, aend, bstart, bend);
  988.       }
  989.   }
  990.   else {
  991.       /*
  992.        * Edit script output -- differences are output "backwards"
  993.        * for the benefit of a line-oriented editor.
  994.        */
  995.       for (aend = lenA; aend >= 1; aend = astart - 1) {
  996.         while (aend >= 1
  997.               && match[aend] == (match[aend + 1] - 1)
  998.               && match[aend] != 0)
  999.             aend--;
  1000.         bend = match[aend + 1] - 1;
  1001.         astart = aend + 1;
  1002.         while (astart > 1 && match[astart - 1] == 0)
  1003.             astart--;
  1004.         bstart = match[astart - 1] + 1;
  1005.         match[astart] = bstart;
  1006.         change(astart, aend, bstart, bend);
  1007.       }
  1008.   }
  1009.   if (lenA == 0)
  1010.       change(1, 0, 1, lenB);
  1011. }
  1012.  
  1013.  
  1014. /*
  1015.  * Output a change entry: fileA[astart..aend] changed to fileB[bstart..bend]
  1016.  */
  1017. change(astart, aend, bstart, bend)
  1018. int      astart;
  1019. int      aend;
  1020. int      bstart;
  1021. int      bend;
  1022. {
  1023.   char c;
  1024.   /*
  1025.    * This catches a "dummy" last entry
  1026.    */
  1027.   if (astart > aend && bstart > bend)
  1028.       return;
  1029.   c = (astart > aend) ? 'a' : (bstart > bend) ? 'd' : 'c';
  1030.   if (cflag) fputs("**************\n*** ", stdout);
  1031.  
  1032.   if (c == 'a' && !cflag)
  1033.     range(astart-1, astart-1, 0);    /* Addition: just print one odd # */
  1034.   else
  1035.     range(astart, aend, 0);        /* Print both, if different */
  1036.   if (!cflag) {
  1037.     putchar(c);
  1038.     if (!eflag) {
  1039.     if (c == 'd')
  1040.         range(bstart-1, bstart-1, 1); /* Deletion: just print one odd # */
  1041.     else
  1042.         range(bstart, bend, 1);    /* Print both, if different */
  1043.     }
  1044.   }
  1045.   putchar('\n');
  1046.   if ((!eflag && c != 'a') || cflag) {
  1047.       fetch(oldseek, astart, aend, lenA, infd[0], 
  1048.         cflag ? (c=='d' ? "- " : "! ") : "< ");
  1049.     if (cflag) {
  1050.       fputs("--- ", stdout);
  1051.       range(bstart, bend, 1);
  1052.       fputs(" -----\n", stdout);
  1053.     } else if (astart <= aend && bstart <= bend)
  1054.         printf("---\n");
  1055.   }
  1056.   fetch(newseek, bstart, bend, lenB, infd[1], 
  1057.       cflag ? (c=='a' ? "+ " : "! ") : (eflag ? "" : "> "));
  1058.   if (eflag && bstart <= bend)
  1059.       printf(".\n");
  1060. }
  1061.  
  1062.  
  1063. range(from, to, w)
  1064. int      from;
  1065. int      to;
  1066. int    w;
  1067. /*
  1068.  * Print a range
  1069.  */
  1070. {
  1071.   if (cflag) {
  1072.     if((from -= cflag) <= 0) from = 1;
  1073.     if((to += cflag) > len[w]) to = len[w];
  1074.   }
  1075.   if (to > from) {
  1076.     printf("%d,%d", from, to);
  1077.   } else if (to < from) {
  1078.     printf("%d,%d", to, from);
  1079.   } else {
  1080.     printf("%d", from);
  1081.   }
  1082. }
  1083.  
  1084.  
  1085. fetch(seekvec, start, end, trueend, fd, pfx)
  1086. long      *seekvec;
  1087. register int  start;
  1088. register int  end;
  1089. int      trueend;
  1090. FILE      *fd;
  1091. char      *pfx;
  1092. /*
  1093.  * Print the appropriate text
  1094.  */
  1095. {
  1096.   register int  i;
  1097.   register int    first;
  1098.   register int    last;
  1099.  
  1100.   if (cflag) {
  1101.     if((first = start - cflag) <= 0) first = 1;
  1102.     if((last = end + cflag) > trueend) last = trueend;
  1103.   } else {
  1104.     first = start;
  1105.     last = end;
  1106.   }
  1107.   if (fseek(fd, seekvec[first], 0) != 0) {
  1108.       printf("?Can't read line %d at %08lx (hex) in file%c\n",
  1109.         start, seekvec[first],
  1110.         (fd == infd[0]) ? 'A' : 'B');
  1111.   }
  1112.   else {
  1113.       for (i = first; i <= last; i++) {
  1114.         if (fgetss(text, sizeof text, fd) == NULL) {
  1115.             printf("** Unexpected end of file\n");
  1116.             break;
  1117.         }
  1118. #ifdef DEBUG
  1119.         printf("%5d: %s%s\n", i, pfx, text);
  1120. #else
  1121.         fputs((cflag && (i<start || i>end)) ? "  " : pfx, stdout);
  1122.         fputs(text, stdout);
  1123.       putchar('\n');
  1124. #endif
  1125.       }
  1126.   }  
  1127. }
  1128.  
  1129.  
  1130. /*
  1131.  * Input routine, read one line to buffer[], return TRUE on eof, else FALSE.
  1132.  * The terminating newline is always removed.  If "-b" was given, trailing
  1133.  * whitespace (blanks and tabs) are removed and strings of blanks and
  1134.  * tabs are replaced by a single blank.  Getline() does all hacking for
  1135.  * redirected input files.
  1136.  */
  1137. int
  1138. getline(fd, buffer)
  1139. FILE      *fd;
  1140. char      *buffer;
  1141. {
  1142.   register char  *top;
  1143.   register char  *fromp;
  1144.   register char  c;
  1145.  
  1146.   if (fgetss(buffer, sizeof text, fd) == NULL) {
  1147.       *buffer = EOS;
  1148.       return(TRUE);
  1149.   }
  1150.   if (fd == stdin)
  1151.       fputss(buffer, tempfd);
  1152.   if (bflag || iflag) {
  1153.       top = buffer;
  1154.       fromp = buffer;
  1155.       while ((c = *fromp++) != EOS) {
  1156.         if (bflag && (c == ' ' || c == '\t')) {
  1157.             c = ' ';
  1158.             while (*fromp == ' ' || *fromp == '\t')
  1159.               fromp++;
  1160.         }
  1161.         if (iflag)
  1162.             c = tolower(c);
  1163.         *top++ = c;
  1164.       }
  1165.       if (bflag && top[-1] == ' ')
  1166.         top--;
  1167.       *top = EOS;
  1168.   }
  1169.   return(FALSE);
  1170. }
  1171. static unsigned short crc16a[] = {
  1172.   0000000,  0140301,  0140601,  0000500,
  1173.   0141401,  0001700,  0001200,  0141101,
  1174.   0143001,  0003300,  0003600,  0143501,
  1175.   0002400,  0142701,  0142201,  0002100,  
  1176. };
  1177. static unsigned short crc16b[] = {
  1178.   0000000,  0146001,  0154001,  0012000,
  1179.   0170001,  0036000,  0024000,  0162001,
  1180.   0120001,  0066000,  0074000,  0132001,
  1181.   0050000,  0116001,  0104001,  0043000,
  1182. };
  1183.  
  1184. unsigned short
  1185. hash(buffer)
  1186. char      *buffer;
  1187. /*
  1188.  * Return the CRC16 hash code for the buffer
  1189.  * Algorithm from Stu Wecker (Digital memo 130-959-002-00).
  1190.  */
  1191. {
  1192.   register unsigned short  crc;
  1193.   register char      *tp;
  1194.   register short       temp;
  1195.  
  1196.   crc = 0;
  1197.   for (tp = buffer; *tp != EOS;) {
  1198.       temp = *tp++ ^ crc;  /* XOR crc with new char  */
  1199.       crc = (crc >> 8)
  1200.         ^ crc16a[(temp & 0017)]
  1201.         ^ crc16b[(temp & 0360) >> 4];
  1202.   }
  1203. #ifdef  DEBUG_ALL
  1204.   printf("%06o: %s\n", (crc == 0) ? 1 : crc, buffer);
  1205. #endif
  1206.   return((crc == 0) ? (unsigned short) 1 : crc);
  1207. }      
  1208.  
  1209.  
  1210. #ifdef vms
  1211. opendir(which, arg, okfd)
  1212. int      which;      /* Which file to open (0 or 1)      */
  1213. char      **arg;      /* File name argument, &argv[which]  */
  1214. FILE      *okfd;      /* File name (already open)      */
  1215. {
  1216.   register char      *tp;
  1217.   register int      c;
  1218.   register char      *newname;
  1219.  
  1220.   fgetname(okfd, text);
  1221.   /*
  1222.    * Skip over device name
  1223.    */
  1224.   for (tp = text; (c = *tp) && c != ':'; tp++);
  1225.   if (c)  tp++;
  1226.   else  tp = text;
  1227.   /*
  1228.    * Skip over [UIC] or [PPN] if present
  1229.    */
  1230.   if (*tp == '[' || *tp == '(') {
  1231.       while ((c = *tp++) && c != ']' && c != ')');
  1232.       if (c == 0) {
  1233.         fprintf(stderr, "?Bug: bad file name \"%s\"\n",
  1234.               text);
  1235.         tp--;
  1236.       }
  1237.   }
  1238.   strcpy(text, tp);
  1239.   /*
  1240.    * Don't include version
  1241.    */
  1242.   for (tp = text; (c = *tp) && c != ';'; tp++);
  1243.   *tp = 0;
  1244.   /*
  1245.    * Now, text has the file name, tp - text, its length,
  1246.    * and *arg the (possible) directory name.  Create a new
  1247.    * file name for opening.
  1248.    */
  1249. #ifndef    OSK
  1250.   if ((newname = malloc(tp - text + strlen(*arg) + 1)) == NULL)
  1251.       error("Out of space at start");
  1252. #ifdef    AMIGA
  1253.     savsiz = tp - text + strlen(*arg) + 1;
  1254.     savptr = newname;
  1255. #endif
  1256. #else
  1257.   newname = myalloc(tp - text + strlen(*arg) + 1, "Out of space at start");
  1258. #endif
  1259.   concat(newname, *arg, text, NULL);
  1260.   if ((infd[which] = fopen(newname, "r")) == NULL)
  1261.       cant(*arg, "constructed input", 1);
  1262.   else
  1263.       *arg = newname;
  1264. }
  1265. /* Amiga C doesn't have all these extensions for directory... */
  1266. #endif
  1267.  
  1268. char *
  1269. myalloc(amount, why)
  1270. int      amount;
  1271. char      *why;
  1272. /*
  1273.  * Allocate or crash.
  1274.  */
  1275. {
  1276.   register char  *pointer;
  1277.  
  1278. #ifdef OSK
  1279.   amount += sizeof(int);
  1280. #endif
  1281.   if ((pointer = malloc((unsigned) amount)) == NULL)
  1282.       noroom(why);
  1283. #ifdef OSK
  1284.   *((int *)pointer) = amount;
  1285.   pointer += sizeof(int);
  1286. #ifdef DEBUG
  1287.   fprintf(stderr, "Myalloc: %d at %06o\n", amount, pointer);
  1288. #endif
  1289. #endif
  1290. #ifdef    AMIGA
  1291.    savsiz =  amount;
  1292.    savptr = pointer;
  1293. #endif
  1294.  
  1295.   return (pointer);
  1296. }
  1297.  
  1298.  
  1299. /*
  1300.  * Reallocate pointer, compacting storage
  1301.  *
  1302.  * The "compacting storage" part is probably not relevant any more.
  1303.  * There used to be horrid code here that malloc'd one byte and freed
  1304.  * it at magic times, to cause garbage collection of the freespace
  1305.  * or something.  It's safely gone now, you didn't have to see it.
  1306.  *    -- John Gilmore, Nebula Consultants, Sept 26, 1986
  1307.  */
  1308. char *
  1309. compact(pointer, new_amount, why)
  1310. char      *pointer;
  1311. int      new_amount;
  1312. char      *why;
  1313. {
  1314.   register char *new_pointer;
  1315.  
  1316. #ifndef AMIGA
  1317. #ifndef OSK
  1318. #ifdef TURBO
  1319.   extern void *realloc();
  1320. #else
  1321.   extern char *realloc();
  1322. #endif
  1323.  
  1324.   if ((new_pointer =  realloc(pointer, (unsigned) new_amount)) == NULL){
  1325.       noroom(why);
  1326.   }
  1327. #else
  1328.   register int old_amount;
  1329.   new_amount += sizeof(int);
  1330.   if((new_pointer = malloc(new_amount)) == NULL) noroom(why);
  1331.   *(int *)new_pointer = new_amount;
  1332.   new_pointer += sizeof(int);
  1333.   old_amount = *(((int *)pointer)-1);
  1334.   /* _strass is like bcopy with the first two arguments reversted */
  1335.   _strass(new_pointer, pointer, (new_amount <= old_amount ?
  1336.       new_amount : old_amount) - sizeof(int));
  1337. #ifdef DEBUG
  1338.   fprintf(stderr, "compact %d to %d from %06o to %06o\n", 
  1339.     old_amount, new_amount, pointer, new_pointer);
  1340. #endif
  1341.   free(pointer - sizeof(int));
  1342. #endif
  1343. #else
  1344.   /*
  1345.    * This routine is heavily dependent on C storage allocator hacks
  1346.    * For Amiga, we can't rely on storage being left alone "up to"
  1347.    * the boundary of allocation as in VMS or RSX. Therefore we have
  1348.    * to be different here and allocate a new larger segment, then
  1349.    * free the old one. Messy but hopefully it will work.
  1350.    */
  1351.   extern char  *malloc();
  1352.  
  1353.   /* No realloc().  Do a malloc and copy it.  */
  1354.   if ((new_pointer = malloc((unsigned) new_amount)) == NULL){
  1355.       noroom(why);
  1356.   }
  1357. /* This MUST assume the program calls compact using the old pointer as the
  1358.   last call of malloc... Reason is that RSX version is really simpleminded */
  1359.    cpysiz=savsiz;
  1360. /* Complain if deallocate area not same as last allocate area */
  1361.  if (savptr != pointer) bogus(why);
  1362.    wrk2=new_pointer;
  1363.    for (wrk=pointer;cpysiz > 0;cpysiz--){
  1364. /* copy data to new area */
  1365.      *wrk2++ = *wrk++;
  1366.      }
  1367. /* when done, free old memory area. */
  1368.    free(pointer);
  1369. #endif
  1370.  
  1371. #ifndef OSK
  1372. #ifdef  DEBUG
  1373.   if (new_pointer != pointer) {
  1374.       fprintf(stderr, "moved from %06o to %06o\n",
  1375.         pointer, new_pointer);
  1376.   }
  1377. /*  rdump(new_pointer, why);
  1378. */
  1379. #endif
  1380. #endif
  1381.   return (new_pointer);
  1382. }
  1383.  
  1384. noroom(why)
  1385. char      *why;
  1386. {
  1387.   fprintf(stderr, "?DIFF-F-out of room when %s\n", why);
  1388.   exit(IO_ERROR);
  1389. }
  1390.  
  1391. #ifdef    AMIGA
  1392. bogus(why)
  1393. char      *why;
  1394. {
  1395.   fprintf(stderr, "?DIFF-F-invalid compaction when %s\n", why);
  1396.   exit(IO_ERROR);
  1397. }
  1398. #endif
  1399.  
  1400. #ifdef  DEBUG
  1401. rdump(pointer, why)
  1402. int      *pointer;
  1403. char      *why;
  1404. /*
  1405.  * Dump memory block
  1406.  */
  1407. {
  1408.   int  *last;
  1409.   int  count;
  1410.  
  1411.   last = ((int **)pointer)[-1];
  1412.   fprintf(stderr, "dump %s of %06o -> %06o, %d words",
  1413.         why, pointer, last, last - pointer);
  1414.   last = (int *)(((int) last) & ~1);
  1415.   for (count = 0; pointer < last; ++count) {
  1416.       if ((count & 07) == 0) {
  1417.         fprintf(stderr, "\n%06o", pointer);
  1418.       }
  1419.       fprintf(stderr, "\t%06o", *pointer);
  1420.       pointer++;
  1421.   }
  1422.   fprintf(stderr, "\n");
  1423. }
  1424. #endif
  1425. cant(filename, what, fatalflag)
  1426. char      *filename;
  1427. char      *what;
  1428. int      fatalflag;
  1429. /*
  1430.  * Can't open file message
  1431.  */
  1432. {
  1433.   fprintf(stderr, "Can't open %s file \"%s\": ", what, filename);
  1434. #ifndef    OSK
  1435.   perror((char *)NULL);
  1436. #else
  1437.   prerr(0, errno);
  1438. #endif
  1439.   if (fatalflag) {
  1440.       exit(fatalflag);
  1441.   }
  1442. }
  1443. #ifdef  DEBUG
  1444. dump(d_linep, d_len, d_which)
  1445. LINE  *d_linep;
  1446. {
  1447.   register int i;
  1448.   
  1449.   printf("Dump of file%c, %d elements\n", "AB"[d_which], d_len);
  1450.   printf("linep @ %06o\n", d_linep);
  1451.   for (i = 0; i <= d_len; i++) {
  1452.       printf("%3d  %6d  %06o\n", i,
  1453.             d_linep[i].serial, d_linep[i].hash);
  1454.   }
  1455. }
  1456.  
  1457. dumpklist(kmax, why)
  1458. int  kmax;
  1459. char  *why;
  1460. /*
  1461.  * Dump klist
  1462.  */
  1463. {
  1464.   register int      i;
  1465.   register CANDIDATE  *cp;
  1466.   register int      count;
  1467.  
  1468.   printf("\nklist[0..%d] %s, clength = %d\n", kmax, why, clength);
  1469.   for (i = 0; i <= kmax; i++) {
  1470.       cp = &clist[klist[i]];
  1471.       printf("%2d %2d", i, klist[i]);
  1472.       if (cp >= &clist[0] && cp < &clist[clength])
  1473.         printf(" (%2d %2d -> %2d)\n", cp->a, cp->b, cp->link);
  1474.       else if (klist[i] == -1)
  1475.         printf(" End of chain\n");
  1476.       else  printf(" illegal klist element\n");
  1477.   }
  1478.   for (i = 0; i <= kmax; i++) {
  1479.       count = -1;
  1480.       for (cp = (CANDIDATE *)klist[i]; cp > &clist[0];
  1481.         cp = (CANDIDATE *)&cp->link) {
  1482.         if (++count >= 6) {
  1483.             printf("\n    ");
  1484.             count = 0;
  1485.         }
  1486.         printf(" (%2d: %2d,%2d -> %d)",
  1487.             cp-clist, cp->a, cp->b, cp->link);
  1488.       }
  1489.       printf("\n");
  1490.   }
  1491.   printf("*\n");
  1492. }
  1493. #endif
  1494. #ifdef  TIMING
  1495. ptime(why)
  1496. char      *why;
  1497. /*
  1498.  * Dump time buffer
  1499.  */
  1500. {
  1501.   long  ttemp;
  1502.  
  1503.   ttemp = time(NULL);
  1504.   printf("%ld seconds for %s\n",
  1505.       ttemp - sectiontime, why);
  1506.   sectiontime = ttemp;
  1507. }
  1508. #endif
  1509.  
  1510. /*
  1511.  *        s t r e q . c
  1512.  */
  1513.  
  1514. /*)LIBRARY
  1515. */
  1516.  
  1517.  
  1518. /* #define  EOS  0
  1519. #define  FALSE  0
  1520. #define  TRUE  1
  1521. */
  1522. int
  1523. streq(s1, s2)
  1524. register char  *s1;
  1525. register char  *s2;
  1526. /*
  1527.  * TRUE if strings are identical
  1528.  */
  1529. {
  1530.   while (*s1++ == *s2) {
  1531.       if (*s2++ == EOS)
  1532.       return (TRUE);
  1533.   }
  1534.   return (FALSE);
  1535. }
  1536. /*
  1537.  *        e r r o r . c
  1538.  */
  1539.  
  1540. /*)LIBRARY
  1541. */
  1542.  
  1543.  
  1544. /* VARARGS */
  1545. error(format, args)
  1546. char      *format;
  1547. /*
  1548.  * Error message before retiring.
  1549.  */
  1550. {
  1551.   fprintf(stderr, format, &args);
  1552.   putc('\n', stderr);
  1553.   _error();
  1554. }
  1555.  
  1556. _error()
  1557. {
  1558.   exit(1);
  1559. }
  1560.  
  1561. /* #include  <stdio.h> */
  1562.   
  1563. fputss(s, iop)
  1564. register char *s;
  1565. register FILE *iop;
  1566. /*
  1567.  * Like fput() except that it puts a newline at the end of the line.
  1568.  */
  1569. {
  1570. #ifndef OSK
  1571. /*
  1572.  * Why wasn't this written like the OSK section?  What's the difference between
  1573.  * fputc and putc other than I've never heard of fputc?
  1574.  */
  1575.   register c;
  1576.  
  1577.   while (c = *s++)
  1578.     fputc(c, iop);
  1579.   fputc('\n', iop);
  1580. #else
  1581.   fputs(s, iop);
  1582.   putc('\n', iop);
  1583. #endif
  1584. }
  1585.  
  1586.  
  1587. /*
  1588.  * Fgetss() is like fgets() except that the terminating newline
  1589.  * is removed.
  1590.  */
  1591. char *fgetss(s, n, iop)
  1592. char *s;
  1593. register FILE *iop;
  1594. {
  1595.   register c;
  1596.   register char *cs;
  1597.  
  1598.   cs = s;
  1599.   /*
  1600.    * The getc in the next line used to be an "fgetc".  Change it back if
  1601.    * getc doesn't work on your system, though that would be odd.
  1602.    */
  1603.   while ((c = getc(iop))>=0 && --n>0) {
  1604.       if (c=='\n')
  1605.         break;
  1606.       *cs++ = c;
  1607.   }
  1608.   if (c<0 && cs==s)
  1609.       return((char *)NULL);
  1610.   *cs = '\0';        /* Overwrite newline as null  */
  1611.   return(s);
  1612. }
  1613. xzyyz
  1614. echo done
  1615. ---
  1616.                 Mike Slomin
  1617.                 bellcore!lcuxa!mike2
  1618.