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