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

##### Functions

    cleanup           X
    cmpnum            X
    cmpnumfld         X
    compartial        X
    countnumflds      X
    expandsym         X
    genbranch         X
    genrevs           X
    getancestor       X
    getbranchno       X
    incnum            X
    lookupsym         X
    main              X
    partialno         X

       1: /*
       2:  *                     RCS revision number handling
       3:  */
       4: #ifndef lint
       5: static char rcsid[]= "$Id: rcsrev.c,v 4.3 87/10/18 10:38:42 narten Exp $ Purdue CS";
       6: #endif
       7: /*********************************************************************************
       8:  *********************************************************************************
       9:  *
      10:  * Copyright (C) 1982 by Walter F. Tichy
      11:  *                       Purdue University
      12:  *                       Computer Science Department
      13:  *                       West Lafayette, IN 47907
      14:  *
      15:  * All rights reserved. No part of this software may be sold or distributed
      16:  * in any form or by any means without the prior written permission of the
      17:  * author.
      18:  * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
      19:  */
      20:
      21:
      22: /* $Log:	rcsrev.c,v $
      23:  * Revision 4.3  87/10/18  10:38:42  narten
      24:  * Updating version numbers. Changes relative to version 1.1 actually
      25:  * relative to 4.1
      26:  *
      27:  * Revision 1.3  87/09/24  14:00:37  narten
      28:  * Sources now pass through lint (if you ignore printf/sprintf/fprintf
      29:  * warnings)
      30:  *
      31:  * Revision 1.2  87/03/27  14:22:37  jenkins
      32:  * Port to suns
      33:  *
      34:  * Revision 1.1  84/01/23  14:50:37  kcs
      35:  * Initial revision
      36:  *
      37:  * Revision 4.1  83/03/25  21:10:45  wft
      38:  * Only changed $Header to $Id.
      39:  *
      40:  * Revision 3.4  82/12/04  13:24:08  wft
      41:  * Replaced getdelta() with gettree().
      42:  *
      43:  * Revision 3.3  82/11/28  21:33:15  wft
      44:  * fixed compartial() and compnum() for nil-parameters; fixed nils
      45:  * in error messages. Testprogram output shortenend.
      46:  *
      47:  * Revision 3.2  82/10/18  21:19:47  wft
      48:  * renamed compnum->cmpnum, compnumfld->cmpnumfld,
      49:  * numericrevno->numricrevno.
      50:  *
      51:  * Revision 3.1  82/10/11  19:46:09  wft
      52:  * changed expandsym() to check for source==nil; returns zero length string
      53:  * in that case.
      54:  */
      55:
      56:
      57:
      58: /*
      59: #define REVTEST
      60: /* version REVTEST is for testing the routines that generate a sequence
      61:  * of delta numbers needed to regenerate a given delta.
      62:  */
      63:
      64: #include "rcsbase.h"
      65:
      66: extern FILE * finptr;   /* RCS input file */
      67: extern char * getid();
      68: extern struct hshentry * getnum();
      69: extern int    getkey();
      70: extern int    getlex();
      71:
      72: extern char * getkeyval();
      73: extern int delta(), deltatext();
      74: struct hshentry * genbranch(); /* forward */
      75:
      76:
      77:
      78: int countnumflds(s)
      79: char * s;
      80: /* Given a pointer s to a dotted number (date or revision number),
      81:  * countnumflds returns the number of digitfields in s.
      82:  */
      83: {       register char * sp;
      84:         register int    count;
      85:         if ((sp=s)==nil) return(0);
      86:         if (*sp == '\0') return(0);
      87:         count = 1;
      88:         while (*sp) {
      89:                 if (*sp++ == '.') count++;
      90:         }
      91:         if (*(--sp) == '.') count--; /*trailing periods don't count*/
      92:         return(count);
      93: }
      94:
      95: getbranchno(revno,branchno)
      96: char * revno, * branchno;
      97: /* Given a non-nil revision number revno, getbranchno copies the number of the branch
      98:  * on which revno is into branchnumber. If revno itself is a branch number,
      99:  * it is copied unchanged.
     100:  */
     101: {
     102:         register int i, numflds;
     103:         register char * tp, * sp;
     104:
     105:         numflds=countnumflds(revno);
     106:         if (numflds%2 == 1)
     107:                 VOID strcpy(branchno,revno);
     108:         else {
     109:                 sp=revno; tp=branchno;
     110:                 for (i=1;i<numflds;i++) {
     111:                         while(*sp!='.') *tp++ = *sp++;
     112:                         *tp++ = *sp++;
     113:                 }
     114:                 *(tp-1)='\0';
     115:         }
     116: }
     117:
     118:
     119:
     120: int cmpnum(num1, num2)
     121: char * num1, * num2;
     122: /* compares the two dotted numbers num1 and num2 lexicographically
     123:  * by field. Individual fields are compared numerically.
     124:  * returns <0, 0, >0 if num1<num2, num1==num2, and num1>num2, resp.
     125:  * omitted fields are assumed to be higher than the existing ones.
     126: */
     127: {
     128:         register char * s1, *s2;
     129:         register int n1, n2;
     130:
     131:         s1=num1==nil?"":num1;
     132:         s2=num2==nil?"":num2;
     133:
     134:         do {
     135:                 n1 = 0;
     136:                 while (('0' <= *s1) && (*s1 <= '9')) {
     137:                         n1 = n1*10 + (*s1 - '0');
     138:                         s1++;
     139:                 }
     140:                 /* skip '.' */
     141:                 if (*s1=='.') s1++;
     142:
     143:                 n2 = 0;
     144:                 while (('0' <= *s2) && (*s2 <= '9')) {
     145:                         n2 = n2*10 + (*s2 - '0');
     146:                         s2++;
     147:                 }
     148:                 /* skip '.' */
     149:                 if (*s2=='.') s2++;
     150:
     151:         } while ((n1==n2) && (*s1!='\0') && (*s2!='\0'));
     152:
     153:         if (((*s1=='\0') && (*s2=='\0')) || (n1!=n2))
     154:                 return (n1 - n2);
     155:         /*now n1==n2 and one of s1 or s2 is shorter*/
     156:         /*give precedence to shorter one*/
     157:         if (*s1=='\0') return 1;
     158:         else           return -1;
     159:
     160: }
     161:
     162:
     163:
     164: int cmpnumfld(num1, num2, fld)
     165: char * num1, * num2; int fld;
     166: /* compares the two dotted numbers at field fld and returns
     167:  * num1[fld]-num2[fld]. Assumes that num1 and num2 have at least fld fields.
     168: */
     169: {
     170:         register char * s1, *s2;
     171:         register int n1, n2;
     172:
     173:         s1=num1; n1=fld-1;
     174:         /* skip fld-1 fields */
     175:         while (n1) {
     176:                 while(*s1 != '.') s1++;
     177:                 n1--; s1++;
     178:         }
     179:         s2 = num2; n2=fld-1;
     180:         while (n2) {
     181:                 while(*s2 != '.') s2++;
     182:                 n2--; s2++;
     183:         }
     184:         /* Don't put the above into a single loop! */
     185:         /* Now s1 and s2 point to the beginning of the respective fields */
     186:         /* compute numerical value and compare */
     187:         n1 = 0;
     188:         while (('0' <= *s1) && (*s1 <= '9')) {
     189:                 n1 = n1*10 + (*s1 - '0');
     190:                 s1++;
     191:         }
     192:         n2 = 0;
     193:         while (('0' <= *s2) && (*s2 <= '9')) {
     194:                 n2 = n2*10 + (*s2 - '0');
     195:                 s2++;
     196:         }
     197:         return (n1 - n2);
     198: }
     199:
     200:
     201: int compartial(num1, num2, length)
     202: char    * num1;
     203: char    * num2;
     204: int     length;
     205:
     206: /*   compare the first "length" fields of two dot numbers;
     207:      the omitted field is considered to be larger than any number  */
     208: /*   restriction:  at least one number has length or more fields   */
     209:
     210: {
     211:         register        char    *s1, *s2;
     212:         register        int     n1, n2;
     213:
     214:
     215:         s1 = num1;      s2 = num2;
     216:         if ( s1==nil || *s1 == '\0' ) return 1;
     217:         if ( s2==nil || *s2 == '\0' ) return -1;
     218:
     219:         do {
     220:             n1 = 0;
     221:             while( ('0' <= *s1) && (*s1 <= '9') ) {
     222:                 n1 = n1 * 10 + (*s1 - '0') ;
     223:                 s1++;
     224:             }
     225:             if ( *s1 == '.' ) s1++;    /*  skip .   */
     226:
     227:             n2 = 0;
     228:             while( ( '0' <= *s2) && ( *s2 <= '9' ) ) {
     229:                    n2 = n2 * 10 + ( *s2 - '0' ) ;
     230:                 s2++;
     231:             }
     232:             if (*s2 == '.') s2++;
     233:         }   while(  ( n1 == n2) && ((--length) != 0) &&
     234:                     ( *s1 != '\0') && (*s2 != '\0')  );
     235:
     236:         if ( (n1 != n2) || (length == 0) ){
     237:                 return(n1-n2);   }
     238:
     239:         if ( *s1 == '\0' ) return 1;
     240:         if ( *s2 == '\0' ) return -1;
     241:     fprintf(stderr, "RCS Internal error, routine: compartial\n");
     242:     return(0);
     243: /*NOTREACHED*/
     244: }
     245:
     246:
     247:
     248: incnum(onum,nnum)
     249: char * onum, *nnum;
     250: /* increments the last field of revision number onum by one and
     251:  * places the result into nnum
     252:  */
     253: {
     254:         register char * sp, *tp;
     255:         register int i;
     256:
     257:         sp = onum; tp = nnum;
     258:         for (i=countnumflds(onum)-1; i>0; i--) {
     259:                 while (*sp != '.') *tp++ = *sp++;
     260:                 *tp++ = *sp++;  /* copy dot also */
     261:         }
     262:         VOID sprintf(tp,"%d",atoi(sp)+1);
     263: }
     264:
     265:
     266: char * partialno(rev1,rev2,length)
     267: char * rev1, * rev2; register int length;
     268: /* Function: Copies length fields of revision number rev2 into rev1.
     269:  * returns rev1.
     270:  */
     271: {       register char * r1,* r2;
     272:
     273:         r1=rev1; r2=rev2;
     274:         while (length) {
     275:                 while(*r2 != '.' && *r2!='\0') *r1++ = *r2++;
     276:                 *r1++ = *r2++;
     277:                 length--;
     278:         }
     279:         /* eliminate last '.'*/
     280:         *(r1-1)='\0';
     281:         return rev1;
     282: }
     283:
     284:
     285:
     286: char * getancestor(r1, r2, r3)
     287: char * r1, *r2, *r3;
     288: /* function: finds the common ancestor of r1 and r2 and
     289:  * places it into r3.
     290:  * returns r3 if successful, false otherwise.
     291:  * works reliably only if r1 and r2 are not branch numbers.
     292:  */
     293: {       int l1, l2, l3;
     294:         char t1[revlength], t2[revlength];
     295:
     296:         l1=countnumflds(r1); l2=countnumflds(r2);
     297:         if ((l1<=2 && l2<=2)||(cmpnum(r1,r2)==0)) {
     298:                 /* on main trunk or identical */
     299:                 error("Common ancestor of %s and %s undefined.", r1, r2);
     300:                 return false;
     301:         }
     302:
     303:         l3=0;
     304:         while ((cmpnumfld(r1, r2, l3+1)==0) && (cmpnumfld(r1, r2, l3+2)==0)){
     305:                 l3=l3+2;
     306:         }
     307:         /* This will terminate since r1 and r2 are not the same; see above*/
     308:         if (l3==0) {
     309:                 /* no common prefix. Common ancestor on main trunk. */
     310:                 VOID partialno(t1,r1,l1>2?2:l1); VOID partialno(t2,r2,l2>2?2:l2);
     311:                 if (cmpnum(t1,t2)<0)
     312:                         VOID strcpy(r3,t1);
     313:                 else    VOID strcpy(r3,t2);
     314:                 if ((cmpnum(r3,r1)==0)||(cmpnum(r3,r2)==0)) {
     315:                         error("Ancestor for %s and %s undefined.",r1,r2);
     316:                         return false;
     317:                 }
     318:                 return r3;
     319:         } else {
     320:                if (cmpnumfld(r1,r2,l3+1)==0) {
     321:                         error("Ancestor for %s and %s undefined.",r1,r2);
     322:                         return false;
     323:                 }
     324:                 return(partialno(r3,r1,l3));
     325:         }
     326: }
     327:
     328:
     329:
     330:
     331: struct hshentry * genrevs(revno,date,author,state,store)
     332: char * revno, * date, * author, * state;
     333: struct hshentry * * store;
     334: /* Function: finds the deltas needed for reconstructing the
     335:  * revision given by revno, date, author, and state, and stores pointers
     336:  * to these deltas into an array whose starting address is given by store.
     337:  * The last pointer stored is nil. The last delta (target delta) is returned.
     338:  * If the proper delta could not be found, nil is returned.
     339:  */
     340: {
     341:         int length;
     342:         register struct hshentry * next;
     343:         int result;
     344:         char * branchnum;
     345:         char t[revlength];
     346:
     347:         if (Head == nil) {
     348:                 error("RCSfile empty.");
     349:                 return nil;
     350:         }
     351:
     352:         length = countnumflds(revno);
     353:         next=Head;
     354:
     355:         if (length >= 1) {
     356:                 /* at least one field; find branch exactly */
     357:                 while ((next!=nil) &&
     358:                        ((result=cmpnumfld(revno,next->num,1))<0)) {
     359:                         /*puts(next->num);*/
     360:                         *store++ = next;
     361:                         next = next->next;
     362:                 }
     363:
     364:                 if (next==nil) {error("Branch number %s too low.",partialno(t,revno,1));return nil;}
     365:                 if (result>0)  {error("Branch number %s not present.",partialno(t,revno,1));return nil;}
     366:         }
     367:         if (length<=1){
     368:                 /* pick latest one on given branch */
     369:                 branchnum = next->num; /* works even for empty revno*/
     370:                 while ((next!=nil) &&
     371:                        (cmpnumfld(branchnum,next->num,1)==0) &&
     372:                        !(
     373:                         (date==nil?1:(cmpnum(date,next->date)>=0)) &&
     374:                         (author==nil?1:(strcmp(author,next->author)==0)) &&
     375:                         (state ==nil?1:(strcmp(state, next->state) ==0))
     376:                         )
     377:                        )
     378:                 {       /*puts(next->num);*/
     379:                         *store ++ = next;
     380:                         next=next->next;
     381:                 }
     382:                 if ((next==nil) ||
     383:                     (cmpnumfld(branchnum,next->num,1)!=0))/*overshot*/ {
     384:                         error("Cannot find revision on branch %s with a date before %s, author %s, and state %s.",
     385:                                 length==0?partialno(t,branchnum,1):revno,date==nil?"<now>":date,
     386:                                 author==nil?"<any>":author, state==nil?"<any>":state);
     387:                         return nil;
     388:                 } else {
     389:                         /*puts(next->num);*/
     390:                         *store++ = next;
     391:                 }
     392:                 *store = nil;
     393:                 return next;
     394:         }
     395:
     396:         /* length >=2 */
     397:         /* find revision; may go low if length==2*/
     398:         while ((next!=nil) &&
     399:                ((result =cmpnumfld(revno,next->num,2)) <0) &&
     400:                (cmpnumfld(revno,next->num,1)==0) ) {
     401:                 /*puts(next->num);*/
     402:                 *store++ = next;
     403:                 next = next->next;
     404:         }
     405:
     406:         if ((next==nil) || (cmpnumfld(revno,next->num,1)!=0)) {
     407:                 error("Revision number %s too low.",partialno(t,revno,2));
     408:                 return nil;
     409:         }
     410:         if ((length>2) && (result!=0)) {
     411:                 error("Revision %s not present.",partialno(t,revno,2));
     412:                 return nil;
     413:         }
     414:
     415:         /* print last one */
     416:         /*puts(next->num);*/
     417:         *store++ = next;
     418:
     419:         if (length>2)
     420:                 return genbranch(next,revno,length,date,author,state,store);
     421:         else { /* length == 2*/
     422:                 if ((date!=nil) && (cmpnum(date,next->date)<0)){
     423:                         error("Revision %s has date %s.",next->num, next->date);
     424:                         return nil;
     425:                 }
     426:                 if ((author!=nil)&&(strcmp(author,next->author)!=0)) {
     427:                         error("Revision %s has author %s.",next->num,next->author);
     428:                         return nil;
     429:                 }
     430:                 if ((state!=nil)&&(strcmp(state,next->state)!=0)) {
     431:                         error("Revision %s has state %s.",next->num,
     432:                                next->state==nil?"<empty>":next->state);
     433:                         return nil;
     434:                 }
     435:                 *store=nil;
     436:                 return next;
     437:         }
     438: }
     439:
     440:
     441:
     442:
     443: struct hshentry * genbranch(bpoint, revno, length,date,author,state,store)
     444: struct hshentry * bpoint;
     445: char * revno; int length;
     446: char * date, * author, * state;
     447: struct hshentry ** store;
     448: /* Function: given a branchpoint, a revision number, date, author, and state,
     449:  * genbranch finds the deltas necessary to reconstruct the given revision
     450:  * from the branch point on.
     451:  * Pointers to the found deltas are stored in an array beginning with store.
     452:  * revno must be on a side branch.
     453:  * return nil on error
     454:  */
     455: {
     456:         int field;
     457:         register struct hshentry * next, * trail;
     458:         register struct branchhead * bhead;
     459:         int result;
     460:         char t[revlength];
     461:
     462:         bhead = bpoint->branches;
     463:
     464:         for (field=3; field<=length; field=field+2) {
     465:
     466:                 if (bhead==nil) {error("No side branches present for %s.",partialno(t,revno,field-1));return nil;}
     467:
     468:                 /*find branch head*/
     469:                 /*branches are arranged in increasing order*/
     470:                 while ((bhead!=nil) &&
     471:                        ((result=cmpnumfld(revno,bhead->hsh->num,field))>0)) {
     472:                         bhead = bhead->nextbranch;
     473:                 }
     474:
     475:                 if (bhead==nil) {error("Branch number %s too high.",partialno(t,revno,field));return nil;}
     476:                 if (result<0)   {error("Branch number %s not present.",partialno(t,revno,field));return nil;}
     477:
     478:                 next = bhead->hsh;
     479:                 if (length==field) {
     480:                         /* pick latest one on that branch */
     481:                         trail=nil;
     482:                         do { if ((date==nil?1:(cmpnum(date,next->date)>=0)) &&
     483:                                  (author==nil?1:(strcmp(author,next->author)==0)) &&
     484:                                  (state ==nil?1:(strcmp(state, next->state) ==0))
     485:                              ) trail = next;
     486:                              next=next->next;
     487:                         } while (next!=nil);
     488:
     489:                         if (trail==nil) {
     490:                              error("Cannot find revision on branch %s with a date before %s, author %s, and state %s.",
     491:                                         revno, date==nil?"<now>":date,
     492:                                         author==nil?"<any>":author, state==nil?"<any>":state);
     493:                              return nil;
     494:                         } else { /* print up to last one suitable */
     495:                              next = bhead->hsh;
     496:                              while (next!=trail) {
     497:                                   /*puts(next->num);*/
     498:                                   *store++ = next;
     499:                                   next=next->next;
     500:                              }
     501:                              /*puts(next->num);*/
     502:                              *store++ = next;
     503:                         }
     504:                         *store = nil;
     505:                         return next;
     506:                 }
     507:
     508:                 /* length > field */
     509:                 /* find revision */
     510:                 /* check low */
     511:                 if (cmpnumfld(revno,next->num,field+1)<0) {
     512:                         error("Revision number %s too low.",partialno(t,revno,field+1));
     513:                         return(nil);
     514:                 }
     515:                 do {    /*puts(next->num);*/
     516:                         *store++ = next;
     517:                         trail = next;
     518:                         next = next->next;
     519:                 } while ((next!=nil) &&
     520:                        (cmpnumfld(revno,next->num,field+1) >=0));
     521:
     522:                 if ((length>field+1) &&  /*need exact hit */
     523:                     (cmpnumfld(revno,trail->num,field+1) !=0)){
     524:                         error("Revision %s not present.",partialno(t,revno,field+1));
     525:                         return(nil);
     526:                 }
     527:                 if (length == field+1) {
     528:                         if ((date!=nil) && (cmpnum(date,trail->date)<0)){
     529:                                 error("Revision %s has date %s.",trail->num, trail->date);
     530:                                 return nil;
     531:                         }
     532:                         if ((author!=nil)&&(strcmp(author,trail->author)!=0)) {
     533:                                 error("Revision %s has author %s.",trail->num,trail->author);
     534:                                 return nil;
     535:                         }
     536:                         if ((state!=nil)&&(strcmp(state,trail->state)!=0)) {
     537:                                 error("Revision %s has state %s.",trail->num,
     538:                                        trail->state==nil?"<empty>":trail->state);
     539:                                 return nil;
     540:                         }
     541:                 }
     542:                 bhead = trail->branches;
     543:
     544:         }
     545:         * store = nil;
     546:         return trail;
     547: }
     548:
     549:
     550: char * lookupsym(id)
     551: char * id;
     552: /* Function: looks up id in the list of symbolic names starting
     553:  * with pointer SYMBOLS, and returns a pointer to the corresponding
     554:  * revision number. Returns nil if not present.
     555:  */
     556: {
     557:         register struct assoc * next;
     558:         next = Symbols;
     559:         while (next!=nil) {
     560:                 if (strcmp(id, next->symbol)==0)
     561:                         return(next->delta->num);
     562:                 else    next=next->nextassoc;
     563:         }
     564:         return nil;
     565: }
     566:
     567: int expandsym(source, target)
     568: char * source, * target;
     569: /* Function: Source points to a revision number. Expandsym copies
     570:  * the number to target, but replaces all symbolic fields in the
     571:  * source number with their numeric values.
     572:  * A trailing '.' is omitted; leading zeroes are compressed.
     573:  * returns false on error;
     574:  */
     575: {       register char * sp, * tp, *bp;
     576:         char symbuf[30];
     577:         register enum tokens d;
     578:
     579:         sp = source; tp=target;
     580:         if (sp == nil) { /*accept nil pointer as a legal value*/
     581:                 *tp='\0';
     582:                 return true;
     583:         }
     584:
     585:         while (*sp != '\0') {
     586:                 if (ctab[*sp] == DIGIT) {
     587:                         if (*sp=='0') {
     588:                                 /* skip leading zeroes */
     589:                                 sp++;
     590:                                 while(*sp == '0') sp++;
     591:                                 if (*sp=='\0' || *sp=='.') *tp++ = '0'; /*single zero*/
     592:                         }
     593:                         while(ctab[*sp] == DIGIT) *tp++ = *sp++;
     594:                         if ((*sp == '\0') || ((*sp=='.')&&(*(sp+1)=='\0'))) {
     595:                                 *tp='\0'; return true;
     596:                         }
     597:                         if (*sp == '.') *tp++ = *sp++;
     598:                         else {
     599:                             error("Improper revision number: %s",source);
     600:                             *tp = '\0';
     601:                             return false;
     602:                         }
     603:                 } elsif (ctab[*sp] == LETTER) {
     604:                         bp = symbuf;
     605:                         do {    *bp++ = *sp++;
     606:                         } while(((d=ctab[*sp])==LETTER) || (d==DIGIT) ||
     607:                               (d==IDCHAR));
     608:                         *bp= '\0';
     609:                         bp=lookupsym(symbuf);
     610:                         if (bp==nil) {
     611:                                 error("Symbolic number %s is undefined.",symbuf);
     612:                                 *tp='\0';
     613:                                 return false;
     614:                         } else { /* copy number */
     615:                                 while (*tp++ = *bp++); /* copies the trailing \0*/
     616:                         }
     617:                         if ((*sp == '\0') || ((*sp=='.')&&(*(sp+1)=='\0')))
     618:                                 return true;
     619:                         if (*sp == '.')  {
     620:                                 *(tp-1) = *sp++;
     621:                         } else {
     622:                                 error("Improper revision number: %s",source);
     623:                                 return false;
     624:                         }
     625:                 }else {
     626:                         error("Improper revision number: %s", source);
     627:                         *tp = '\0';
     628:                         return false;
     629:                 }
     630:         }
     631:         *tp = '\0';
     632:         return true;
     633: }
     634:
     635:
     636:
     637: #ifdef REVTEST
     638:
     639: main(argc,argv)
     640: int argc; char * argv[];
     641: {
     642:         char symrevno[revlength];       /* used for input of revision numbers */
     643:         char numricrevno[revlength];
     644:         char author[20];
     645:         char state[20];
     646:         char date[20];
     647:         struct hshentry * gendeltas[hshsize/2];
     648:         struct hshentry * target;
     649:         int i;
     650:
     651:         cmdid = "revtest";
     652:         if (argc<2) {
     653:                 VOID fputs("No input file\n",stderr);
     654:                 exit(-1);
     655:         }
     656:         if ((finptr=fopen(argv[1], "r")) == NULL) {
     657:                 faterror("Can't open input file %s\n",argv[1]);
     658:         }
     659:         Lexinit();
     660:         getadmin();
     661:
     662:         gettree();
     663:
     664:         getdesc(false);
     665:
     666:         do {
     667:                 /* all output goes to stderr, to have diagnostics and       */
     668:                 /* errors in sequence.                                      */
     669:                 VOID fprintf(stderr,"\nEnter revision number or <return> or '.': ");
     670:                 if(gets(symrevno)==NULL) break;
     671:                 if (*symrevno == '.') break;
     672:                 VOID fprintf(stderr,"%s;\n",symrevno);
     673:                 expandsym(symrevno,numricrevno);
     674:                 VOID fprintf(stderr,"expanded number: %s; ",numricrevno);
     675:                 VOID fprintf(stderr,"Date: ");
     676:                 gets(date); VOID fprintf(stderr,"%s; ",date);
     677:                 VOID fprintf(stderr,"Author: ");
     678:                 gets(author);VOID fprintf(stderr,"%s; ",author);
     679:                 VOID fprintf(stderr,"State: ");
     680:                 gets(state); VOID fprintf(stderr, "%s;\n", state);
     681:                 target=genrevs(numricrevno,*date=='\0'?(char *)nil:date, *author=='\0'?(char *)nil:author,
     682:                               *state=='\0'?(char *)nil:state,gendeltas);
     683:                 if (target!=nil) {
     684:                         i=0;
     685:                         while (gendeltas[i]!=nil) {
     686:                                 VOID fprintf(stderr,"%s\n",gendeltas[i++]->num);
     687:                         }
     688:                 }
     689:         } while (true);
     690:         VOID fprintf(stderr,"done\n");
     691:
     692: }
     693:
     694: cleanup(){}
     695: /*dummy*/
     696:
     697: #endif REVTEST

