6 "$Header: /pub/NetBSD/misc/repositories/cvsroot/src/usr.bin/rcs/src/Attic/rlog.c,v 1.1 1993/03/21 09:58:09 cgd Exp $ Purdue CS";
8 /*****************************************************************************
9 * print contents of RCS files
10 *****************************************************************************
13 /* Copyright (C) 1982, 1988, 1989 Walter Tichy
14 * All rights reserved.
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
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.
26 * Report all problems and direct all questions to:
27 * rcs-bugs@cs.purdue.edu
42 * Revision 4.7 89/05/01 15:13:48 narten
43 * changed copyright header to reflect current distribution rules
45 * Revision 4.6 88/11/08 11:59:40 narten
46 * changes from eggert@sm.unisys.com (Paul Eggert)
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.
52 * Revision 4.5 87/12/18 11:46:38 narten
53 * more lint cleanups (Guy Harris)
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
59 * Revision 1.3 87/09/24 14:01:10 narten
60 * Sources now pass through lint (if you ignore printf/sprintf/fprintf
63 * Revision 1.2 87/03/27 14:22:45 jenkins
66 * Revision 1.1 84/01/23 14:50:45 kcs
69 * Revision 4.2 83/12/05 09:18:09 wft
70 * changed rewriteflag to external.
72 * Revision 4.1 83/05/11 16:16:55 wft
73 * Added -b, updated getnumericrev() accordingly.
74 * Replaced getpwuid() with getcaller().
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()).
81 * Revision 3.6 82/12/24 15:57:53 wft
82 * shortened output format.
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.
88 * Revision 3.4 82/12/04 13:26:25 wft
89 * Replaced getdelta() with gettree(); removed updating of field lockedby.
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.
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.
101 * Revision 3.1 82/10/13 16:07:56 wft
102 * fixed type of variables receiving from getc() (char -> int).
110 static char rcsbaseid
[] = RCSBASE
;
113 extern char * partialno();
114 extern char * getcaller(); /*get login of caller */
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 */
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 */
133 char * RCSfilename
, * workfilename
;
135 char * caller
; /* caller's login; */
136 int descflag
, selectflag
, selectop
; /* option to print access list, symbolic */
137 /* names, descriptive text, locks and */
139 int onlylockflag
; /* option to print only files */
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 */
145 struct lockers
{ /* lockers in locker option; stored */
146 char * login
; /* lockerlist */
147 struct lockers
* lockerlink
;
150 struct stateattri
{ /* states in state option; stored in */
151 char * status
; /* statelist */
152 struct stateattri
* nextstate
;
155 struct authors
{ /* login names in author option; */
156 char * login
; /* stored in authorlist */
157 struct authors
* nextauthor
;
160 struct Revpairs
{ /* revision or branch range in -r */
161 int numfld
; /* option; stored in revlist */
164 struct Revpairs
* rnext
;
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
;
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
;
188 struct Datepairs
* currdate
;
189 struct assoc
* curassoc
;
190 struct access
* curaccess
;
191 struct lock
* currlock
;
194 cmdusage
= "command format:\nrlog -L -R -h -t -b -ddates -l[lockers] -rrevisions -sstates -w[logins] file ...";
196 descflag
= selectflag
= true;
197 lockflag
= onlylockflag
= selectop
= false;
202 Revlst
= revlist
= nil
;
204 duelst
= datelist
= nil
;
207 while (--argc
,++argv
, argc
>=1 && ((*argv
)[0] == '-')) {
208 switch ((*argv
)[1]) {
221 getlocker( (*argv
)+2 );
231 getrevpairs( (*argv
)+2 );
236 getdatepair( (*argv
)+2 );
241 getstate( (*argv
)+2);
246 getauthor( (*argv
)+2);
250 if ( ! selectflag
) warn("option -t overrides -h");
251 else descflag
= false;
256 if ( ! descflag
) warn("option -t overrides -h");
261 faterror("unknown option: %s\n%s", *argv
,cmdusage
);
264 } /* end of option processing */
266 if (argc
<1) faterror("No input file\n%s",cmdusage
);
269 /* now handle all filenames */
275 if (!pairfilenames(argc
, argv
, true,false)) continue;
277 /* now RCSfilename contains the name of the RCS file, and finptr
278 * the file descriptor. Workfilename contains the name of the
282 if ( !trysema(RCSfilename
, false)) goto loopend
; /* give up */
284 /* do nothing if -L is given and there are no locks*/
285 if ( onlylockflag
&& Locks
== nil
) goto loopend
;
288 VOID
fprintf(stdout
, "%s\n", RCSfilename
);
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
);
299 VOID
fputs("locks: ", stdout
); /* print locker list */
302 VOID
fprintf(stdout
," %s: %s;", currlock
->login
,
303 currlock
->delta
->num
);
304 currlock
= currlock
->nextlock
;
307 VOID
fputs(Locks
==nil
?" ; strict":" strict",stdout
);
309 VOID
fputs("\naccess list: ", stdout
); /* print access list */
310 curaccess
= AccessList
;
312 VOID
fputs(" ",stdout
);
313 VOID
fputs(curaccess
->login
, stdout
);
314 curaccess
= curaccess
->nextaccess
;
317 VOID
fputs("\nsymbolic names:", stdout
); /* print symbolic names */
320 VOID
fprintf(stdout
, " %s: %s;",curassoc
->symbol
,
321 curassoc
->delta
->num
);
322 curassoc
= curassoc
->nextassoc
;
325 VOID
fprintf(stdout
,"\ncomment leader: \"%s\"\n",Comment
);
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
);
333 VOID
fputs("=============================================================================\n",stdout
);
338 /* keep only those locks given by -l */
341 getnumericrev(); /* get numeric revision or branch names */
346 /* get most recently date of the dates pointed by duelst */
349 recentdate(Head
, currdate
);
350 currdate
= currdate
->dnext
;
355 /* reinitialize the date specification list */
358 VOID
sprintf(currdate
->strtdate
,DATEFORM
,0,0,0,0,0,0);
359 currdate
= currdate
->dnext
;
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
);
367 while( (nexttok
!= EOFILE
) && readdeltalog());
368 if (selectflag
&& descflag
&& revno
) {
371 if (nextlex(), nexttok
!= EOFILE
)
372 fatserror("syntax error; expecting EOF");
374 VOID
fputs("=============================================================================\n",stdout
);
377 } while( ++argv
, --argc
>= 1);
384 /* function: print revisions chosen, which are in trunk */
387 struct hshentry
* ptr
, * pre
;
389 if (Head
== nil
) return; /* empty tree */
394 putadelta(pre
,ptr
,true);
398 putadelta(pre
,ptr
,true);
404 struct hshentry
*root
;
405 /* function: print delta tree( not include trunck) in reversed calender
406 order on each branch */
409 if ( root
== nil
) return;
413 putforest(root
->branches
);
419 putforest(branchroot
)
420 struct branchhead
* branchroot
;
421 /* function: print branches that has the same direct ancestor */
424 if ( branchroot
== nil
) return;
426 putforest(branchroot
->nextbranch
);
428 putabranch(branchroot
->hsh
);
429 putree(branchroot
->hsh
);
436 struct hshentry
*root
;
437 /* function : print one branch */
441 if ( root
== nil
) return;
443 putabranch(root
->next
);
445 putadelta(root
, root
, false);
452 putadelta(node
,editscript
,trunk
)
453 register struct hshentry
* node
;
454 register struct hshentry
* editscript
;
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 */
460 struct branchhead
* newbranch
;
461 char * branchnum
, branch
[40];
463 if ( ( node
== nil
) || ( node
->selector
== 'u'))
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
);
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
);
480 VOID
fprintf(stdout
,"lines added/del: %d/%d",
481 editscript
->deletelns
, editscript
->insertlns
);
483 VOID
fprintf(stdout
,"lines added/del: %d/%d",
484 editscript
->insertlns
, editscript
->deletelns
);
486 VOID
putc('\n', stdout
);
488 branchnum
= & (branch
[0]);
489 newbranch
= node
->branches
;
491 VOID
fputs("branches: ", stdout
);
493 getbranchno(newbranch
->hsh
->num
, branchnum
);
494 VOID
fprintf(stdout
, "%s; ", branchnum
);
495 newbranch
= newbranch
->nextbranch
;
497 VOID
putc('\n', stdout
);
500 VOID
fputs(node
->log
,stdout
);
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
514 register struct hshentry
* Delta
;
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
);
523 if ( ! getkey(Ktext
) || (nexttok
!= STRING
) )
524 fatserror("Missing delta text");
525 Delta
->insertlns
= Delta
->deletelns
= 0;
536 struct hshentry
* Delta
;
537 /* function: read edit script of Delta and count how many lines added */
538 /* and deleted in the script */
541 int ed
; /* editor command */
548 while( (ed
= getc(fin
)) != EOF
) {
549 /* assume first none white character is command name */
550 while( ed
== '\n' || ed
== ' ' || ed
== '\t')
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");
558 while( '0' <= (c
= getc(fin
)) && c
<= '9' ) ;
560 while( c
== ' ')c
= getc(fin
); /* skip blanks */
561 if ( !('0' <= c
&& c
<= '9' ) ) {
562 faterror("Incorrect range in edit script");
566 while( '0' <= (c
= getc(fin
)) && c
<= '9' )
567 length
= length
* 10 + c
- '0';
568 while( c
!= '\n' && c
!= EOF
) c
= getc(fin
);
571 Delta
->deletelns
+= length
;
575 /* skip scripted lines */
576 for ( i
=length
; i
> 0 && c
!= EOF
; i
--){
577 while( (c
=getc(fin
)) != '\n' && c
!= EOF
);
583 faterror("Unknown command in edit script: %c", ed
);
597 struct hshentry
*root
;
598 /* function: select revisions , starting with root */
601 struct branchhead
* newbranch
;
603 if (root
== nil
) return;
608 newbranch
= root
->branches
;
610 exttree(newbranch
->hsh
);
611 newbranch
= newbranch
->nextbranch
;
620 /* function : get the login names of lockers from command line */
621 /* and store in lockerlist. */
625 struct lockers
* newlocker
;
627 while( ( c
= (*++argv
)) == ',' || c
== ' ' || c
== '\t' ||
628 c
== '\n' || c
== ';') ;
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
!= ';') ;
642 if ( c
== '\0' ) return;
643 while( ( c
= (*++argv
)) == ',' || c
== ' ' || c
== '\t' ||
644 c
== '\n' || c
== ';') ;
652 /* function: get the author's name form command line */
653 /* and store in aauthorlist */
657 struct authors
* newauthor
;
660 while( ( c
= (*++argv
)) == ',' || c
== ' ' || c
== '\t' ||
661 c
== '\n' || c
== ';') ;
663 authorlist
= (struct authors
*)talloc(sizeof(struct authors
));
664 authorlist
->login
= caller
;
665 authorlist
->nextauthor
= nil
;
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
!= ';') ;
677 if ( c
== '\0') return;
678 while( ( c
= (*++argv
)) == ',' || c
== ' ' || c
== '\t' ||
679 c
== '\n' || c
== ';') ;
688 /* function : get the states of revisions from command line */
689 /* and store in statelist */
693 struct stateattri
*newstate
;
696 while( ( c
= (*++argv
)) == ',' || c
== ' ' || c
== '\t' ||
697 c
== '\n' || c
== ';') ;
699 warn(" Missing state attributes after -s options");
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
!= ';') ;
711 if ( c
== '\0' ) return;
712 while( ( c
= (*++argv
)) == ',' || c
== ' ' || c
== '\t' ||
713 c
== '\n' || c
== ';') ;
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. */
724 struct lockers
* plocker
;
725 struct lock
* plocked
, * nextlocked
;
727 if ( (lockerlist
== nil
) || (Locks
== nil
)) return;
729 /* shorten Locks to those contained in lockerlist */
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
;
741 plocked
= nextlocked
;
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 */
755 struct branchhead
* newbranch
;
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
);
764 recentdate(root
->next
, pd
);
765 newbranch
= root
->branches
;
767 recentdate(newbranch
->hsh
, pd
);
768 newbranch
= newbranch
->nextbranch
;
778 struct hshentry
* root
;
779 /* function: select revisions which are in the date range specified */
780 /* in duelst and datelist, start at root */
783 struct branchhead
* newbranch
;
784 struct Datepairs
* pdate
;
786 if ( root
== nil
) return;
788 if ( datelist
|| duelst
) {
791 if ( (pdate
->strtdate
)[0] == '\0' || cmpnum(root
->date
,pdate
->strtdate
) >= 0){
792 if ((pdate
->enddate
)[0] == '\0' || cmpnum(pdate
->enddate
,root
->date
) >= 0)
795 pdate
= pdate
->dnext
;
800 if ( cmpnum(root
->date
, pdate
->strtdate
) == 0)
802 pdate
= pdate
->dnext
;
806 root
->selector
= 'u';
808 if (root
->selector
== 's') revno
++;
812 newbranch
= root
->branches
;
814 extdate(newbranch
->hsh
);
815 newbranch
= newbranch
->nextbranch
;
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' */
829 struct stateattri
* pstate
;
830 struct authors
* pauthor
;
831 struct Revpairs
* prevision
;
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';
844 if ( statelist
) { /* revisions with certain state wanted */
846 while((pstate
!= nil
) && (strcmp(pstate
->status
, pdelta
->state
)!=0))
847 pstate
= pstate
->nextstate
;
848 if ( pstate
== nil
) {
849 pdelta
->selector
= 'u';
853 if ( lockflag
) { /* locked revisions */
855 while( plock
&& (plock
->delta
!= pdelta
))
856 plock
= plock
->nextlock
;
858 pdelta
->selector
= 'u';
862 if ( Revlst
) { /* revisions or branches selected */
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) )
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) )
877 prevision
= prevision
->rnext
;
879 if (prevision
== nil
) {
880 pdelta
->selector
= 'u';
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.
896 struct tm parseddate
, *ftm
;
898 if ( partime(source
, &parseddate
) == 0) {
899 error("Can't parse date/time: %s", source
);
903 if ( (unixtime
= maketime(&parseddate
)) == 0L) {
904 error("Inconsistent date/time: %s", source
);
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
);
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 */
923 struct Datepairs
* nextdate
;
928 while( ( c
= (*++argv
)) == ',' || c
== ' ' || c
== '\t' ||
929 c
== '\n' || c
== ';') ;
931 warn("Missing date/time after -d");
937 nextdate
= (struct Datepairs
*) talloc(sizeof(struct Datepairs
));
938 if ( c
== '<' ) { /* case: -d <date */
940 (nextdate
->strtdate
)[0] = '\0';
941 } elsif (c
== '>') { /* case: -d >date */
943 (nextdate
->enddate
)[0] = '\0';
947 while( c
!= '<' && c
!= '>' && c
!= ';' && c
!= '\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
;
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 */
965 *nextdate
->strtdate
= '\0';
967 *nextdate
->enddate
= '\0';
968 nextdate
->dnext
= datelist
;
975 while( c
!= '>' && c
!= '<' && c
!= ';' && c
!= '\0')
978 if (procdate(switchflag
?nextdate
->strtdate
:nextdate
->enddate
,
979 rawdate
)==nil
) continue;
980 nextdate
->dnext
= datelist
;
984 VOID printf("startdate: %s; enddate: %s;\n", nextdate->strtdate,nextdate->enddate);
986 if ( c
== '\0') return;
987 while( (c
= *++argv
) == ';' || c
== ' ' || c
== '\t' || c
=='\n');
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 */
1001 struct Revpairs
* ptr
, *pt
;
1005 /* free the previous numeric revision list */
1012 Nextdotstring
= &Dotstring
[0]; /* reset buffer */
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' ) ;
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';
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';
1045 choptail(pt
->endrev
);
1046 *Nextdotstring
++ = '.';
1047 *Nextdotstring
++ = '1';
1048 *Nextdotstring
++ = '\0';
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
;
1078 /* Now take care of branchflag */
1081 pt
= (struct Revpairs
*) talloc(sizeof(struct Revpairs
));
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
);
1099 checkrevpair(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) */
1108 if ( (length
= countnumflds(num1
)) != countnumflds(num2
) ) {
1109 error(" Invalid branch or revision pair %s : %s", num1
, num2
);
1113 if (compartial(num1
, num2
, length
-1) != 0) {
1114 error("Invalid branch or revision pair %s : %s", num1
, num2
);
1124 register char * argv
;
1125 /* function: get revision or branch range from command line, and */
1126 /* store in revlist */
1130 struct Revpairs
* nextrevpair
;
1134 while( ( c
= (*++argv
)) == ',' || c
== ' ' || c
== '\t' ||
1135 c
== '\n' || c
== ';') ;
1137 warn(" Missing revision or branch number after -r");
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
;
1152 if ( c
== '<' || c
== '-' ) { /* case: -r -rev or -r <rev */
1154 while( (c
=(*++argv
)) == ' ' || c
== '\t' || c
=='\n') ;
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
;
1164 if ( c
!= '<' && c
!= '-') { /* case: rev */
1165 nextrevpair
->numfld
= 1;
1169 if ( (c
=(*++argv
)) == ',' || c
== '\0' || c
== ' '
1170 || c
== '\t' || c
== '\n' || c
== ';') {/* case: rev_ */
1171 nextrevpair
->numfld
= 2;
1175 nextrevpair
->endrev
= argv
;
1176 while( c
!= ',' && c
!= ' ' && c
!= '\0' && c
!= '\t' && c
!= '<'
1177 && c
!= '\n' && c
!= '-' && c
!= ';') c
= *++argv
;
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
;
1188 if (flag
) /* case: -rev */
1189 nextrevpair
->numfld
= 3;
1191 else /* rev1-rev2 appears */
1192 nextrevpair
->numfld
= 4;
1201 /* function : chop off the last field of a branch or a revision number */
1206 for(pt
= Nextdotstring
-1; pt
!= strhead
&& *pt
!= '.'; pt
--) ;
1207 for(sp
= strhead
; sp
< pt
; sp
++) *Nextdotstring
++ = *sp
;