# 2.11BSD#431 - /usr/src/new/rcs/src/co.c

##### Functions

    buildjoin         X
    creatempty        X
    getrev            X
    main              X
    preparejoin       X
    rmlock            X
    rmworkfile        X

##### Variables

    RCSfilename       X
    author            X
    caller            X
    date              X
    finaldate         X
    forceflag         X
    gendeltas         X
    join              X
    joinlist          X
    lastjoin          X
    lockflag          X
    newRCSfilename    X
    neworkfilename    X
    numericrev        X
    rev               X
    state             X
    targetdelta       X
    tostdout          X
    unlockflag        X
    workfilename      X

       1: /*
       2:  *                     RCS checkout operation
       3:  */
       4: #ifndef lint
       5: static char rcsid[]=
       6: "$Header: /usr/src/local/bin/rcs/src/RCS/co.c,v 4.5 87/12/18 11:35:40 narten Exp $ Purdue CS";
       7: #endif
       8: /*****************************************************************************
       9:  *                       check out revisions from RCS files
      10:  *****************************************************************************
      11:  *
      12:  * Copyright (C) 1982 by Walter F. Tichy
      13:  *                       Purdue University
      14:  *                       Computer Science Department
      15:  *                       West Lafayette, IN 47907
      16:  *
      17:  * All rights reserved. No part of this software may be sold or distributed
      18:  * in any form or by any means without the prior written permission of the
      19:  * author.
      20:  * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
      21:  */
      22:
      23:
      24: /* $Log:	co.c,v $
      25:  * Revision 4.5  87/12/18  11:35:40  narten
      26:  * lint cleanups (from Guy Harris)
      27:  *
      28:  * Revision 4.4  87/10/18  10:20:53  narten
      29:  * Updating version numbers changes relative to 1.1, are actually
      30:  * relative to 4.2
      31:  *
      32:  * Revision 1.3  87/09/24  13:58:30  narten
      33:  * Sources now pass through lint (if you ignore printf/sprintf/fprintf
      34:  * warnings)
      35:  *
      36:  * Revision 1.2  87/03/27  14:21:38  jenkins
      37:  * Port to suns
      38:  *
      39:  * Revision 1.1  84/01/23  14:49:58  kcs
      40:  * Initial revision
      41:  *
      42:  * Revision 4.2  83/12/05  13:39:48  wft
      43:  * made rewriteflag external.
      44:  *
      45:  * Revision 4.1  83/05/10  16:52:55  wft
      46:  * Added option -u and -f.
      47:  * Added handling of default branch.
      48:  * Replaced getpwuid() with getcaller().
      49:  * Removed calls to stat(); now done by pairfilenames().
      50:  * Changed and renamed rmoldfile() to rmworkfile().
      51:  * Replaced catchints() calls with restoreints(), unlink()--link() with rename();
      52:  *
      53:  * Revision 3.7  83/02/15  15:27:07  wft
      54:  * Added call to fastcopy() to copy remainder of RCS file.
      55:  *
      56:  * Revision 3.6  83/01/15  14:37:50  wft
      57:  * Added ignoring of interrupts while RCS file is renamed; this avoids
      58:  * deletion of RCS files during the unlink/link window.
      59:  *
      60:  * Revision 3.5  82/12/08  21:40:11  wft
      61:  * changed processing of -d to use DATEFORM; removed actual from
      62:  * call to preparejoin; re-fixed printing of done at the end.
      63:  *
      64:  * Revision 3.4  82/12/04  18:40:00  wft
      65:  * Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE.
      66:  * Fixed printing of "done".
      67:  *
      68:  * Revision 3.3  82/11/28  22:23:11  wft
      69:  * Replaced getlogin() with getpwuid(), flcose() with ffclose(),
      70:  * %02d with %.2d, mode generation for working file with WORKMODE.
      71:  * Fixed nil printing. Fixed -j combined with -l and -p, and exit
      72:  * for non-existing revisions in preparejoin().
      73:  *
      74:  * Revision 3.2  82/10/18  20:47:21  wft
      75:  * Mode of working file is now maintained even for co -l, but write permission
      76:  * is removed.
      77:  * The working file inherits its mode from the RCS file, plus write permission
      78:  * for the owner. The write permission is not given if locking is strict and
      79:  * co does not lock.
      80:  * An existing working file without write permission is deleted automatically.
      81:  * Otherwise, co asks (empty answer: abort co).
      82:  * Call to getfullRCSname() added, check for write error added, call
      83:  * for getlogin() fixed.
      84:  *
      85:  * Revision 3.1  82/10/13  16:01:30  wft
      86:  * fixed type of variables receiving from getc() (char -> int).
      87:  * removed unused variables.
      88:  */
      89:
      90:
      91:
      92:
      93: #include "rcsbase.h"
      94: #include "time.h"
      95: #include <sys/types.h>
      96: #include <sys/stat.h>
      97:
      98: #ifndef lint
      99: static char rcsbaseid[] = RCSBASE;
     100: #endif
     101:
     102: extern FILE * fopen();
     103: extern int    rename();
     104: extern char * getcaller();          /*get login of caller                   */
     105: extern char * malloc();
     106: extern struct hshentry * genrevs(); /*generate delta numbers                */
     107: extern char * getancestor();
     108: extern int  nextc;                  /*next input character                  */
     109: extern int  nerror;                 /*counter for errors                    */
     110: extern char * Kdesc;                /*keyword for description               */
     111: extern char * buildrevision();      /*constructs desired revision           */
     112: extern int    buildjoin();          /*join several revisions                */
     113: extern char * mktempfile();         /*temporary file name generator         */
     114: extern struct hshentry * findlock();/*find (and delete) a lock              */
     115: extern struct lock * addlock();     /*add a new lock                        */
     116: extern long   maketime();           /*convert parsed time to unix time.     */
     117: extern struct tm * localtime();     /*convert unixtime into a tm-structure  */
     118: extern int StrictLocks;
     119: extern FILE * finptr;               /* RCS input file                       */
     120: extern FILE * frewrite;             /* new RCS file                         */
     121: extern int    rewriteflag;          /* indicates whether input should be    */
     122:                     /* echoed to frewrite                   */
     123:
     124: char * newRCSfilename, * neworkfilename;
     125: char * RCSfilename, * workfilename;
     126: extern struct stat RCSstat, workstat; /* file status of RCS and work file   */
     127: extern int  haveRCSstat, haveworkstat;/* status indicators                  */
     128:
     129: char * date, * rev, * state, * author, * join;
     130: char finaldate[datelength];
     131:
     132: int forceflag, lockflag, unlockflag, tostdout;
     133: char * caller;                        /* caller's login;                    */
     134: extern quietflag;
     135:
     136: char numericrev[revlength];           /* holds expanded revision number     */
     137: struct hshentry * gendeltas[hshsize]; /* stores deltas to be generated      */
     138: struct hshentry * targetdelta;        /* final delta to be generated        */
     139:
     140: char * joinlist[joinlength];          /* pointers to revisions to be joined */
     141: int lastjoin;                         /* index of last element in joinlist  */
     142:
     143: main (argc, argv)
     144: int argc;
     145: char * argv[];
     146: {
     147:         int killock;                  /* indicates whether a lock is removed*/
     148:         char * cmdusage;
     149:         struct tm parseddate, *ftm;
     150:         char * rawdate;
     151:         long unixtime;
     152:
     153:     catchints();
     154:         cmdid = "co";
     155:     cmdusage = "command format:\nco -f[rev] -l[rev] -p[rev] -q[rev] -r[rev] -ddate -sstate -w[login] -jjoinlist file ...";
     156:         date = rev = state = author = join = nil;
     157:     forceflag = lockflag = unlockflag = tostdout = quietflag = false;
     158:     caller=getcaller();
     159:
     160:         while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
     161:                 switch ((*argv)[1]) {
     162:
     163:                 case 'r':
     164:                 revno:  if ((*argv)[2]!='\0') {
     165:                                 if (rev!=nil) warn("Redefinition of revision number");
     166:                                 rev = (*argv)+2;
     167:                         }
     168:                         break;
     169:
     170:         case 'f':
     171:             forceflag=true;
     172:             goto revno;
     173:
     174:                 case 'l':
     175:                         lockflag=true;
     176:                         if (unlockflag) {
     177:                                 warn("-l has precedence over -u");
     178:                                 unlockflag=false;
     179:                         }
     180:                         goto revno;
     181:
     182:                 case 'u':
     183:                         unlockflag=true;
     184:                         if (lockflag) {
     185:                                 warn("-l has precedence over -u");
     186:                                 unlockflag=false;
     187:                         }
     188:                         goto revno;
     189:
     190:                 case 'p':
     191:                         tostdout=true;
     192:                         goto revno;
     193:
     194:                 case 'q':
     195:                         quietflag=true;
     196:                         goto revno;
     197:
     198:                 case 'd':
     199:                         if ((*argv)[2]!='\0') {
     200:                                 if (date!=nil) warn("Redefinition of -d option");
     201:                                 rawdate=(*argv)+2;
     202:                         }
     203:                         /* process date/time */
     204:                         if (partime(rawdate,&parseddate)==0)
     205:                                 faterror("Can't parse date/time: %s",rawdate);
     206:                         if ((unixtime=maketime(&parseddate))== 0L)
     207:                                 faterror("Inconsistent date/time: %s",rawdate);
     208:                         ftm=localtime(&unixtime);
     209:                         VOID sprintf(finaldate,DATEFORM,
     210:                         ftm->tm_year,ftm->tm_mon+1,ftm->tm_mday,ftm->tm_hour,ftm->tm_min,ftm->tm_sec);
     211:                         date=finaldate;
     212:                         break;
     213:
     214:                 case 'j':
     215:                         if ((*argv)[2]!='\0'){
     216:                                 if (join!=nil)warn("Redefinition of -j option");
     217:                                 join = (*argv)+2;
     218:                         }
     219:                         break;
     220:
     221:                 case 's':
     222:                         if ((*argv)[2]!='\0'){
     223:                                 if (state!=nil)warn("Redefinition of -s option");
     224:                                 state = (*argv)+2;
     225:                         }
     226:                         break;
     227:
     228:                 case 'w':
     229:                         if (author!=nil)warn("Redefinition of -w option");
     230:                         if ((*argv)[2]!='\0')
     231:                                 author = (*argv)+2;
     232:                         else    author = caller;
     233:                         break;
     234:
     235:                 default:
     236:                         faterror("unknown option: %s\n%s", *argv,cmdusage);
     237:
     238:                 };
     239:         } /* end of option processing */
     240:
     241:         if (argc<1) faterror("No input file\n%s",cmdusage);
     242:
     243:         /* now handle all filenames */
     244:         do {
     245:         rewriteflag=false;
     246:         finptr=frewrite=NULL;
     247:         neworkfilename=nil;
     248:
     249:         if (!pairfilenames(argc,argv,true,tostdout)) continue;
     250:
     251:         /* now RCSfilename contains the name of the RCS file, and finptr
     252:          * the file descriptor. If tostdout is false, workfilename contains
     253:          * the name of the working file, otherwise undefined (not nil!).
     254:          * Also, RCSstat, workstat, and haveworkstat have been set.
     255:          */
     256:         diagnose("%s  -->  %s", RCSfilename,tostdout?"stdout":workfilename);
     257:
     258:
     259:         if (!tostdout && !trydiraccess(workfilename)) continue; /* give up */
     260:         if ((lockflag||unlockflag) && !checkaccesslist(caller)) continue;     /* give up */
     261:         if (!trysema(RCSfilename,lockflag||unlockflag)) continue;           /* give up */
     262:
     263:
     264:         gettree();  /* reads in the delta tree */
     265:
     266:         if (Head==nil) {
     267:                 /* no revisions; create empty file */
     268:                 diagnose("no revisions present; generating empty revision 0.0");
     269:                 if (!tostdout)
     270:                         if (!creatempty()) continue;
     271:                 else    VOID putchar('\0'); /* end of file */
     272:                 /* Can't reserve a delta, so don't call addlock */
     273:         } else {
     274:                 if (rev!=nil) {
     275:                         /* expand symbolic revision number */
     276:                         if (!expandsym(rev,numericrev))
     277:                                 continue;
     278:         } elsif (unlockflag && (targetdelta=findlock(caller,false))!=nil) {
     279:             VOID strcpy(numericrev,targetdelta->num);
     280:                 } elsif (Dbranch!=nil) {
     281:                         VOID strcpy(numericrev,Dbranch->num);
     282:         } else  numericrev[0]='\0'; /* empty */
     283:                 /* get numbers of deltas to be generated */
     284:                 if (!(targetdelta=genrevs(numericrev,date,author,state,gendeltas)))
     285:                         continue;
     286:                 /* check reservations */
     287:                 if (lockflag && !addlock(targetdelta,caller))
     288:                         continue;
     289:
     290:                 if (unlockflag) {
     291:                         if((killock=rmlock(caller,targetdelta))== -1)
     292:                                 continue;
     293:                 } else {
     294:                         killock=0;
     295:                 }
     296:
     297:                 if (join && !preparejoin()) continue;
     298:
     299:                 diagnose("revision %s %s",targetdelta->num,
     300:                          lockflag?"(locked)":
     301:                          (unlockflag?"(unlocked)":""));
     302:
     303:                 /* remove old working file if necessary */
     304:                 if (!tostdout)
     305:                         if (!rmworkfile()) continue;
     306:
     307:                 /* prepare for rewriting the RCS file */
     308:                 if (lockflag||(killock==1)) {
     309:                         newRCSfilename=mktempfile(RCSfilename,NEWRCSFILE);
     310:                         if ((frewrite=fopen(newRCSfilename, "w"))==NULL) {
     311:                                 error("Can't open file %s",newRCSfilename);
     312:                                 continue;
     313:                         }
     314:                         putadmin(frewrite);
     315:                         puttree(Head,frewrite);
     316:                         VOID fprintf(frewrite, "\n\n%s%c",Kdesc,nextc);
     317:                         rewriteflag=true;
     318:                 }
     319:
     320:                 /* skip description */
     321:                 getdesc(false); /* don't echo*/
     322:
     323:                 if (!(neworkfilename=buildrevision(gendeltas,targetdelta,
     324:                       tostdout?(join!=nil?"/tmp/":(char *)nil):workfilename,true)))
     325:                                 continue;
     326:
     327:                 if ((lockflag||killock==1)&&nerror==0) {
     328:                         /* rewrite the rest of the RCSfile */
     329:                         fastcopy(finptr,frewrite);
     330:                         ffclose(frewrite); frewrite=NULL;
     331:             ignoreints();
     332:                         if (rename(newRCSfilename,RCSfilename)<0) {
     333:                                 error("Can't rewrite %s; saved in: %s",
     334:                                 RCSfilename, newRCSfilename);
     335:                                 newRCSfilename[0]='\0'; /* avoid deletion*/
     336:                                 restoreints();
     337:                                 break;
     338:                         }
     339:                         newRCSfilename[0]='\0'; /* avoid re-deletion by cleanup()*/
     340:                         if (chmod(RCSfilename,RCSstat.st_mode & ~0222)<0)
     341:                             warn("Can't preserve mode of %s",RCSfilename);
     342:                         restoreints();
     343:                 }
     344:
     345: #               ifdef SNOOPFILE
     346:                 logcommand("co",targetdelta,gendeltas,caller);
     347: #               endif
     348:
     349:                 if (join) {
     350:                         VOID rmsema(); /* kill semaphore file so other co's can proceed */
     351:                         if (!buildjoin(neworkfilename,tostdout)) continue;
     352:                 }
     353:                 if (!tostdout) {
     354:             if (rename(neworkfilename,workfilename) <0) {
     355:                                 error("Can't create %s; see %s",workfilename,neworkfilename);
     356:                                 neworkfilename[0]= '\0'; /*avoid deletion*/
     357:                                 continue;
     358:                         }
     359:             neworkfilename[0]= '\0'; /*avoid re-deletion by cleanup()*/
     360:         }
     361:         }
     362:     if (!tostdout)
     363:             if (chmod(workfilename, WORKMODE(RCSstat.st_mode))<0)
     364:                 warn("Can't adjust mode of %s",workfilename);
     365:
     366:
     367:         if (!tostdout) diagnose("done");
     368:         } while (cleanup(),
     369:                  ++argv, --argc >=1);
     370:
     371:         exit(nerror!=0);
     372:
     373: }       /* end of main (co) */
     374:
     375:
     376: /*****************************************************************
     377:  * The following routines are auxiliary routines
     378:  *****************************************************************/
     379:
     380: int rmworkfile()
     381: /* Function: unlinks workfilename, if it exists, under the following conditions:
     382:  * If it is read-only, workfilename is unlinked.
     383:  * Otherwise (file writable):
     384:  *   if !quietmode asks the user whether to really delete it (default: fail);
     385:  *   otherwise failure.
     386:  * Returns false on failure to unlink, true otherwise.
     387:  */
     388: {
     389:         int response, c;    /* holds user response to queries */
     390:
     391:         if (haveworkstat< 0)      /* File doesn't exist; set by pairfilenames*/
     392:             return (true);        /* No problem */
     393:
     394:     if ((workstat.st_mode & 0222)&&!forceflag) {    /* File is writable */
     395:             if (!quietflag) {
     396:                 VOID fprintf(stderr,"writable %s exists; overwrite? [ny](n): ",workfilename);
     397:                 /* must be stderr in case of IO redirect */
     398:                 c=response=getchar();
     399:                 while (!(c==EOF || c=='\n')) c=getchar(); /*skip rest*/
     400:                 if (!(response=='y'||response=='Y')) {
     401:                         warn("checkout aborted.");
     402:                         return false;
     403:                 }
     404:             } else {
     405:                 error("writable %s exists; checkout aborted.",workfilename);
     406:                 return false;
     407:             }
     408:         }
     409:     /* now unlink: either not writable, forceflag, or permission given */
     410:         if (unlink(workfilename) != 0) {            /* Remove failed   */
     411:             error("Can't unlink %s",workfilename);
     412:             return false;
     413:         }
     414:         return true;
     415: }
     416:
     417:
     418: creatempty()
     419: /* Function: creates an empty working file.
     420:  * First, removes an existing working file with rmworkfile().
     421:  */
     422: {
     423:         int  fdesc;              /* file descriptor */
     424:
     425:         if (!rmworkfile()) return false;
     426:         fdesc=creat(workfilename,0666);
     427:         if (fdesc < 0) {
     428:                 faterror("Cannot create %s",workfilename);
     429:                 return false;
     430:         } else {
     431:                 VOID close(fdesc); /* empty file */
     432:                 return true;
     433:         }
     434: }
     435:
     436:
     437: int rmlock(who,delta)
     438: char * who; struct hshentry * delta;
     439: /* Function: removes the lock held by who on delta.
     440:  * Returns -1 if someone else holds the lock,
     441:  * 0 if there is no lock on delta,
     442:  * and 1 if a lock was found and removed.
     443:  */
     444: {       register struct lock * next, * trail;
     445:         char * num;
     446:         struct lock dummy;
     447:         int whomatch, nummatch;
     448:
     449:         num=delta->num;
     450:         dummy.nextlock=next=Locks;
     451:         trail = &dummy;
     452:         while (next!=nil) {
     453:                 whomatch=strcmp(who,next->login);
     454:                 nummatch=strcmp(num,next->delta->num);
     455:                 if ((whomatch==0) && (nummatch==0)) break;
     456:                      /*found a lock on delta by who*/
     457:                 if ((whomatch!=0)&&(nummatch==0)) {
     458:                     error("revision %s locked by %s; use co -r or rcs -u",num,next->login);
     459:                     return -1;
     460:                 }
     461:                 trail=next;
     462:                 next=next->nextlock;
     463:         }
     464:         if (next!=nil) {
     465:                 /*found one; delete it */
     466:                 trail->nextlock=next->nextlock;
     467:                 Locks=dummy.nextlock;
     468:                 next->delta->lockedby=nil; /* reset locked-by */
     469:                 return 1; /*success*/
     470:         } else  return 0; /*no lock on delta*/
     471: }
     472:
     473:
     474:
     475:
     476: /*****************************************************************
     477:  * The rest of the routines are for handling joins
     478:  *****************************************************************/
     479:
     480: char * getrev(sp, tp, buffsize)
     481: register char * sp, *tp; int buffsize;
     482: /* Function: copies a symbolic revision number from sp to tp,
     483:  * appends a '\0', and returns a pointer to the character following
     484:  * the revision number; returns nil if the revision number is more than
     485:  * buffsize characters long.
     486:  * The revision number is terminated by space, tab, comma, colon,
     487:  * semicolon, newline, or '\0'.
     488:  * used for parsing the -j option.
     489:  */
     490: {
     491:         register char c;
     492:         register int length;
     493:
     494:         length = 0;
     495:         while (((c= *sp)!=' ')&&(c!='\t')&&(c!='\n')&&(c!=':')&&(c!=',')
     496:                 &&(c!=';')&&(c!='\0')) {
     497:                 if (length>=buffsize) return false;
     498:                 *tp++= *sp++;
     499:                 length++;
     500:         }
     501:         *tp= '\0';
     502:         return sp;
     503: }
     504:
     505:
     506:
     507: int preparejoin()
     508: /* Function: Parses a join list pointed to by join and places pointers to the
     509:  * revision numbers into joinlist.
     510:  */
     511: {
     512:         struct hshentry * (* joindeltas)[];
     513:         struct hshentry * tmpdelta;
     514:         register char * j;
     515:         char symbolrev[revlength],numrev[revlength];
     516:
     517:         joindeltas = (struct hshentry * (*)[])malloc(hshsize*sizeof(struct hshentry *));
     518:         j=join;
     519:         lastjoin= -1;
     520:         for (;;) {
     521:                 while ((*j==' ')||(*j=='\t')||(*j==',')) j++;
     522:                 if (*j=='\0') break;
     523:                 if (lastjoin>=joinlength-2) {
     524:                         error("too many joins");
     525:                         return(false);
     526:                 }
     527:                 if(!(j=getrev(j,symbolrev,revlength))) return false;
     528:                 if (!expandsym(symbolrev,numrev)) return false;
     529:                 tmpdelta=genrevs(numrev,(char *)nil,(char *)nil,(char *)nil,(struct hshentry * *)joindeltas);
     530:                 if (tmpdelta==nil)
     531:                         return false;
     532:                 else    joinlist[++lastjoin]=tmpdelta->num;
     533:                 while ((*j==' ') || (*j=='\t')) j++;
     534:                 if (*j == ':') {
     535:                         j++;
     536:                         while((*j==' ') || (*j=='\t')) j++;
     537:                         if (*j!='\0') {
     538:                                 if(!(j=getrev(j,symbolrev,revlength))) return false;
     539:                                 if (!expandsym(symbolrev,numrev)) return false;
     540:                                 tmpdelta=genrevs(numrev,(char *)nil,(char *)nil,(char *)nil, (struct hshentry * *) joindeltas);
     541:                                 if (tmpdelta==nil)
     542:                                         return false;
     543:                                 else    joinlist[++lastjoin]=tmpdelta->num;
     544:                         } else {
     545:                                 error("join pair incomplete");
     546:                                 return false;
     547:                         }
     548:                 } else {
     549:                         if (lastjoin==0) { /* first pair */
     550:                                 /* common ancestor missing */
     551:                                 joinlist[1]=joinlist[0];
     552:                                 lastjoin=1;
     553:                                 /*derive common ancestor*/
     554:                                 joinlist[0]=malloc(revlength);
     555:                                 if (!getancestor(targetdelta->num,joinlist[1],joinlist[0]))
     556:                                        return false;
     557:                         } else {
     558:                                 error("join pair incomplete");
     559:                                 return false;
     560:                         }
     561:                 }
     562:         }
     563:         if (lastjoin<1) {
     564:                 error("empty join");
     565:                 return false;
     566:         } else  return true;
     567: }
     568:
     569:
     570:
     571: buildjoin(initialfile, tostdout)
     572: char * initialfile; int tostdout;
     573: /* Function: merge pairs of elements in joinlist into initialfile
     574:  * If tostdout==true, copy result to stdout.
     575:  * All unlinking of initialfile, rev2, and rev3 should be done by cleanup().
     576:  */
     577: {       char command[NCPPN+80];
     578:         char subs[revlength];
     579:         char * rev2, * rev3;
     580:         int i;
     581:
     582:         rev2=mktempfile("/tmp/",JOINFIL2);
     583:         rev3=mktempfile("/tmp/",JOINFIL3);
     584:
     585:         i=0;
     586:         while (i<lastjoin) {
     587:                 /*prepare marker for merge*/
     588:                 if (i==0)
     589:                         VOID strcpy(subs,targetdelta->num);
     590:                 else    VOID sprintf(subs, "merge%d",i/2);
     591:                 diagnose("revision %s",joinlist[i]);
     592:                 VOID sprintf(command,"%s/co -p%s -q  %s > %s\n",TARGETDIR,joinlist[i],RCSfilename,rev2);
     593:                 if (system(command)) {
     594:                         nerror++;return false;
     595:                 }
     596:                 diagnose("revision %s",joinlist[i+1]);
     597:                 VOID sprintf(command,"%s/co -p%s -q  %s > %s\n",TARGETDIR,joinlist[i+1],RCSfilename,rev3);
     598:                 if (system(command)) {
     599:                         nerror++; return false;
     600:                 }
     601:                 diagnose("merging...");
     602:                 VOID sprintf(command,"%s %s%s %s %s %s %s\n", MERGE,
     603:                         ((i+2)>=lastjoin && tostdout)?"-p ":"",
     604:                         initialfile,rev2,rev3,subs,joinlist[i+1]);
     605:                 if (system(command)) {
     606:                         nerror++; return false;
     607:                 }
     608:                 i=i+2;
     609:         }
     610:         return true;
     611: }