#### Defined functions

cleanup defined in line 694; never used
cmpnum defined in line 120; used 30 times

- in line 297, 311-314(3), 373, 422, 482, 528
- in /usr/src/new/rcs/src/ci.c line 415, 609, 630, 700, 879(2)
- in /usr/src/new/rcs/src/rcs.c line 1153, 1239-1240(2), 1249, 1261, 1267-1272(2), 1364, 1408, 1430
- in /usr/src/new/rcs/src/rcsutil.c line 160
- in /usr/src/new/rcs/src/rlog.c line 734-735(2), 766-767(2), 775

cmpnumfld defined in line 164; used 16 times

- in line 304(2), 320, 358, 371, 383, 399-400(2), 406, 471, 511, 520-523(2)
- in /usr/src/new/rcs/src/ci.c line 605, 683
- in /usr/src/new/rcs/src/rcs.c line 1187

compartial defined in line 201; used 9 times

- in /usr/src/new/rcs/src/rcs.c line 1083, 1230
- in /usr/src/new/rcs/src/rlog.c line 93, 844-850(4), 1035, 1087

countnumflds defined in line 78; used 33 times

- in line 105, 258, 296(2), 352
- in /usr/src/new/rcs/src/ci.c line 541, 547, 573, 596, 656, 664
- in /usr/src/new/rcs/src/rcs.c line 464, 1154, 1226, 1364, 1408, 1430
- in /usr/src/new/rcs/src/rcssyn.c line 160, 224, 264, 280, 297
- in /usr/src/new/rcs/src/rcsutil.c line 353
- in /usr/src/new/rcs/src/rlog.c line 92, 843-848(2), 995, 1002, 1014, 1030, 1065, 1082(2)

