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