home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / vers_con / dosrcs / rcsdiff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-18  |  12.7 KB  |  395 lines

  1. /*
  2.  *                     RCS rcsdiff operation
  3.  */
  4. #ifndef lint
  5. static char rcsid[]=
  6. "$Header: /site/tmp/dosrcs/src/RCS/rcsdiff.c,v 5.5 90/07/15 21:55:43 lfk Release $ 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 5.5  90/07/15  21:55:43  lfk
  43.  * fixed incompatible arguments for MKS diff
  44.  * 
  45.  * Revision 5.3  90/07/15  20:24:46  lfk
  46.  * Most major fixes added between rev 5.1 and rev 5.5:
  47.  *     signals fixed so they work on MS-DOS
  48.  *     Added MKS arguments code so argv can be large
  49.  *     added code to handle slashes a'la Unix
  50.  *     added more file extensions to system from MS-DOS
  51.  * 
  52.  * Revision 5.2  90/07/15  11:33:19  ROOT_DOS
  53.  * DOS version of RCS 4.0 checked in for MODS
  54.  * by lfk@athena.mit.edu
  55.  * Also update to MSC 6.0
  56.  * 
  57.  * Revision 4.6  89/05/01  15:12:27  narten
  58.  * changed copyright header to reflect current distribution rules
  59.  * 
  60.  * Revision 4.5  88/11/08  12:01:51  narten
  61.  * changes from  eggert@sm.unisys.com (Paul Eggert)
  62.  * 
  63.  * Revision 4.5  88/08/09  19:12:41  eggert
  64.  * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
  65.  * 
  66.  * Revision 4.4  87/12/18  11:37:46  narten
  67.  * changes Jay Lepreau made in the 4.3 BSD version, to add support for
  68.  * "-i", "-w", and "-t" flags and to permit flags to be bundled together, 
  69.  * merged in.
  70.  * 
  71.  * Revision 4.3  87/10/18  10:31:42  narten
  72.  * Updating version numbers. Changes relative to 1.1 actually
  73.  * relative to 4.1
  74.  * 
  75.  * Revision 1.3  87/09/24  13:59:21  narten
  76.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  77.  * warnings)
  78.  * 
  79.  * Revision 1.2  87/03/27  14:22:15  jenkins
  80.  * Port to suns
  81.  * 
  82.  * Revision 1.1  84/01/23  14:50:18  kcs
  83.  * Initial revision
  84.  * 
  85.  * Revision 4.1  83/05/03  22:13:19  wft
  86.  * Added default branch, option -q, exit status like diff.
  87.  * Added fterror() to replace faterror().
  88.  * 
  89.  * Revision 3.6  83/01/15  17:52:40  wft
  90.  * Expanded mainprogram to handle multiple RCS files.
  91.  *
  92.  * Revision 3.5  83/01/06  09:33:45  wft
  93.  * Fixed passing of -c (context) option to diff.
  94.  *
  95.  * Revision 3.4  82/12/24  15:28:38  wft
  96.  * Added call to catchsig().
  97.  *
  98.  * Revision 3.3  82/12/10  16:08:17  wft
  99.  * Corrected checking of return code from diff; improved error msgs.
  100.  *
  101.  * Revision 3.2  82/12/04  13:20:09  wft
  102.  * replaced getdelta() with gettree(). Changed diagnostics.
  103.  *
  104.  * Revision 3.1  82/11/28  19:25:04  wft
  105.  * Initial revision.
  106.  *
  107.  */
  108. #include <ctype.h>
  109. #include "rcsbase.h"
  110. #define ERRCODE 2                   /*error code for exit status            */
  111. extern char *rindex();
  112. #ifndef lint
  113. static char rcsbaseid[] = RCSBASE;
  114. #endif
  115. static char co[] = CO;
  116.  
  117. extern int    cleanup();            /* cleanup after signals                */
  118. extern char * mktempfile();         /*temporary file name generator         */
  119. extern int    fterror();            /*forward for special fatal error func. */
  120. extern struct hshentry * genrevs(); /*generate delta numbers                */
  121. extern int    nerror;               /*counter for errors                    */
  122. extern int    quietflag;            /*suppresses diagnostics                */
  123. extern FILE * finptr;               /* RCS input file                       */
  124.  
  125. char *RCSfilename;
  126. char *workfilename;
  127. char * temp1file, * temp2file;
  128.  
  129. #ifdef MSDOS
  130. int old_stdout;
  131. char *gettmpdir();
  132. char tmpdir[NCPPN];
  133. #endif /* MSDOS */
  134.  
  135. char bops[10];
  136. char otherops[10];
  137.  
  138.  
  139. #ifdef MKS
  140. main(int argc, char *argv[], char *env[])
  141. #else
  142. main (argc, argv)
  143. int argc;
  144. char * argv[];
  145. #endif /* MKS */
  146. {
  147.         char * cmdusage;
  148.     char commarg[revlength+3];
  149.         int  revnums;                 /* counter for revision numbers given */
  150.         char * rev1, * rev2;          /* revision numbers from command line */
  151.         char numericrev[revlength];   /* holds expanded revision number     */
  152.         char * xrev1, * xrev2;        /* expanded revision numbers          */
  153.         struct hshentry * gendeltas[hshsize];/*stores deltas to be generated*/
  154.         struct hshentry * target;
  155.     char * boption, * otheroption;
  156.         int  exit_stats;
  157.     int  diffs_found;
  158.     char *argp;
  159.     register c;
  160. #ifdef MKS
  161.     int z = 0;
  162.     int ARGC = 0;
  163.     char **tmp;
  164.     char *env_name;
  165. #    define MAXARGS 500        /* This means 500 items on the command line */
  166.     if (!(tmp = (char **)malloc(sizeof(char *)*(MAXARGS+1)))) {
  167.         fprintf(stderr, "%s: can't allocate space for arguments\n",argv[0]);
  168.         exit(1);
  169.     }
  170.     for ( z = 0 ; env[z] != NULL; z++) {    /* loop through environment */
  171.         if (*env[z] == '~') {    /* testing for entries begining with '~' */
  172.             *++env[z];            /* increment pointer to delete '~' */
  173.             tmp[ARGC++] = env[z];    /* add it to our new array */
  174.             if (z >= MAXARGS) {
  175.                 fprintf(stderr, "%s: can't handle any more arguments\n", argv[0]);
  176.                 goto list;
  177.             }
  178.         }
  179.         else if (*env[z] == '_') {    /* testing for entries begining with _ */
  180.             *++env[z] ; *++env[z];    /* move past the '_' and the '=' */
  181.             env_name = env[z];    /* copy the name */
  182.         }
  183.     }
  184. list:
  185.     if ( STREQ( (char *) argv[0] , env_name ) ) {    /* test name against startup args */
  186.         /* environment arguments meant for this program */
  187. #    ifdef DEBUG
  188.         printf("Using shell supplied args\n");
  189. #    endif
  190.         argc = ARGC;
  191.         tmp[ARGC] = NULL;    /* the terminal NULL */
  192.         argv = tmp;
  193.     }
  194. #    ifdef DEBUG
  195.     else 
  196.         printf("Using startup supplied args\n");
  197. #    endif /* debug */
  198. #endif /* MKS */
  199.  
  200.         catchints();
  201.         otheroption = otherops + 2;
  202.     boption = bops + 2;
  203.         cmdid = "rcsdiff";
  204.     cmdusage = "command format:\n    rcsdiff [-biwt] [-q] [-cefhn] [-rrev1] [-rrev2] file";
  205.     diffs_found=revnums=0;
  206.         while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
  207.         argp = &((*argv)[1]);
  208.         while (c = *argp++) switch (c) {
  209.                 case 'r':
  210.                 if (*argp!='\0') {
  211.                             if (revnums==0) {
  212.                                     rev1= argp; revnums=1;
  213.                             } elif (revnums==1) {
  214.                                     rev2= argp; revnums=2;
  215.                             } else {
  216.                     fterror("too many revision numbers");
  217.                             }
  218.                         } /* do nothing for empty -r */
  219.             argp += strlen(argp);
  220.                         break;
  221.                 case 'b':
  222.                 case 'i':
  223.                 case 'w':
  224.                 case 't':
  225.             if (!rindex(bops + 2, c))
  226.                 *boption++ = c;
  227.             break;
  228.         case 'q':
  229.             quietflag=true;
  230.             break;
  231.                 case 'c':
  232.                 case 'e':
  233.                 case 'f':
  234.                 case 'h':
  235.                 case 'n':
  236.                         if (otheroption == otherops + 2) {
  237.                 *otheroption++ = c;
  238.                 if (c == 'c' && isdigit(*argp)) {
  239.                     while (isdigit(*argp) && otheroption < otherops+sizeof(otherops)-1)
  240.                         *otheroption++ = *argp++;
  241.                     if (*argp)
  242.                         faterror("-c: bad count");
  243.                     argp = "";
  244.                 }
  245.                         } else {
  246.                 fterror("Options c,e,f,h,n are mutually exclusive");
  247.                         }
  248.             break;
  249.                 default:
  250.             fterror("unknown option: %s\n%s", *argv,cmdusage);
  251.                 };
  252.         } /* end of option processing */
  253.  
  254.     if (boption != bops + 2) {
  255.         bops[0] = ' ';
  256.         bops[1] = '-';
  257.         boption = bops;
  258.     }
  259.     if (otheroption != otherops + 2) {
  260.          otherops[0] = ' ';
  261.         otherops[1] = '-';
  262.         otheroption = otherops;
  263.     }
  264.     if (argc<1) fterror("No input file\n%s",cmdusage);
  265.  
  266. #ifdef MSDOS
  267.     strcpy( tmpdir, gettmpdir() );
  268.     old_stdout = dup(1);
  269. #endif /* MSDOS */        
  270. /* now handle all filenames */
  271.         do {
  272.                 finptr=NULL;
  273.  
  274.                 if (pairfilenames(argc,argv,true,false)!=1) continue;
  275.         diagnose("===================================================================");
  276.                 diagnose("RCS file: %s",RCSfilename);
  277.                 if (revnums<2 && !(access(workfilename,4)==0)) {
  278.                         error("Can't open %s",workfilename);
  279.                         continue;
  280.                 }
  281.                 if (!trysema(RCSfilename,false)) continue; /* give up */
  282.  
  283.  
  284.                 gettree(); /* reads in the delta tree */
  285.  
  286.                 if (Head==nil) {
  287.                         error("no revisions present");
  288.                         continue;
  289.                 }
  290.                 if (revnums==0)
  291.                         rev1=Dbranch!=nil?Dbranch->num:Head->num; /* default rev1 */
  292.  
  293.                 if (!expandsym(rev1,numericrev)) continue;
  294.                 if (!(target=genrevs(numericrev,(char *)nil,(char *)nil,(char *)nil,gendeltas))) continue;
  295.                 xrev1=target->num;
  296.  
  297.                 if (revnums==2) {
  298.                         if (!expandsym(rev2,numericrev)) continue;
  299.                         if (!(target=genrevs(numericrev,(char *)nil,(char *)nil,(char *)nil,gendeltas))) continue;
  300.                         xrev2=target->num;
  301.                 }
  302.  
  303.  
  304. #ifdef MSDOS
  305.                 temp1file=mktempfile(tmpdir,TMPFILE1);
  306. #else
  307.                 temp1file=mktempfile("/tmp/",TMPFILE1);
  308. #endif /* MSDOS */
  309.                 diagnose("retrieving revision %s",xrev1);
  310.                 VOID sprintf(commarg,"-p%s",xrev1);
  311.                 if (run((char*)nil,temp1file, co,"-q",commarg,RCSfilename,(char*)nil)){
  312.                         error("co failed");
  313.                         continue;
  314.                 }
  315.                 if (revnums<=1) {
  316.                         temp2file=workfilename;
  317.                         diagnose("diff%s%s -r%s %s",boption,otheroption,xrev1,workfilename);
  318.                 } else {
  319. #ifdef MSDOS
  320.                         temp2file=mktempfile(tmpdir,TMPFILE2);
  321. #else
  322.                         temp2file=mktempfile("/tmp/",TMPFILE2);
  323. #endif /* MSDOS */
  324.                         diagnose("retrieving revision %s",xrev2);
  325.             VOID sprintf(commarg,"-p%s",xrev2);
  326.                         if (run((char*)nil,temp2file, co,"-q",commarg,RCSfilename,(char *)nil)){
  327.                                 error("co failed");
  328.                                 continue;
  329.                         }
  330.                         diagnose("diff%s%s -r%s -r%s",boption,otheroption,xrev1,xrev2);
  331.                 }
  332. #ifdef MSDOS
  333. #    ifdef MKS
  334.         dup2( old_stdout, 1 );
  335.                 exit_stats =
  336.             *boption
  337.             ? *otheroption
  338.               ? spawnlp( 0, DIFF, DIFF, boption+1, otheroption+1, temp1file,temp2file,NULL)
  339.               : spawnlp( 0, DIFF, DIFF, boption+1, temp1file, temp2file, NULL)
  340.             : *otheroption
  341.               ? spawnlp( 0, DIFF, DIFF, otheroption+1, temp1file,temp2file, NULL)
  342.               : spawnlp( 0, DIFF, DIFF, temp1file, temp2file, NULL);
  343. #    else
  344.         dup2( old_stdout, 1 );
  345.                 exit_stats =
  346.             *boption
  347.             ? *otheroption
  348.               ? spawnlp( 0, DIFF, DIFF, "-a", boption+1, otheroption+1, temp1file,temp2file,NULL)
  349.               : spawnlp( 0, DIFF, DIFF, "-a", boption+1, temp1file, temp2file, NULL)
  350.             : *otheroption
  351.               ? spawnlp( 0, DIFF, DIFF, "-a", otheroption+1, temp1file,temp2file, NULL)
  352.               : spawnlp( 0, DIFF, DIFF, "-a", temp1file, temp2file, NULL);
  353. #    endif
  354. #else
  355.                 exit_stats =
  356.             *boption
  357.             ? *otheroption
  358.               ? run((char*)nil,(char*)nil, DIFF, boption+1,    otheroption+1,    temp1file,temp2file,(char*)nil)
  359.               : run((char*)nil,(char*)nil, DIFF, boption+1,            temp1file,temp2file,(char*)nil)
  360.             : *otheroption
  361.               ? run((char*)nil,(char*)nil, DIFF,         otheroption+1,    temp1file,temp2file,(char*)nil)
  362.               : run((char*)nil,(char*)nil, DIFF,                 temp1file,temp2file,(char*)nil);
  363. #endif /* MSDOS */
  364.  
  365. #ifdef MSDOS
  366.                 if (exit_stats == 1 )
  367. #else
  368.                 if (exit_stats == (1 << BYTESIZ))
  369. #endif /* MSDOS */
  370.             diffs_found = 1;
  371.                 else if (exit_stats != 0) {
  372.                         error ("diff failed");
  373.                         continue;
  374.                 }
  375.         } while ( cleanup(),
  376.                  ++argv, --argc >=1);
  377.  
  378.  
  379.         exit(nerror ? ERRCODE : diffs_found);
  380. }
  381.  
  382.  
  383. /*VARARGS3*/
  384. fterror(e, e1, e2)
  385. char * e, * e1, * e2;
  386. /* prints error message and terminates program with ERRCODE */
  387. {       nerror++;
  388.         VOID fprintf(stderr,"%s error: ",cmdid);
  389.     VOID fprintf(stderr,e, e1, e2);
  390.         VOID fprintf(stderr,"\n%s aborted\n",cmdid);
  391.         VOID cleanup();
  392.     exit(ERRCODE);
  393. }
  394.  
  395.