expandsym defined in line 567; used 24 times

- in line 673
- in /usr/src/new/rcs/src/ci.c line 382
- in /usr/src/new/rcs/src/co.c line 276, 528, 539
- in /usr/src/new/rcs/src/rcs.c line 116, 463, 1150, 1225, 1318, 1361, 1404, 1426
- in /usr/src/new/rcs/src/rcsclean.c line 124
- in /usr/src/new/rcs/src/rcsdiff.c line 196-201(2)
- in /usr/src/new/rcs/src/rcsmerge.c line 125-130(2)
- in /usr/src/new/rcs/src/rlog.c line 94, 994, 1001, 1011, 1026-1029(2)

genbranch defined in line 443; used 2 times

- in line 74, 420

genrevs defined in line 331; used 28 times

- in line 681
- in /usr/src/new/rcs/src/ci.c line 120, 567, 615, 628, 697
- in /usr/src/new/rcs/src/co.c line 106, 284, 529, 540
- in /usr/src/new/rcs/src/rcs.c line 127, 520, 1151, 1214, 1235, 1362, 1405, 1427
- in /usr/src/new/rcs/src/rcsclean.c line 45, 125
- in /usr/src/new/rcs/src/rcsdiff.c line 80, 197-202(2)
- in /usr/src/new/rcs/src/rcsgen.c line 85
- in /usr/src/new/rcs/src/rcsmerge.c line 59, 126-131(2)
- in /usr/src/new/rcs/src/rlog.c line 91

getancestor defined in line 286; used 2 times

- in /usr/src/new/rcs/src/co.c line 107, 555

getbranchno defined in line 95; used 4 times

- in /usr/src/new/rcs/src/ci.c line 673, 696
- in /usr/src/new/rcs/src/rcs.c line 1213
- in /usr/src/new/rcs/src/rlog.c line 470

incnum defined in line 248; used 6 times

- in /usr/src/new/rcs/src/ci.c line 572-577(2), 594, 606, 674, 706

lookupsym defined in line 550; used 1 times

- in line 609

main defined in line 639; never used
partialno defined in line 266; used 15 times

- in line 310(2), 324, 364-365(2), 385, 407-411(2), 466, 475-476(2), 512, 524
- in /usr/src/new/rcs/src/rlog.c line 86, 1060

#### Defined variables

rcsid defined in line 5; never used

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