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

Defined functions

cleanup defined in line 675; never used
cmpnum defined in line 103; used 30 times
cmpnumfld defined in line 147; used 16 times
compartial defined in line 184; used 9 times
genbranch defined in line 423; used 2 times
getancestor defined in line 266; used 1 times
incnum defined in line 228; used 5 times
lookupsym defined in line 530; used 1 times
main defined in line 619; never used
partialno defined in line 246; used 14 times

Defined variables

rcsid defined in line 5; never used
Last modified: 1985-10-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2543
Valid CSS Valid XHTML 1.0 Strict