home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / RCS_SRC.ZIP / RCSDIFF.C < prev    next >
C/C++ Source or Header  |  1991-01-15  |  10KB  |  290 lines

  1. /*
  2.  *                     RCS rcsdiff operation
  3.  */
  4. #ifndef lint
  5. static char rcsid[]=
  6. "$Header: /usr/src/local/bin/rcs/src/RCS/rcsdiff.c,v 4.6 89/05/01 15:12:27 narten Exp $ Purdue CS";
  7. #endif
  8. /*****************************************************************************
  9.  *                       generate difference between RCS revisions
  10.  *****************************************************************************
  11.  */
  12.  
  13. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  14.    Distributed under license by the Free Software Foundation, Inc.
  15.  
  16. This file is part of RCS.
  17.  
  18. RCS is free software; you can redistribute it and/or modify
  19. it under the terms of the GNU General Public License as published by
  20. the Free Software Foundation; either version 1, or (at your option)
  21. any later version.
  22.  
  23. RCS is distributed in the hope that it will be useful,
  24. but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26. GNU General Public License for more details.
  27.  
  28. You should have received a copy of the GNU General Public License
  29. along with RCS; see the file COPYING.  If not, write to
  30. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  31.  
  32. Report problems and direct all questions to:
  33.  
  34.     rcs-bugs@cs.purdue.edu
  35.  
  36. */
  37.  
  38.  
  39.  
  40.  
  41. /* $Log:    rcsdiff.c,v $
  42.  * Revision 4.6  89/05/01  15:12:27  narten
  43.  * changed copyright header to reflect current distribution rules
  44.  * 
  45.  * Revision 4.5  88/11/08  12:01:51  narten
  46.  * changes from  eggert@sm.unisys.com (Paul Eggert)
  47.  * 
  48.  * Revision 4.5  88/08/09  19:12:41  eggert
  49.  * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
  50.  * 
  51.  * Revision 4.4  87/12/18  11:37:46  narten
  52.  * changes Jay Lepreau made in the 4.3 BSD version, to add support for
  53.  * "-i", "-w", and "-t" flags and to permit flags to be bundled together, 
  54.  * merged in.
  55.  * 
  56.  * Revision 4.3  87/10/18  10:31:42  narten
  57.  * Updating version numbers. Changes relative to 1.1 actually
  58.  * relative to 4.1
  59.  * 
  60.  * Revision 1.3  87/09/24  13:59:21  narten
  61.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  62.  * warnings)
  63.  * 
  64.  * Revision 1.2  87/03/27  14:22:15  jenkins
  65.  * Port to suns
  66.  * 
  67.  * Revision 1.1  84/01/23  14:50:18  kcs
  68.  * Initial revision
  69.  * 
  70.  * Revision 4.1  83/05/03  22:13:19  wft
  71.  * Added default branch, option -q, exit status like diff.
  72.  * Added fterror() to replace faterror().
  73.  * 
  74.  * Revision 3.6  83/01/15  17:52:40  wft
  75.  * Expanded mainprogram to handle multiple RCS files.
  76.  *
  77.  * Revision 3.5  83/01/06  09:33:45  wft
  78.  * Fixed passing of -c (context) option to diff.
  79.  *
  80.  * Revision 3.4  82/12/24  15:28:38  wft
  81.  * Added call to catchsig().
  82.  *
  83.  * Revision 3.3  82/12/10  16:08:17  wft
  84.  * Corrected checking of return code from diff; improved error msgs.
  85.  *
  86.  * Revision 3.2  82/12/04  13:20:09  wft
  87.  * replaced getdelta() with gettree(). Changed diagnostics.
  88.  *
  89.  * Revision 3.1  82/11/28  19:25:04  wft
  90.  * Initial revision.
  91.  *
  92.  */
  93. #include <ctype.h>
  94. #include "rcsbase.h"
  95. #define ERRCODE 2                   /*error code for exit status            */
  96. extern char *rindex();
  97. #ifndef lint
  98. static char rcsbaseid[] = RCSBASE;
  99. #endif
  100. static char co[] = CO;
  101.  
  102. extern int    cleanup();            /* cleanup after signals                */
  103. extern char * mktempfile();         /*temporary file name generator         */
  104. extern int    fterror();            /*forward for special fatal error func. */
  105. extern struct hshentry * genrevs(); /*generate delta numbers                */
  106. extern int    nerror;               /*counter for errors                    */
  107. extern int    quietflag;            /*suppresses diagnostics                */
  108. extern FILE * finptr;               /* RCS input file                       */
  109.  
  110. char *RCSfilename;
  111. char *workfilename;
  112. char * temp1file, * temp2file;
  113.  
  114. char bops[10];
  115. char otherops[10];
  116.  
  117. main (argc, argv)
  118. int argc; char **argv;
  119. {
  120.         char * cmdusage;
  121.     char commarg[revlength+3];
  122.         int  revnums;                 /* counter for revision numbers given */
  123.         char * rev1, * rev2;          /* revision numbers from command line */
  124.         char numericrev[revlength];   /* holds expanded revision number     */
  125.         char * xrev1, * xrev2;        /* expanded revision numbers          */
  126.         struct hshentry * gendeltas[hshsize];/*stores deltas to be generated*/
  127.         struct hshentry * target;
  128.     char * boption, * otheroption;
  129.         int  exit_stats;
  130.     int  diffs_found;
  131.     char *argp;
  132.     register c;
  133.  
  134.         catchints();
  135.         otheroption = otherops + 2;
  136.     boption = bops + 2;
  137.         cmdid = "rcsdiff";
  138.     cmdusage = "command format:\n    rcsdiff [-biwt] [-q] [-cefhn] [-rrev1] [-rrev2] file";
  139.     diffs_found=revnums=0;
  140.         while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
  141.         argp = &((*argv)[1]);
  142.         while (c = *argp++) switch (c) {
  143.                 case 'r':
  144.                 if (*argp!='\0') {
  145.                             if (revnums==0) {
  146.                                     rev1= argp; revnums=1;
  147.                             } elif (revnums==1) {
  148.                                     rev2= argp; revnums=2;
  149.                             } else {
  150.                     fterror("too many revision numbers");
  151.                             }
  152.                         } /* do nothing for empty -r */
  153.             argp += strlen(argp);
  154.                         break;
  155.                 case 'b':
  156.                 case 'i':
  157.                 case 'w':
  158.                 case 't':
  159.             if (!rindex(bops + 2, c))
  160.                 *boption++ = c;
  161.             break;
  162.         case 'q':
  163.             quietflag=true;
  164.             break;
  165.                 case 'c':
  166.                 case 'e':
  167.                 case 'f':
  168.                 case 'h':
  169.                 case 'n':
  170.                         if (otheroption == otherops + 2) {
  171.                 *otheroption++ = c;
  172.                 if (c == 'c' && isdigit(*argp)) {
  173.                     while (isdigit(*argp) && otheroption < otherops+sizeof(otherops)-1)
  174.                         *otheroption++ = *argp++;
  175.                     if (*argp)
  176.                         faterror("-c: bad count");
  177.                     argp = "";
  178.                 }
  179.                         } else {
  180.                 fterror("Options c,e,f,h,n are mutually exclusive");
  181.                         }
  182.             break;
  183.                 default:
  184.             fterror("unknown option: %s\n%s", *argv,cmdusage);
  185.                 };
  186.         } /* end of option processing */
  187.  
  188.     if (boption != bops + 2) {
  189.         bops[0] = ' ';
  190.         bops[1] = '-';
  191.         boption = bops;
  192.     }
  193.     if (otheroption != otherops + 2) {
  194.          otherops[0] = ' ';
  195.         otherops[1] = '-';
  196.         otheroption = otherops;
  197.     }
  198.     if (argc<1) fterror("No input file\n%s",cmdusage);
  199.  
  200.         /* now handle all filenames */
  201.         do {
  202.                 finptr=NULL;
  203.  
  204.                 if (pairfilenames(argc,argv,true,false)!=1) continue;
  205.         diagnose("===================================================================");
  206.                 diagnose("RCS file: %s",RCSfilename);
  207.                 if (revnums<2 && !(access(workfilename,4)==0)) {
  208.                         error("Can't open %s",workfilename);
  209.                         continue;
  210.                 }
  211.                 if (!trysema(RCSfilename,false)) continue; /* give up */
  212.  
  213.  
  214.                 gettree(); /* reads in the delta tree */
  215.  
  216.                 if (Head==nil) {
  217.                         error("no revisions present");
  218.                         continue;
  219.                 }
  220.                 if (revnums==0)
  221.                         rev1=Dbranch!=nil?Dbranch->num:Head->num; /* default rev1 */
  222.  
  223.                 if (!expandsym(rev1,numericrev)) continue;
  224.                 if (!(target=genrevs(numericrev,(char *)nil,(char *)nil,(char *)nil,gendeltas))) continue;
  225.                 xrev1=target->num;
  226.  
  227.                 if (revnums==2) {
  228.                         if (!expandsym(rev2,numericrev)) continue;
  229.                         if (!(target=genrevs(numericrev,(char *)nil,(char *)nil,(char *)nil,gendeltas))) continue;
  230.                         xrev2=target->num;
  231.                 }
  232.  
  233.  
  234.                 temp1file=mktempfile("/tmp/",TMPFILE1);
  235.                 diagnose("retrieving revision %s",xrev1);
  236.                 VOID sprintf(commarg,"-p%s",xrev1);
  237.                 if (run((char*)nil,temp1file, co,"-q",commarg,RCSfilename,(char*)nil)){
  238.                         error("co failed");
  239.                         continue;
  240.                 }
  241.                 if (revnums<=1) {
  242.                         temp2file=workfilename;
  243.                         diagnose("diff%s%s -r%s %s",boption,otheroption,xrev1,workfilename);
  244.                 } else {
  245.                         temp2file=mktempfile("/tmp/",TMPFILE2);
  246.                         diagnose("retrieving revision %s",xrev2);
  247.             VOID sprintf(commarg,"-p%s",xrev2);
  248.                         if (run((char*)nil,temp2file, co,"-q",commarg,RCSfilename,(char *)nil)){
  249.                                 error("co failed");
  250.                                 continue;
  251.                         }
  252.                         diagnose("diff%s%s -r%s -r%s",boption,otheroption,xrev1,xrev2);
  253.                 }
  254.  
  255.                 exit_stats =
  256.             *boption
  257.             ? *otheroption
  258.               ? run((char*)nil,(char*)nil, DIFF, boption+1,    otheroption+1,    temp1file,temp2file,(char*)nil)
  259.               : run((char*)nil,(char*)nil, DIFF, boption+1,            temp1file,temp2file,(char*)nil)
  260.             : *otheroption
  261.               ? run((char*)nil,(char*)nil, DIFF,         otheroption+1,    temp1file,temp2file,(char*)nil)
  262.               : run((char*)nil,(char*)nil, DIFF,                 temp1file,temp2file,(char*)nil);
  263.  
  264.                 if (exit_stats == (1 << BYTESIZ))
  265.             diffs_found = 1;
  266.                 else if (exit_stats != 0) {
  267.                         error ("diff failed");
  268.                         continue;
  269.                 }
  270.         } while (cleanup(),
  271.                  ++argv, --argc >=1);
  272.  
  273.  
  274.         exit(nerror ? ERRCODE : diffs_found);
  275. }
  276.  
  277.  
  278. /*VARARGS3*/
  279. fterror(e, e1, e2)
  280. char * e, * e1, * e2;
  281. /* prints error message and terminates program with ERRCODE */
  282. {       nerror++;
  283.         VOID fprintf(stderr,"%s error: ",cmdid);
  284.     VOID fprintf(stderr,e, e1, e2);
  285.         VOID fprintf(stderr,"\n%s aborted\n",cmdid);
  286.         VOID cleanup();
  287.     exit(ERRCODE);
  288. }
  289.  
  290.