#### Defined functions

buildjoin defined in line 571; used 2 times

- in line 112, 351

creatempty defined in line 418; used 1 times

- in line 270

getrev defined in line 480; used 2 times

- in line 527, 538

main defined in line 143; never used
preparejoin defined in line 507; used 1 times

- in line 297

rmlock defined in line 437; used 1 times

- in line 291

rmworkfile defined in line 380; used 2 times

- in line 305, 425

#### Defined variables

RCSfilename defined in line 125; used 9 times

- in line 256-261(2), 309, 332-334(2), 340-341(2), 592-597(2)

author defined in line 129; used 5 times

- in line 156, 229-232(3), 284

caller defined in line 133; used 7 times

- in line 158, 232, 260, 278, 287-291(2), 346

date defined in line 129; used 4 times

- in line 156, 200, 211, 284

finaldate defined in line 130; used 2 times

- in line 209-211(2)

forceflag defined in line 132; used 3 times

- in line 157, 171, 394

gendeltas defined in line 137; used 3 times

- in line 284, 323, 346

join defined in line 129; used 7 times

- in line 156, 216-217(2), 297, 324, 349, 518

joinlist defined in line 140; used 12 times

- in line 532, 543, 551-555(5), 591-597(4), 604

lastjoin defined in line 141; used 9 times

