home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / rcs4 / source / rcsdiff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-08  |  13.2 KB  |  398 lines

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