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