- in line 519-523(2), 532, 543, 549-552(2), 563, 586, 603

lockflag defined in line 132; used 9 times

- in line 157, 175, 184, 260-261(2), 287, 300, 308, 327

newRCSfilename defined in line 124; used 7 times

- in line 309-311(3), 332-339(4)

neworkfilename defined in line 124; used 7 times

- in line 247, 323, 351-359(5)

numericrev defined in line 136; used 5 times

- in line 276-284(5)

rcsbaseid defined in line 99; never used
rcsid defined in line 5; never used
rev defined in line 129; used 5 times

- in line 156, 165-166(2), 274-276(2)

state defined in line 129; used 4 times

- in line 156, 223-224(2), 284

targetdelta defined in line 138; used 10 times

- in line 278-291(5), 299, 323, 346, 555, 589

tostdout defined in line 132; used 15 times

- in line 157, 191, 249, 256-259(2), 269, 304, 324, 351-353(2), 362-367(2), 571-572(2), 603

unlockflag defined in line 132; used 10 times

- in line 157, 176-186(4), 260-261(2), 278, 290, 301

workfilename defined in line 125; used 13 times

- in line 256-259(2), 324, 354-355(2), 363-364(2), 396, 405-411(3), 426-428(2)

Last modified: 1988-02-18 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1527 |