|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.