|
|
1.1 ! root 1: /* ! 2: * RLOG operation ! 3: */ ! 4: #ifndef lint ! 5: static char rcsid[]= ! 6: "$Header: /usr/src/local/bin/rcs/src/RCS/rlog.c,v 4.7 89/05/01 15:13:48 narten Exp $ Purdue CS"; ! 7: #endif ! 8: /***************************************************************************** ! 9: * print contents of RCS files ! 10: ***************************************************************************** ! 11: */ ! 12: ! 13: /* Copyright (C) 1982, 1988, 1989 Walter Tichy ! 14: * All rights reserved. ! 15: * ! 16: * Redistribution and use in source and binary forms are permitted ! 17: * provided that the above copyright notice and this paragraph are ! 18: * duplicated in all such forms and that any documentation, ! 19: * advertising materials, and other materials related to such ! 20: * distribution and use acknowledge that the software was developed ! 21: * by Walter Tichy. ! 22: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 23: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 24: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 25: * ! 26: * Report all problems and direct all questions to: ! 27: * [email protected] ! 28: * ! 29: ! 30: ! 31: ! 32: ! 33: ! 34: ! 35: ! 36: */ ! 37: ! 38: ! 39: ! 40: ! 41: /* $Log: rlog.c,v $ ! 42: * Revision 4.7 89/05/01 15:13:48 narten ! 43: * changed copyright header to reflect current distribution rules ! 44: * ! 45: * Revision 4.6 88/11/08 11:59:40 narten ! 46: * changes from [email protected] (Paul Eggert) ! 47: * ! 48: * Revision 4.6 88/08/09 19:13:28 eggert ! 49: * Check for memory exhaustion; don't access freed storage. ! 50: * Shrink stdio code size; remove lint. ! 51: * ! 52: * Revision 4.5 87/12/18 11:46:38 narten ! 53: * more lint cleanups (Guy Harris) ! 54: * ! 55: * Revision 4.4 87/10/18 10:41:12 narten ! 56: * Updating version numbers ! 57: * Changes relative to 1.1 actually relative to 4.2 ! 58: * ! 59: * Revision 1.3 87/09/24 14:01:10 narten ! 60: * Sources now pass through lint (if you ignore printf/sprintf/fprintf ! 61: * warnings) ! 62: * ! 63: * Revision 1.2 87/03/27 14:22:45 jenkins ! 64: * Port to suns ! 65: * ! 66: * Revision 1.1 84/01/23 14:50:45 kcs ! 67: * Initial revision ! 68: * ! 69: * Revision 4.2 83/12/05 09:18:09 wft ! 70: * changed rewriteflag to external. ! 71: * ! 72: * Revision 4.1 83/05/11 16:16:55 wft ! 73: * Added -b, updated getnumericrev() accordingly. ! 74: * Replaced getpwuid() with getcaller(). ! 75: * ! 76: * Revision 3.7 83/05/11 14:24:13 wft ! 77: * Added options -L and -R; ! 78: * Fixed selection bug with -l on multiple files. ! 79: * Fixed error on dates of the form -d'>date' (rewrote getdatepair()). ! 80: * ! 81: * Revision 3.6 82/12/24 15:57:53 wft ! 82: * shortened output format. ! 83: * ! 84: * Revision 3.5 82/12/08 21:45:26 wft ! 85: * removed call to checkaccesslist(); used DATEFORM to format all dates; ! 86: * removed unused variables. ! 87: * ! 88: * Revision 3.4 82/12/04 13:26:25 wft ! 89: * Replaced getdelta() with gettree(); removed updating of field lockedby. ! 90: * ! 91: * Revision 3.3 82/12/03 14:08:20 wft ! 92: * Replaced getlogin with getpwuid(), %02d with %.2d, fancydate with PRINTDATE. ! 93: * Fixed printing of nil, removed printing of Suffix, ! 94: * added shortcut if no revisions are printed, disambiguated struct members. ! 95: * ! 96: * Revision 3.2 82/10/18 21:09:06 wft ! 97: * call to curdir replaced with getfullRCSname(), ! 98: * fixed call to getlogin(), cosmetic changes on output, ! 99: * changed conflicting long identifiers. ! 100: * ! 101: * Revision 3.1 82/10/13 16:07:56 wft ! 102: * fixed type of variables receiving from getc() (char -> int). ! 103: */ ! 104: ! 105: ! 106: ! 107: #include "time.h" ! 108: #include "rcsbase.h" ! 109: #ifndef lint ! 110: static char rcsbaseid[] = RCSBASE; ! 111: #endif ! 112: ! 113: extern char * partialno(); ! 114: extern char * getcaller(); /*get login of caller */ ! 115: extern free(); ! 116: extern int countnumflds(); ! 117: extern int compartial(); ! 118: extern int expandsym(); /*get numeric name of a revision */ ! 119: extern int nextc; /*next input character */ ! 120: extern char Klog[]; ! 121: extern char Ktext[]; ! 122: extern int partime(); ! 123: extern long maketime(); /*convert parsed time to unix time. */ ! 124: extern struct tm * localtime(); /*convert unixtime into a tm-structure */ ! 125: extern int pairfilenames(); ! 126: extern struct hshentry * getnum(); ! 127: extern FILE * finptr; /* RCS input file */ ! 128: extern FILE * frewrite; /* new RCS file */ ! 129: extern int rewriteflag; /* indicates whether input should be */ ! 130: /* echoed to frewrite */ ! 131: extern int nerror; /* error counter */ ! 132: ! 133: char * RCSfilename, * workfilename; ! 134: ! 135: char * caller; /* caller's login; */ ! 136: int descflag, selectflag, selectop; /* option to print access list, symbolic */ ! 137: /* names, descriptive text, locks and */ ! 138: /* Head */ ! 139: int onlylockflag; /* option to print only files */ ! 140: /* with locks */ ! 141: int onlyRCSflag; /* option to print only RCS file name */ ! 142: int lockflag; /* whether locker option is set */ ! 143: int revno; /* number of revision chosen */ ! 144: ! 145: struct lockers { /* lockers in locker option; stored */ ! 146: char * login; /* lockerlist */ ! 147: struct lockers * lockerlink; ! 148: } ; ! 149: ! 150: struct stateattri { /* states in state option; stored in */ ! 151: char * status; /* statelist */ ! 152: struct stateattri * nextstate; ! 153: } ; ! 154: ! 155: struct authors { /* login names in author option; */ ! 156: char * login; /* stored in authorlist */ ! 157: struct authors * nextauthor; ! 158: } ; ! 159: ! 160: struct Revpairs{ /* revision or branch range in -r */ ! 161: int numfld; /* option; stored in revlist */ ! 162: char * strtrev; ! 163: char * endrev; ! 164: struct Revpairs * rnext; ! 165: } ; ! 166: ! 167: struct Datepairs{ /* date range in -d option; stored in */ ! 168: char strtdate[datelength]; /* duelst and datelist */ ! 169: char enddate[datelength]; ! 170: struct Datepairs * dnext; ! 171: }; ! 172: ! 173: char Dotstring[200]; /* string of numeric revision name */ ! 174: char * Nextdotstring; /* next available place of Dotstring */ ! 175: struct Datepairs * datelist, * duelst; ! 176: struct Revpairs * revlist, * Revlst; ! 177: int branchflag; /* set on -b */ ! 178: struct lockers * lockerlist; ! 179: struct stateattri * statelist; ! 180: struct authors * authorlist; ! 181: ! 182: ! 183: ! 184: main (argc, argv) ! 185: int argc; ! 186: char * argv[]; ! 187: { ! 188: struct Datepairs * currdate; ! 189: struct assoc * curassoc; ! 190: struct access * curaccess; ! 191: struct lock * currlock; ! 192: char * cmdusage; ! 193: ! 194: cmdusage = "command format:\nrlog -L -R -h -t -b -ddates -l[lockers] -rrevisions -sstates -w[logins] file ..."; ! 195: cmdid = "rlog"; ! 196: descflag = selectflag = true; ! 197: lockflag = onlylockflag = selectop = false; ! 198: onlyRCSflag = false; ! 199: lockerlist = nil; ! 200: authorlist = nil; ! 201: statelist = nil; ! 202: Revlst = revlist = nil; ! 203: branchflag= false; ! 204: duelst = datelist = nil; ! 205: caller=getcaller(); ! 206: ! 207: while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) { ! 208: switch ((*argv)[1]) { ! 209: ! 210: case 'L': ! 211: onlylockflag = true; ! 212: break; ! 213: ! 214: case 'R': ! 215: onlyRCSflag =true; ! 216: break; ! 217: ! 218: case 'l': ! 219: selectop = true; ! 220: lockflag = true; ! 221: getlocker( (*argv)+2 ); ! 222: break; ! 223: ! 224: case 'b': ! 225: selectop = true; ! 226: branchflag = true; ! 227: break; ! 228: ! 229: case 'r': ! 230: selectop = true; ! 231: getrevpairs( (*argv)+2 ); ! 232: break; ! 233: ! 234: case 'd': ! 235: selectop = true; ! 236: getdatepair( (*argv)+2 ); ! 237: break; ! 238: ! 239: case 's': ! 240: selectop = true; ! 241: getstate( (*argv)+2); ! 242: break; ! 243: ! 244: case 'w': ! 245: selectop = true; ! 246: getauthor( (*argv)+2); ! 247: break; ! 248: ! 249: case 'h': ! 250: if ( ! selectflag ) warn("option -t overrides -h"); ! 251: else descflag = false; ! 252: break; ! 253: ! 254: case 't': ! 255: selectflag = false; ! 256: if ( ! descflag ) warn("option -t overrides -h"); ! 257: descflag = true; ! 258: break; ! 259: ! 260: default: ! 261: faterror("unknown option: %s\n%s", *argv,cmdusage); ! 262: ! 263: }; ! 264: } /* end of option processing */ ! 265: ! 266: if (argc<1) faterror("No input file\n%s",cmdusage); ! 267: ! 268: ! 269: /* now handle all filenames */ ! 270: do { ! 271: rewriteflag=false; ! 272: finptr=frewrite=nil; ! 273: ! 274: ! 275: if (!pairfilenames(argc, argv, true,false)) continue; ! 276: ! 277: /* now RCSfilename contains the name of the RCS file, and finptr ! 278: * the file descriptor. Workfilename contains the name of the ! 279: * working file. ! 280: */ ! 281: ! 282: if ( !trysema(RCSfilename, false)) goto loopend; /* give up */ ! 283: ! 284: /* do nothing if -L is given and there are no locks*/ ! 285: if ( onlylockflag && Locks == nil ) goto loopend; ! 286: ! 287: if ( onlyRCSflag ) { ! 288: VOID fprintf(stdout, "%s\n", RCSfilename); ! 289: goto loopend; ! 290: } ! 291: /* print RCS filename , working filename and optional ! 292: administrative information */ ! 293: VOID fprintf(stdout, "\nRCS file: %s; ",RCSfilename); ! 294: /* could use getfullRCSname() here, but that is very slow */ ! 295: VOID fprintf(stdout, "Working file: %s\n", workfilename); ! 296: VOID fprintf(stdout, "head: %s\n", Head==nil?"":Head->num); ! 297: VOID fprintf(stdout, "branch: %s\n", Dbranch==nil?"":Dbranch->num); ! 298: ! 299: VOID fputs("locks: ", stdout); /* print locker list */ ! 300: currlock = Locks; ! 301: while( currlock ) { ! 302: VOID fprintf(stdout," %s: %s;", currlock->login, ! 303: currlock->delta->num); ! 304: currlock = currlock->nextlock; ! 305: } ! 306: if ( StrictLocks ) ! 307: VOID fputs(Locks==nil?" ; strict":" strict",stdout); ! 308: ! 309: VOID fputs("\naccess list: ", stdout); /* print access list */ ! 310: curaccess = AccessList; ! 311: while(curaccess) { ! 312: VOID fputs(" ",stdout); ! 313: VOID fputs(curaccess->login, stdout); ! 314: curaccess = curaccess->nextaccess; ! 315: } ! 316: ! 317: VOID fputs("\nsymbolic names:", stdout); /* print symbolic names */ ! 318: curassoc = Symbols; ! 319: while( curassoc ) { ! 320: VOID fprintf(stdout, " %s: %s;",curassoc->symbol, ! 321: curassoc->delta->num); ! 322: curassoc = curassoc->nextassoc; ! 323: } ! 324: ! 325: VOID fprintf(stdout,"\ncomment leader: \"%s\"\n",Comment); ! 326: ! 327: gettree(); ! 328: VOID fprintf(stdout, "total revisions: %d; ", TotalDeltas); ! 329: if ( Head == nil || !selectflag || !descflag) { ! 330: VOID putc('\n',stdout); ! 331: if (descflag) VOID fputs("description:\n", stdout); ! 332: getdesc(descflag); ! 333: VOID fputs("=============================================================================\n",stdout); ! 334: goto loopend; ! 335: } ! 336: ! 337: ! 338: /* keep only those locks given by -l */ ! 339: if (lockflag) ! 340: trunclocks(); ! 341: getnumericrev(); /* get numeric revision or branch names */ ! 342: revno = 0; ! 343: ! 344: exttree(Head); ! 345: ! 346: /* get most recently date of the dates pointed by duelst */ ! 347: currdate = duelst; ! 348: while( currdate) { ! 349: recentdate(Head, currdate); ! 350: currdate = currdate->dnext; ! 351: } ! 352: ! 353: extdate(Head); ! 354: ! 355: /* reinitialize the date specification list */ ! 356: currdate = duelst; ! 357: while(currdate) { ! 358: VOID sprintf(currdate->strtdate,DATEFORM,0,0,0,0,0,0); ! 359: currdate = currdate->dnext; ! 360: } ! 361: ! 362: if ( selectop || ( selectflag && descflag) ) ! 363: VOID fprintf(stdout, "selected revisions: %d", revno); ! 364: VOID putc('\n', stdout); ! 365: if (descflag) VOID fputs("description:\n", stdout); ! 366: getdesc(descflag); ! 367: while( (nexttok != EOFILE) && readdeltalog()); ! 368: if (selectflag && descflag && revno) { ! 369: putrunk(); ! 370: putree(Head); ! 371: if (nextlex(), nexttok != EOFILE) ! 372: fatserror("syntax error; expecting EOF"); ! 373: } ! 374: VOID fputs("=============================================================================\n",stdout); ! 375: loopend: ! 376: VOID fclose(finptr); ! 377: } while( ++argv, --argc >= 1); ! 378: exit(nerror!=0); ! 379: } ! 380: ! 381: ! 382: ! 383: putrunk() ! 384: /* function: print revisions chosen, which are in trunk */ ! 385: ! 386: { ! 387: struct hshentry * ptr, * pre; ! 388: ! 389: if (Head == nil) return; /* empty tree */ ! 390: ! 391: pre = Head; ! 392: ptr = Head->next; ! 393: while( ptr ) { ! 394: putadelta(pre,ptr,true); ! 395: pre = ptr; ! 396: ptr = ptr->next; ! 397: } ! 398: putadelta(pre,ptr,true); ! 399: } ! 400: ! 401: ! 402: ! 403: putree(root) ! 404: struct hshentry *root; ! 405: /* function: print delta tree( not include trunck) in reversed calender ! 406: order on each branch */ ! 407: ! 408: { ! 409: if ( root == nil ) return; ! 410: ! 411: putree(root->next); ! 412: ! 413: putforest(root->branches); ! 414: } ! 415: ! 416: ! 417: ! 418: ! 419: putforest(branchroot) ! 420: struct branchhead * branchroot; ! 421: /* function: print branches that has the same direct ancestor */ ! 422: { ! 423: ! 424: if ( branchroot == nil ) return; ! 425: ! 426: putforest(branchroot->nextbranch); ! 427: ! 428: putabranch(branchroot->hsh); ! 429: putree(branchroot->hsh); ! 430: } ! 431: ! 432: ! 433: ! 434: ! 435: putabranch(root) ! 436: struct hshentry *root; ! 437: /* function : print one branch */ ! 438: ! 439: { ! 440: ! 441: if ( root == nil) return; ! 442: ! 443: putabranch(root->next); ! 444: ! 445: putadelta(root, root, false); ! 446: } ! 447: ! 448: ! 449: ! 450: ! 451: ! 452: putadelta(node,editscript,trunk) ! 453: register struct hshentry * node; ! 454: register struct hshentry * editscript; ! 455: int trunk; ! 456: /* function: print delta node if node->selector is 's'. */ ! 457: /* editscript indicates where the editscript is stored */ ! 458: /* trunk indicated whether this node is in trunk */ ! 459: { ! 460: struct branchhead * newbranch; ! 461: char * branchnum, branch[40]; ! 462: ! 463: if ( ( node == nil) || ( node->selector == 'u')) ! 464: return; ! 465: ! 466: VOID fprintf(stdout,"----------------------------\n"); ! 467: VOID fprintf(stdout, "revision %s ",node->num); ! 468: if ( node->lockedby ) ! 469: VOID fprintf(stdout, "locked by: %s; ", node->lockedby); ! 470: VOID putc('\n', stdout); ! 471: ! 472: VOID fputs("date: ",stdout); ! 473: VOID PRINTDATE(stdout,node->date); VOID putc(' ',stdout); ! 474: VOID PRINTTIME(stdout,node->date); ! 475: VOID fprintf(stdout, "; author: %s; ", node->author); ! 476: VOID fprintf(stdout, "state: %s; ", node->state); ! 477: ! 478: if ( editscript ) ! 479: if(trunk) ! 480: VOID fprintf(stdout,"lines added/del: %d/%d", ! 481: editscript->deletelns, editscript->insertlns); ! 482: else ! 483: VOID fprintf(stdout,"lines added/del: %d/%d", ! 484: editscript->insertlns, editscript->deletelns); ! 485: ! 486: VOID putc('\n', stdout); ! 487: ! 488: branchnum = & (branch[0]); ! 489: newbranch = node->branches; ! 490: if ( newbranch ) { ! 491: VOID fputs("branches: ", stdout); ! 492: while( newbranch ) { ! 493: getbranchno(newbranch->hsh->num, branchnum); ! 494: VOID fprintf(stdout, "%s; ", branchnum); ! 495: newbranch = newbranch->nextbranch; ! 496: } ! 497: VOID putc('\n', stdout); ! 498: } ! 499: ! 500: VOID fputs(node->log,stdout); ! 501: } ! 502: ! 503: ! 504: ! 505: ! 506: ! 507: readdeltalog() ! 508: /* Function : get the log message and skip the text of a deltatext node. ! 509: * Return false if current block does not start with a number. ! 510: * Assumes the current lexeme is not yet in nexttok; does not ! 511: * advance nexttok. ! 512: */ ! 513: { ! 514: register struct hshentry * Delta; ! 515: ! 516: nextlex(); ! 517: if ( !(Delta = getnum() )) return(false); ! 518: if ( ! getkey(Klog) || ( nexttok != STRING ) ) ! 519: fatserror("Missing log entry"); ! 520: Delta->log = talloc(logsize); ! 521: VOID savestring(Delta->log, logsize); ! 522: nextlex(); ! 523: if ( ! getkey(Ktext) || (nexttok != STRING) ) ! 524: fatserror("Missing delta text"); ! 525: Delta->insertlns = Delta->deletelns = 0; ! 526: if ( Delta != Head) ! 527: getscript(Delta); ! 528: else ! 529: readstring(); ! 530: return true; ! 531: } ! 532: ! 533: ! 534: ! 535: getscript(Delta) ! 536: struct hshentry * Delta; ! 537: /* function: read edit script of Delta and count how many lines added */ ! 538: /* and deleted in the script */ ! 539: ! 540: { ! 541: int ed; /* editor command */ ! 542: register FILE * fin; ! 543: register int c; ! 544: register int i; ! 545: int length; ! 546: ! 547: fin = finptr; ! 548: while( (ed = getc(fin)) != EOF) { ! 549: /* assume first none white character is command name */ ! 550: while( ed == '\n' || ed == ' ' || ed == '\t') ! 551: ed = getc(fin); ! 552: if (ed == SDELIM) break; /* script text is ended */ ! 553: while( ( c = getc(fin)) == ' ' ); /* skip blank */ ! 554: if ( ! ('0' <= c && c <= '9')) { ! 555: faterror("Missing line number in edit script"); ! 556: break; ! 557: } ! 558: while( '0' <= (c = getc(fin)) && c <= '9' ) ; ! 559: ! 560: while( c == ' ')c = getc(fin); /* skip blanks */ ! 561: if ( !('0' <= c && c <= '9' ) ) { ! 562: faterror("Incorrect range in edit script"); ! 563: break; ! 564: } ! 565: length = c - '0'; ! 566: while( '0' <= (c = getc(fin)) && c <= '9' ) ! 567: length = length * 10 + c - '0'; ! 568: while( c != '\n' && c != EOF) c = getc(fin); ! 569: switch (ed) { ! 570: case 'd' : ! 571: Delta->deletelns += length; ! 572: break; ! 573: ! 574: case 'a' : ! 575: /* skip scripted lines */ ! 576: for ( i=length; i > 0 && c != EOF; i--){ ! 577: while( (c=getc(fin)) != '\n' && c != EOF); ! 578: Delta->insertlns++; ! 579: } ! 580: break; ! 581: ! 582: default: ! 583: faterror("Unknown command in edit script: %c", ed); ! 584: break; ! 585: } ! 586: } ! 587: nextc = getc(fin); ! 588: } ! 589: ! 590: ! 591: ! 592: ! 593: ! 594: ! 595: ! 596: exttree(root) ! 597: struct hshentry *root; ! 598: /* function: select revisions , starting with root */ ! 599: ! 600: { ! 601: struct branchhead * newbranch; ! 602: ! 603: if (root == nil) return; ! 604: ! 605: extractdelta(root); ! 606: exttree(root->next); ! 607: ! 608: newbranch = root->branches; ! 609: while( newbranch ) { ! 610: exttree(newbranch->hsh); ! 611: newbranch = newbranch->nextbranch; ! 612: } ! 613: } ! 614: ! 615: ! 616: ! 617: ! 618: getlocker(argv) ! 619: char * argv; ! 620: /* function : get the login names of lockers from command line */ ! 621: /* and store in lockerlist. */ ! 622: ! 623: { ! 624: register char c; ! 625: struct lockers * newlocker; ! 626: argv--; ! 627: while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' || ! 628: c == '\n' || c == ';') ; ! 629: if ( c == '\0') { ! 630: lockerlist=nil; ! 631: return; ! 632: } ! 633: ! 634: while( c != '\0' ) { ! 635: newlocker = ( struct lockers *)talloc( sizeof(struct lockers) ); ! 636: newlocker->lockerlink = lockerlist; ! 637: newlocker->login = argv; ! 638: lockerlist = newlocker; ! 639: while ( ( c = (*++argv)) != ',' && c != '\0' && c != ' ' ! 640: && c != '\t' && c != '\n' && c != ';') ; ! 641: *argv = '\0'; ! 642: if ( c == '\0' ) return; ! 643: while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' || ! 644: c == '\n' || c == ';') ; ! 645: } ! 646: } ! 647: ! 648: ! 649: ! 650: getauthor(argv) ! 651: char *argv; ! 652: /* function: get the author's name form command line */ ! 653: /* and store in aauthorlist */ ! 654: ! 655: { ! 656: register c; ! 657: struct authors * newauthor; ! 658: ! 659: argv--; ! 660: while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' || ! 661: c == '\n' || c == ';') ; ! 662: if ( c == '\0' ) { ! 663: authorlist = (struct authors *)talloc(sizeof(struct authors)); ! 664: authorlist->login = caller; ! 665: authorlist->nextauthor = nil; ! 666: return; ! 667: } ! 668: ! 669: while( c != '\0' ) { ! 670: newauthor = (struct authors *)talloc(sizeof(struct authors)); ! 671: newauthor->nextauthor = authorlist; ! 672: newauthor->login = argv; ! 673: authorlist = newauthor; ! 674: while( ( c = *++argv) != ',' && c != '\0' && c != ' ' ! 675: && c != '\t' && c != '\n' && c != ';') ; ! 676: * argv = '\0'; ! 677: if ( c == '\0') return; ! 678: while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' || ! 679: c == '\n' || c == ';') ; ! 680: } ! 681: } ! 682: ! 683: ! 684: ! 685: ! 686: getstate(argv) ! 687: char * argv; ! 688: /* function : get the states of revisions from command line */ ! 689: /* and store in statelist */ ! 690: ! 691: { ! 692: register char c; ! 693: struct stateattri *newstate; ! 694: ! 695: argv--; ! 696: while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' || ! 697: c == '\n' || c == ';') ; ! 698: if ( c == '\0'){ ! 699: warn(" Missing state attributes after -s options"); ! 700: return; ! 701: } ! 702: ! 703: while( c != '\0' ) { ! 704: newstate = (struct stateattri *)talloc(sizeof(struct stateattri)); ! 705: newstate->nextstate = statelist; ! 706: newstate->status = argv; ! 707: statelist = newstate; ! 708: while( (c = (*++argv)) != ',' && c != '\0' && c != ' ' ! 709: && c != '\t' && c != '\n' && c != ';') ; ! 710: *argv = '\0'; ! 711: if ( c == '\0' ) return; ! 712: while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' || ! 713: c == '\n' || c == ';') ; ! 714: } ! 715: } ! 716: ! 717: ! 718: ! 719: trunclocks() ! 720: /* Function: Truncate the list of locks to those that are held by the */ ! 721: /* id's on lockerlist. Do not truncate if lockerlist empty. */ ! 722: ! 723: { ! 724: struct lockers * plocker; ! 725: struct lock * plocked, * nextlocked; ! 726: ! 727: if ( (lockerlist == nil) || (Locks == nil)) return; ! 728: ! 729: /* shorten Locks to those contained in lockerlist */ ! 730: plocked = Locks; ! 731: Locks = nil; ! 732: while( plocked != nil) { ! 733: plocker = lockerlist; ! 734: while((plocker != nil) && ( strcmp(plocker->login, plocked->login)!=0)) ! 735: plocker = plocker->lockerlink; ! 736: nextlocked = plocked->nextlock; ! 737: if ( plocker != nil) { ! 738: plocked->nextlock = Locks; ! 739: Locks = plocked; ! 740: } ! 741: plocked = nextlocked; ! 742: } ! 743: } ! 744: ! 745: ! 746: ! 747: recentdate(root, pd) ! 748: struct hshentry * root; ! 749: struct Datepairs * pd; ! 750: /* function: Finds the delta that is closest to the cutoff date given by */ ! 751: /* pd among the revisions selected by exttree. */ ! 752: /* Successively narrows down the interfal given by pd, */ ! 753: /* and sets the strtdate of pd to the date of the selected delta */ ! 754: { ! 755: struct branchhead * newbranch; ! 756: ! 757: if ( root == nil) return; ! 758: if ( root->selector == 's') { ! 759: if ( cmpnum(root->date, pd->strtdate) >= 0 && ! 760: cmpnum(root->date, pd->enddate) <= 0) ! 761: VOID strcpy(pd->strtdate, root->date); ! 762: } ! 763: ! 764: recentdate(root->next, pd); ! 765: newbranch = root->branches; ! 766: while( newbranch) { ! 767: recentdate(newbranch->hsh, pd); ! 768: newbranch = newbranch->nextbranch; ! 769: } ! 770: } ! 771: ! 772: ! 773: ! 774: ! 775: ! 776: ! 777: extdate(root) ! 778: struct hshentry * root; ! 779: /* function: select revisions which are in the date range specified */ ! 780: /* in duelst and datelist, start at root */ ! 781: ! 782: { ! 783: struct branchhead * newbranch; ! 784: struct Datepairs * pdate; ! 785: ! 786: if ( root == nil) return; ! 787: ! 788: if ( datelist || duelst) { ! 789: pdate = datelist; ! 790: while( pdate ) { ! 791: if ( (pdate->strtdate)[0] == '\0' || cmpnum(root->date,pdate->strtdate) >= 0){ ! 792: if ((pdate->enddate)[0] == '\0' || cmpnum(pdate->enddate,root->date) >= 0) ! 793: break; ! 794: } ! 795: pdate = pdate->dnext; ! 796: } ! 797: if ( pdate == nil) { ! 798: pdate = duelst; ! 799: while(pdate) { ! 800: if ( cmpnum(root->date, pdate->strtdate) == 0) ! 801: break; ! 802: pdate = pdate->dnext; ! 803: } ! 804: } ! 805: if ( pdate == nil) ! 806: root->selector = 'u'; ! 807: } ! 808: if (root->selector == 's') revno++; ! 809: ! 810: extdate(root->next); ! 811: ! 812: newbranch = root->branches; ! 813: while( newbranch ) { ! 814: extdate(newbranch->hsh); ! 815: newbranch = newbranch->nextbranch; ! 816: } ! 817: } ! 818: ! 819: ! 820: ! 821: extractdelta(pdelta) ! 822: struct hshentry * pdelta; ! 823: /* function: compare information of pdelta to the authorlst, lockerlist, */ ! 824: /* statelist, revlist and mark 's' on selector if pdelta is */ ! 825: /* selected; otherwise, mark 'u' */ ! 826: ! 827: { ! 828: struct lock * plock; ! 829: struct stateattri * pstate; ! 830: struct authors * pauthor; ! 831: struct Revpairs * prevision; ! 832: int length; ! 833: ! 834: pdelta->selector = 's'; ! 835: if ( authorlist ) { /* certain author's revisions wanted only */ ! 836: pauthor = authorlist; ! 837: while((pauthor != nil) && ( strcmp(pauthor->login, pdelta->author)!=0)) ! 838: pauthor = pauthor->nextauthor; ! 839: if ( pauthor == nil ) { ! 840: pdelta->selector = 'u'; ! 841: return; ! 842: } ! 843: } ! 844: if ( statelist ) { /* revisions with certain state wanted */ ! 845: pstate = statelist; ! 846: while((pstate != nil) && (strcmp(pstate->status, pdelta->state)!=0)) ! 847: pstate = pstate->nextstate; ! 848: if ( pstate == nil ) { ! 849: pdelta->selector = 'u'; ! 850: return; ! 851: } ! 852: } ! 853: if ( lockflag ) { /* locked revisions */ ! 854: plock = Locks; ! 855: while( plock && (plock->delta != pdelta)) ! 856: plock = plock->nextlock; ! 857: if (plock == nil ) { ! 858: pdelta->selector = 'u'; ! 859: return; ! 860: } ! 861: } ! 862: if ( Revlst ) { /* revisions or branches selected */ ! 863: ! 864: prevision = Revlst; ! 865: while( prevision != nil ) { ! 866: length = prevision->numfld; ! 867: if ( length % 2 == 1) { /* a branch number */ ! 868: if ( countnumflds(pdelta->num) ==(length+1)) ! 869: if ( (compartial(pdelta->num, prevision->strtrev,length) >= 0)&& ! 870: (compartial(prevision->endrev, pdelta->num, length) >= 0) ) ! 871: break; ! 872: } ! 873: else if ( countnumflds(pdelta->num ) == length) /* a revision */ ! 874: if ( (compartial(pdelta->num, prevision->strtrev, length) >= 0) && ! 875: (compartial(prevision->endrev, pdelta->num, length) >= 0) ) ! 876: break; ! 877: prevision = prevision->rnext; ! 878: } ! 879: if (prevision == nil) { ! 880: pdelta->selector = 'u'; ! 881: return; ! 882: } ! 883: } ! 884: } ! 885: ! 886: ! 887: ! 888: char * procdate(target, source) ! 889: char * target, * source; ! 890: /* Function: Parses a free-format date in target, converts it ! 891: * into RCS internal format, and stores the result into source. ! 892: * Returns target on success, nil otherwise. ! 893: */ ! 894: { ! 895: long unixtime; ! 896: struct tm parseddate, *ftm; ! 897: ! 898: if ( partime(source, &parseddate) == 0) { ! 899: error("Can't parse date/time: %s", source); ! 900: *target= '\0'; ! 901: return nil; ! 902: } ! 903: if ( (unixtime = maketime(&parseddate)) == 0L) { ! 904: error("Inconsistent date/time: %s", source); ! 905: *target='\0'; ! 906: return nil; ! 907: } ! 908: ftm = localtime(&unixtime); ! 909: VOID sprintf(target,DATEFORM, ! 910: ftm->tm_year,ftm->tm_mon+1,ftm->tm_mday,ftm->tm_hour,ftm->tm_min,ftm->tm_sec); ! 911: return target; ! 912: } ! 913: ! 914: ! 915: ! 916: getdatepair(argv) ! 917: char * argv; ! 918: /* function: get time range from command line and store in datelist if */ ! 919: /* a time range specified or in duelst if a time spot specified */ ! 920: ! 921: { ! 922: register char c; ! 923: struct Datepairs * nextdate; ! 924: char * rawdate; ! 925: int switchflag; ! 926: ! 927: argv--; ! 928: while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' || ! 929: c == '\n' || c == ';') ; ! 930: if ( c == '\0' ) { ! 931: warn("Missing date/time after -d"); ! 932: return; ! 933: } ! 934: ! 935: while( c != '\0' ) { ! 936: switchflag = false; ! 937: nextdate = (struct Datepairs *) talloc(sizeof(struct Datepairs)); ! 938: if ( c == '<' ) { /* case: -d <date */ ! 939: c = *++argv; ! 940: (nextdate->strtdate)[0] = '\0'; ! 941: } elsif (c == '>') { /* case: -d >date */ ! 942: c = *++argv; ! 943: (nextdate->enddate)[0] = '\0'; ! 944: switchflag = true; ! 945: } else { ! 946: rawdate = argv; ! 947: while( c != '<' && c != '>' && c != ';' && c != '\0') ! 948: c = *++argv; ! 949: *argv = '\0'; ! 950: if ( c == '>' ) switchflag=true; ! 951: if (procdate(switchflag?nextdate->enddate:nextdate->strtdate, ! 952: rawdate)==nil) continue; ! 953: if ( c == ';' || c == '\0') { /* case: -d date */ ! 954: VOID strcpy(nextdate->enddate,nextdate->strtdate); ! 955: VOID sprintf(nextdate->strtdate,DATEFORM,0,0,0,0,0,0); ! 956: nextdate->dnext = duelst; ! 957: duelst = nextdate; ! 958: goto end; ! 959: } else { ! 960: /* case: -d date< or -d date>; see switchflag */ ! 961: while ( (c= *++argv) == ' ' || c=='\t' || c=='\n'); ! 962: if ( c == ';' || c == '\0') { ! 963: /* second date missing */ ! 964: if (switchflag) ! 965: *nextdate->strtdate= '\0'; ! 966: else ! 967: *nextdate->enddate= '\0'; ! 968: nextdate->dnext = datelist; ! 969: datelist = nextdate; ! 970: goto end; ! 971: } ! 972: } ! 973: } ! 974: rawdate = argv; ! 975: while( c != '>' && c != '<' && c != ';' && c != '\0') ! 976: c = *++argv; ! 977: *argv = '\0'; ! 978: if (procdate(switchflag?nextdate->strtdate:nextdate->enddate, ! 979: rawdate)==nil) continue; ! 980: nextdate->dnext = datelist; ! 981: datelist = nextdate; ! 982: end: ! 983: /* ! 984: VOID printf("startdate: %s; enddate: %s;\n", nextdate->strtdate,nextdate->enddate); ! 985: */ ! 986: if ( c == '\0') return; ! 987: while( (c = *++argv) == ';' || c == ' ' || c == '\t' || c =='\n'); ! 988: } ! 989: } ! 990: ! 991: ! 992: ! 993: ! 994: ! 995: getnumericrev() ! 996: /* function: get the numeric name of revisions which stored in revlist */ ! 997: /* and then stored the numeric names in Revlst */ ! 998: /* if branchflag, also add default branch */ ! 999: ! 1000: { ! 1001: struct Revpairs * ptr, *pt; ! 1002: int flag; ! 1003: char *temprev; ! 1004: ! 1005: /* free the previous numeric revision list */ ! 1006: pt = Revlst; ! 1007: while( pt) { ! 1008: ptr = pt->rnext; ! 1009: free((char *)pt); ! 1010: pt = ptr; ! 1011: } ! 1012: Nextdotstring = &Dotstring[0]; /* reset buffer */ ! 1013: ! 1014: ! 1015: Revlst = nil; ! 1016: ptr = revlist; ! 1017: while( ptr ) { ! 1018: pt = (struct Revpairs *) talloc(sizeof(struct Revpairs)); ! 1019: if ( ptr->numfld == 1 ){ /* case: -r rev */ ! 1020: if ( (flag = expandsym(ptr->strtrev, Nextdotstring)) == true ) { ! 1021: pt->numfld = countnumflds(Nextdotstring); ! 1022: pt->strtrev = pt->endrev = Nextdotstring; ! 1023: while( *Nextdotstring++ != '\0' ) ; ! 1024: } ! 1025: } ! 1026: else if( ptr->numfld == 2){ /* case: -r rev- */ ! 1027: if ( (flag = expandsym(ptr->strtrev, Nextdotstring)) == true) { ! 1028: pt->numfld = countnumflds(Nextdotstring); ! 1029: pt->strtrev = Nextdotstring; ! 1030: while( *Nextdotstring++ != '\0' ) ; ! 1031: pt->endrev = Nextdotstring; ! 1032: if ( pt->numfld > 2) choptail(pt->strtrev); ! 1033: * Nextdotstring++ = '\0'; ! 1034: } ! 1035: } ! 1036: else if(ptr->numfld == 3) { /* case: -r -rev */ ! 1037: if ( (flag = expandsym(ptr->endrev, Nextdotstring)) == true) { ! 1038: pt->endrev = Nextdotstring; ! 1039: while( *Nextdotstring++ != '\0' ) ; ! 1040: pt->numfld = countnumflds(pt->endrev); ! 1041: pt->strtrev = Nextdotstring; ! 1042: if ( pt->numfld == 2) ! 1043: *Nextdotstring++ = '1'; ! 1044: else ! 1045: choptail(pt->endrev); ! 1046: *Nextdotstring++ = '.'; ! 1047: *Nextdotstring++ = '1'; ! 1048: *Nextdotstring++ = '\0'; ! 1049: } ! 1050: } ! 1051: else { /* case: -r rev1-rev2 */ ! 1052: if ( (flag = expandsym(ptr->strtrev, Nextdotstring)) == true ) { ! 1053: pt->strtrev = Nextdotstring; ! 1054: while( *Nextdotstring++ != '\0' ) ; ! 1055: if ( ( flag = expandsym(ptr->endrev, Nextdotstring)) == true) { ! 1056: pt->numfld = countnumflds(pt->strtrev); ! 1057: pt->endrev = Nextdotstring; ! 1058: while( *Nextdotstring++ != '\0' ) ; ! 1059: if((flag = checkrevpair(pt->strtrev, pt->endrev)) == true) ! 1060: /* switch pt->strtrev with pt->endrev, if pt->strtrev > pt->endre */ ! 1061: if (compartial(pt->strtrev, pt->endrev, pt->numfld) > 0 ) { ! 1062: temprev = pt->strtrev; ! 1063: pt->strtrev = pt->endrev; ! 1064: pt->endrev = temprev; ! 1065: } ! 1066: } ! 1067: } ! 1068: } ! 1069: ! 1070: if ( flag ){ ! 1071: pt->rnext = Revlst; ! 1072: Revlst = pt; ! 1073: } ! 1074: else ! 1075: free((char *)pt); ! 1076: ptr = ptr->rnext; ! 1077: } ! 1078: /* Now take care of branchflag */ ! 1079: if (branchflag) { ! 1080: flag =true; ! 1081: pt = (struct Revpairs *) talloc(sizeof(struct Revpairs)); ! 1082: if (Dbranch) { ! 1083: pt->strtrev = pt->endrev = Dbranch->num; ! 1084: } elsif (Head!=nil) { ! 1085: pt->strtrev = pt->endrev = /* branch number of head */ ! 1086: partialno(Nextdotstring,Head->num,1); ! 1087: while( *Nextdotstring++ != '\0' ) ; ! 1088: } else flag = false; ! 1089: if (flag) { /* prepend new node */ ! 1090: pt->rnext=Revlst; Revlst=pt; ! 1091: pt->numfld = countnumflds(pt->strtrev); ! 1092: } ! 1093: } ! 1094: ! 1095: } ! 1096: ! 1097: ! 1098: ! 1099: checkrevpair(num1,num2) ! 1100: char *num1, *num2; ! 1101: /* function: check whether num1, num2 are legal pair,i.e. ! 1102: only the last field are different and have same number of ! 1103: feilds( if length <= 2, may be different if first field) */ ! 1104: ! 1105: { ! 1106: int length; ! 1107: ! 1108: if ( (length = countnumflds(num1)) != countnumflds(num2) ) { ! 1109: error(" Invalid branch or revision pair %s : %s", num1, num2); ! 1110: return false; ! 1111: } ! 1112: if ( length > 2 ) ! 1113: if (compartial(num1, num2, length-1) != 0) { ! 1114: error("Invalid branch or revision pair %s : %s", num1, num2); ! 1115: return false; ! 1116: } ! 1117: ! 1118: return true; ! 1119: } ! 1120: ! 1121: ! 1122: ! 1123: getrevpairs(argv) ! 1124: register char * argv; ! 1125: /* function: get revision or branch range from command line, and */ ! 1126: /* store in revlist */ ! 1127: ! 1128: { ! 1129: register char c; ! 1130: struct Revpairs * nextrevpair; ! 1131: int flag; ! 1132: ! 1133: argv--; ! 1134: while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' || ! 1135: c == '\n' || c == ';') ; ! 1136: if ( c == '\0' ) { ! 1137: warn(" Missing revision or branch number after -r"); ! 1138: return; ! 1139: } ! 1140: ! 1141: while( c != '\0') { ! 1142: while( c == ',' || c == ' ' || c == '\t' || ! 1143: c == '\n' || c == ';') c = *++argv; ! 1144: if (c == '\0') return; ! 1145: nextrevpair = (struct Revpairs *) talloc(sizeof(struct Revpairs)); ! 1146: nextrevpair->rnext = revlist; ! 1147: revlist = nextrevpair; ! 1148: nextrevpair->numfld = nil; ! 1149: nextrevpair->strtrev = nil; ! 1150: nextrevpair->endrev = nil; ! 1151: flag = false; ! 1152: if ( c == '<' || c == '-' ) { /* case: -r -rev or -r <rev */ ! 1153: flag = true; ! 1154: while( (c =(*++argv)) == ' ' || c == '\t' || c =='\n') ; ! 1155: } ! 1156: else { ! 1157: nextrevpair->strtrev = argv; ! 1158: /* get a revision or branch name */ ! 1159: while( c != ',' && c != ';' && c != ' ' && c != '\0' && c != '-' ! 1160: && c != '\t' && c != '\n' && c != '<') c = *++argv; ! 1161: ! 1162: *argv = '\0'; ! 1163: ! 1164: if ( c != '<' && c != '-') { /* case: rev */ ! 1165: nextrevpair->numfld = 1; ! 1166: continue; ! 1167: } ! 1168: ! 1169: if ( (c =(*++argv)) == ',' || c == '\0' || c == ' ' ! 1170: || c == '\t' || c == '\n' || c == ';') {/* case: rev_ */ ! 1171: nextrevpair->numfld = 2; ! 1172: continue; ! 1173: } ! 1174: } ! 1175: nextrevpair->endrev = argv; ! 1176: while( c != ',' && c != ' ' && c != '\0' && c != '\t' && c != '<' ! 1177: && c != '\n' && c != '-' && c != ';') c = *++argv; ! 1178: ! 1179: * argv = '\0'; ! 1180: if ( c == '<'){ ! 1181: error("separator expected near %s", nextrevpair->endrev); ! 1182: while( (c = *++argv) != ',' && c != ' ' && c != '\0' && ! 1183: c != '\t' && c != '\n' && c != ';' ) ; ! 1184: revlist = nextrevpair->rnext; ! 1185: continue; ! 1186: } ! 1187: else { ! 1188: if (flag) /* case: -rev */ ! 1189: nextrevpair->numfld = 3; ! 1190: ! 1191: else /* rev1-rev2 appears */ ! 1192: nextrevpair->numfld = 4; ! 1193: } ! 1194: } ! 1195: } ! 1196: ! 1197: ! 1198: ! 1199: choptail(strhead) ! 1200: char * strhead; ! 1201: /* function : chop off the last field of a branch or a revision number */ ! 1202: ! 1203: { ! 1204: char *pt, *sp; ! 1205: ! 1206: for(pt = Nextdotstring-1; pt != strhead && *pt != '.'; pt--) ; ! 1207: for(sp = strhead; sp < pt; sp++) *Nextdotstring++ = *sp; ! 1208: } ! 1209:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.