1*86d7f5d3SJohn MarinoChangeLog entry:
2*86d7f5d3SJohn Marino
3*86d7f5d3SJohn MarinoThanks to Paul Eggert who suggested using better random numbers as
4*86d7f5d3SJohn Marinowell as using the base62 format for compactness and provided the
5*86d7f5d3SJohn Marinosample divide_by and convert functions used here.
6*86d7f5d3SJohn Marino
7*86d7f5d3SJohn Marino2005-09-29  Mark D. Baushke  <mdb@gnu.org>
8*86d7f5d3SJohn Marino
9*86d7f5d3SJohn Marino	* man/rcsfile.5in: Document new commitid delta phrase.
10*86d7f5d3SJohn Marino	* man/rcsfile.5: Regenerated.
11*86d7f5d3SJohn Marino
12*86d7f5d3SJohn Marino	* src/ci.c (RANDOM_BYTES, COMMITID_RAW_SIZE): New constants.
13*86d7f5d3SJohn Marino	(mainProg): Add commitid to delta records. Use
14*86d7f5d3SJohn Marino	random data and represent in base62 or fall back to using the
15*86d7f5d3SJohn Marino	same basic format construction as is used by CVS and CVSNT.
16*86d7f5d3SJohn Marino	(divide_by): New function used by convert.
17*86d7f5d3SJohn Marino	(convert): New fucntion to convert to base62.
18*86d7f5d3SJohn Marino	* rcsbase.h (commitidsize): Room for base62 encoded block or
19*86d7f5d3SJohn Marino	32bit pid plus a 32bit time rendered as hex plus one
20*86d7f5d3SJohn Marino	NUL byte round up to 64.
21*86d7f5d3SJohn Marino	(struct hshentry): Add new commitid field.
22*86d7f5d3SJohn Marino	* src/rcsgen.c (putdelta): Preserve old commitid entries.
23*86d7f5d3SJohn Marino	* src/rcssyn.c (Kcommitid): New global constant keyword.
24*86d7f5d3SJohn Marino	(getdelta): Add optional parsing for it.
25*86d7f5d3SJohn Marino	* src/rlog.c (putadelta): Print it out.
26*86d7f5d3SJohn Marino
27*86d7f5d3SJohn MarinoIndex:man/rcsfile.5
28*86d7f5d3SJohn Marino--- man/rcsfile.5~	1995-06-16 06:58:26.000000000 +0000
29*86d7f5d3SJohn Marino+++ man/rcsfile.5	2005-09-27 20:53:01.023504000 +0000
30*86d7f5d3SJohn Marino@@ -1,4 +1,4 @@
31*86d7f5d3SJohn Marino-.lf 1 ./rcsfile.5in
32*86d7f5d3SJohn Marino+.lf 1 rcsfile.5in
33*86d7f5d3SJohn Marino .\" Set p to 1 if your formatter can handle pic output.
34*86d7f5d3SJohn Marino .if t .nr p 1
35*86d7f5d3SJohn Marino .de Id
36*86d7f5d3SJohn Marino@@ -69,6 +69,7 @@ nonterminal symbols are in
37*86d7f5d3SJohn Marino 		\f3state\fP	{\f2id\fP}\f3;\fP
38*86d7f5d3SJohn Marino 		\f3branches\fP	{\f2num\fP}*\f3;\fP
39*86d7f5d3SJohn Marino 		\f3next\fP	{\f2num\fP}\f3;\fP
40*86d7f5d3SJohn Marino+		{ \f3commitid\fP \f2id\fP\f3;\fP }
41*86d7f5d3SJohn Marino 		{ \f2newphrase\fP }*
42*86d7f5d3SJohn Marino .LP
43*86d7f5d3SJohn Marino \f2desc\fP	::=	\f3desc\fP	\f2string\fP
44*86d7f5d3SJohn Marino@@ -128,6 +129,18 @@ and all the digits of years thereafter.
45*86d7f5d3SJohn Marino Dates use the Gregorian calendar; times use UTC.
46*86d7f5d3SJohn Marino .PP
47*86d7f5d3SJohn Marino The
48*86d7f5d3SJohn Marino+.I commitid
49*86d7f5d3SJohn Marino+is followed by an
50*86d7f5d3SJohn Marino+.I id
51*86d7f5d3SJohn Marino+token. This token is intended to be unique across
52*86d7f5d3SJohn Marino+multiple files and is used to help group files as
53*86d7f5d3SJohn Marino+being a part of the same logical commit.
54*86d7f5d3SJohn Marino+This token must uniquely identify the commit
55*86d7f5d3SJohn Marino+operation that was applied to a set of RCS files.
56*86d7f5d3SJohn Marino+In particular, it must be unique among all the
57*86d7f5d3SJohn Marino+commitids in this file.
58*86d7f5d3SJohn Marino+.PP
59*86d7f5d3SJohn Marino+The
60*86d7f5d3SJohn Marino .I newphrase
61*86d7f5d3SJohn Marino productions in the grammar are reserved for future extensions
62*86d7f5d3SJohn Marino to the format of \*r files.
63*86d7f5d3SJohn Marino@@ -230,7 +243,7 @@ The following diagram shows an example o
64*86d7f5d3SJohn Marino .fi
65*86d7f5d3SJohn Marino .\}
66*86d7f5d3SJohn Marino .if \np \{\
67*86d7f5d3SJohn Marino-.lf 232
68*86d7f5d3SJohn Marino+.lf 245
69*86d7f5d3SJohn Marino .PS 4.250i 3.812i
70*86d7f5d3SJohn Marino .\" -2.0625 -4.25 1.75 0
71*86d7f5d3SJohn Marino .\" 0.000i 4.250i 3.812i 0.000i
72*86d7f5d3SJohn Marino@@ -239,7 +252,7 @@ The following diagram shows an example o
73*86d7f5d3SJohn Marino .nr 0x 1
74*86d7f5d3SJohn Marino \h'3.812i'
75*86d7f5d3SJohn Marino .sp -1
76*86d7f5d3SJohn Marino-.lf 242
77*86d7f5d3SJohn Marino+.lf 255
78*86d7f5d3SJohn Marino \h'2.062i-(\w'Head'u/2u)'\v'0.125i-(0v/2u)+0v+0.22m'Head
79*86d7f5d3SJohn Marino .sp -1
80*86d7f5d3SJohn Marino \h'2.062i'\v'0.250i'\D'l0.000i 0.500i'
81*86d7f5d3SJohn Marino@@ -256,7 +269,7 @@ The following diagram shows an example o
82*86d7f5d3SJohn Marino .sp -1
83*86d7f5d3SJohn Marino \h'1.688i'\v'0.750i'\D'l0.000i 0.500i'
84*86d7f5d3SJohn Marino .sp -1
85*86d7f5d3SJohn Marino-.lf 244
86*86d7f5d3SJohn Marino+.lf 257
87*86d7f5d3SJohn Marino \h'2.062i-(\w'2.1'u/2u)'\v'1.000i-(0v/2u)+0v+0.22m'2.1
88*86d7f5d3SJohn Marino .sp -1
89*86d7f5d3SJohn Marino \h'2.062i'\v'1.250i'\D'l0.000i 0.500i'
90*86d7f5d3SJohn Marino@@ -265,7 +278,7 @@ The following diagram shows an example o
91*86d7f5d3SJohn Marino .sp -1
92*86d7f5d3SJohn Marino \h'2.062i'\v'1.750i'\D'l-0.025i -0.100i'
93*86d7f5d3SJohn Marino .sp -1
94*86d7f5d3SJohn Marino-.lf 246
95*86d7f5d3SJohn Marino+.lf 259
96*86d7f5d3SJohn Marino \h'2.062i-(\w'1.3'u/2u)'\v'2.000i-(1v/2u)+0v+0.22m'1.3
97*86d7f5d3SJohn Marino .sp -1
98*86d7f5d3SJohn Marino \h'2.062i'\v'2.250i'\D'l-0.375i -0.500i'
99*86d7f5d3SJohn Marino@@ -280,7 +293,7 @@ The following diagram shows an example o
100*86d7f5d3SJohn Marino .sp -1
101*86d7f5d3SJohn Marino \h'1.375i'\v'1.500i'\D'l0.025i 0.100i'
102*86d7f5d3SJohn Marino .sp -1
103*86d7f5d3SJohn Marino-.lf 249
104*86d7f5d3SJohn Marino+.lf 262
105*86d7f5d3SJohn Marino \h'1.375i-(\w'1.3.1.1'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.3.1.1
106*86d7f5d3SJohn Marino .sp -1
107*86d7f5d3SJohn Marino \h'1.375i'\v'1.000i'\D'l-0.375i 0.500i'
108*86d7f5d3SJohn Marino@@ -295,7 +308,7 @@ The following diagram shows an example o
109*86d7f5d3SJohn Marino .sp -1
110*86d7f5d3SJohn Marino \h'2.062i'\v'2.750i'\D'l-0.025i -0.100i'
111*86d7f5d3SJohn Marino .sp -1
112*86d7f5d3SJohn Marino-.lf 252
113*86d7f5d3SJohn Marino+.lf 265
114*86d7f5d3SJohn Marino \h'2.062i-(\w'1.2'u/2u)'\v'3.000i-(1v/2u)+0v+0.22m'1.2
115*86d7f5d3SJohn Marino .sp -1
116*86d7f5d3SJohn Marino \h'2.062i'\v'3.250i'\D'l-0.375i -0.500i'
117*86d7f5d3SJohn Marino@@ -310,7 +323,7 @@ The following diagram shows an example o
118*86d7f5d3SJohn Marino .sp -1
119*86d7f5d3SJohn Marino \h'0.375i'\v'2.500i'\D'l0.025i 0.100i'
120*86d7f5d3SJohn Marino .sp -1
121*86d7f5d3SJohn Marino-.lf 255
122*86d7f5d3SJohn Marino+.lf 268
123*86d7f5d3SJohn Marino \h'0.375i-(\w'1.2.1.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.1.1
124*86d7f5d3SJohn Marino .sp -1
125*86d7f5d3SJohn Marino \h'0.375i'\v'2.000i'\D'l-0.375i 0.500i'
126*86d7f5d3SJohn Marino@@ -325,7 +338,7 @@ The following diagram shows an example o
127*86d7f5d3SJohn Marino .sp -1
128*86d7f5d3SJohn Marino \h'0.375i'\v'1.500i'\D'l0.025i 0.100i'
129*86d7f5d3SJohn Marino .sp -1
130*86d7f5d3SJohn Marino-.lf 257
131*86d7f5d3SJohn Marino+.lf 270
132*86d7f5d3SJohn Marino \h'0.375i-(\w'1.2.1.3'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.1.3
133*86d7f5d3SJohn Marino .sp -1
134*86d7f5d3SJohn Marino \h'0.375i'\v'1.000i'\D'l-0.375i 0.500i'
135*86d7f5d3SJohn Marino@@ -340,7 +353,7 @@ The following diagram shows an example o
136*86d7f5d3SJohn Marino .sp -1
137*86d7f5d3SJohn Marino \h'2.750i'\v'2.500i'\D'l0.025i 0.100i'
138*86d7f5d3SJohn Marino .sp -1
139*86d7f5d3SJohn Marino-.lf 261
140*86d7f5d3SJohn Marino+.lf 274
141*86d7f5d3SJohn Marino \h'2.750i-(\w'1.2.2.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.2.1
142*86d7f5d3SJohn Marino .sp -1
143*86d7f5d3SJohn Marino \h'2.750i'\v'2.000i'\D'l-0.375i 0.500i'
144*86d7f5d3SJohn Marino@@ -355,7 +368,7 @@ The following diagram shows an example o
145*86d7f5d3SJohn Marino .sp -1
146*86d7f5d3SJohn Marino \h'3.438i'\v'1.250i'\D'l0.025i 0.100i'
147*86d7f5d3SJohn Marino .sp -1
148*86d7f5d3SJohn Marino-.lf 264
149*86d7f5d3SJohn Marino+.lf 277
150*86d7f5d3SJohn Marino \h'3.438i-(\w'\s-21.2.2.1.1.1\s0'u/2u)'\v'1.000i-(1v/2u)+1v+0.22m'\s-21.2.2.1.1.1\s0
151*86d7f5d3SJohn Marino .sp -1
152*86d7f5d3SJohn Marino \h'3.438i'\v'0.750i'\D'l-0.375i 0.500i'
153*86d7f5d3SJohn Marino@@ -370,7 +383,7 @@ The following diagram shows an example o
154*86d7f5d3SJohn Marino .sp -1
155*86d7f5d3SJohn Marino \h'2.750i'\v'1.500i'\D'l0.025i 0.100i'
156*86d7f5d3SJohn Marino .sp -1
157*86d7f5d3SJohn Marino-.lf 267
158*86d7f5d3SJohn Marino+.lf 280
159*86d7f5d3SJohn Marino \h'2.750i-(\w'1.2.2.2'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.2.2
160*86d7f5d3SJohn Marino .sp -1
161*86d7f5d3SJohn Marino \h'2.750i'\v'1.000i'\D'l-0.375i 0.500i'
162*86d7f5d3SJohn Marino@@ -385,7 +398,7 @@ The following diagram shows an example o
163*86d7f5d3SJohn Marino .sp -1
164*86d7f5d3SJohn Marino \h'2.062i'\v'3.750i'\D'l-0.025i -0.100i'
165*86d7f5d3SJohn Marino .sp -1
166*86d7f5d3SJohn Marino-.lf 270
167*86d7f5d3SJohn Marino+.lf 283
168*86d7f5d3SJohn Marino \h'2.062i-(\w'1.1'u/2u)'\v'4.000i-(1v/2u)+0v+0.22m'1.1
169*86d7f5d3SJohn Marino .sp -1
170*86d7f5d3SJohn Marino \h'2.062i'\v'4.250i'\D'l-0.375i -0.500i'
171*86d7f5d3SJohn Marino@@ -398,9 +411,9 @@ The following diagram shows an example o
172*86d7f5d3SJohn Marino .if \n(00 .fi
173*86d7f5d3SJohn Marino .br
174*86d7f5d3SJohn Marino .nr 0x 0
175*86d7f5d3SJohn Marino-.lf 271
176*86d7f5d3SJohn Marino+.lf 284
177*86d7f5d3SJohn Marino .PE
178*86d7f5d3SJohn Marino-.lf 272
179*86d7f5d3SJohn Marino+.lf 285
180*86d7f5d3SJohn Marino .\}
181*86d7f5d3SJohn Marino .PP
182*86d7f5d3SJohn Marino .SH IDENTIFICATION
183*86d7f5d3SJohn MarinoIndex:man/rcsfile.5in
184*86d7f5d3SJohn Marino--- man/rcsfile.5in~	1995-06-05 08:28:35.000000000 +0000
185*86d7f5d3SJohn Marino+++ man/rcsfile.5in	2005-09-27 20:52:46.424504000 +0000
186*86d7f5d3SJohn Marino@@ -68,6 +68,7 @@ nonterminal symbols are in
187*86d7f5d3SJohn Marino 		\f3state\fP	{\f2id\fP}\f3;\fP
188*86d7f5d3SJohn Marino 		\f3branches\fP	{\f2num\fP}*\f3;\fP
189*86d7f5d3SJohn Marino 		\f3next\fP	{\f2num\fP}\f3;\fP
190*86d7f5d3SJohn Marino+		{ \f3commitid\fP \f2id\fP\f3;\fP }
191*86d7f5d3SJohn Marino 		{ \f2newphrase\fP }*
192*86d7f5d3SJohn Marino .LP
193*86d7f5d3SJohn Marino \f2desc\fP	::=	\f3desc\fP	\f2string\fP
194*86d7f5d3SJohn Marino@@ -127,6 +128,18 @@ and all the digits of years thereafter.
195*86d7f5d3SJohn Marino Dates use the Gregorian calendar; times use UTC.
196*86d7f5d3SJohn Marino .PP
197*86d7f5d3SJohn Marino The
198*86d7f5d3SJohn Marino+.I commitid
199*86d7f5d3SJohn Marino+is followed by an
200*86d7f5d3SJohn Marino+.I id
201*86d7f5d3SJohn Marino+token. This token is intended to be unique across
202*86d7f5d3SJohn Marino+multiple files and is used to help group files as
203*86d7f5d3SJohn Marino+being a part of the same logical commit.
204*86d7f5d3SJohn Marino+This token must uniquely identify the commit
205*86d7f5d3SJohn Marino+operation that was applied to a set of RCS files.
206*86d7f5d3SJohn Marino+In particular, it must be unique among all the
207*86d7f5d3SJohn Marino+commitids in this file.
208*86d7f5d3SJohn Marino+.PP
209*86d7f5d3SJohn Marino+The
210*86d7f5d3SJohn Marino .I newphrase
211*86d7f5d3SJohn Marino productions in the grammar are reserved for future extensions
212*86d7f5d3SJohn Marino to the format of \*r files.
213*86d7f5d3SJohn MarinoIndex:src/rcsbase.h
214*86d7f5d3SJohn Marino--- src/rcsbase.h~	1995-06-16 06:19:24.000000000 +0000
215*86d7f5d3SJohn Marino+++ src/rcsbase.h	2005-09-28 21:47:51.490505000 +0000
216*86d7f5d3SJohn Marino@@ -222,6 +222,11 @@ Report problems and direct all questions
217*86d7f5d3SJohn Marino                               /* 1 sets the default locking to strict;      */
218*86d7f5d3SJohn Marino                               /* used in production environments.           */
219*86d7f5d3SJohn Marino
220*86d7f5d3SJohn Marino+/* base64_encode(128 random bits) needs 24 bytes + 1 for NUL */
221*86d7f5d3SJohn Marino+/* time_t may be 64bits on some machines needs 16 bytes + 1 as hex */
222*86d7f5d3SJohn Marino+#define commitidsize	   64 /* time+1+base64(128bits)+1 | pid+time+rand+1 */
223*86d7f5d3SJohn Marino+#define urandom_dev "/dev/urandom"
224*86d7f5d3SJohn Marino+
225*86d7f5d3SJohn Marino #define yearlength	   16 /* (good through AD 9,999,999,999,999,999)    */
226*86d7f5d3SJohn Marino #define datesize (yearlength+16)	/* size of output of time2date */
227*86d7f5d3SJohn Marino #define RCSTMPPREFIX '_' /* prefix for temp files in working dir  */
228*86d7f5d3SJohn Marino@@ -358,6 +363,7 @@ struct hshentry {
229*86d7f5d3SJohn Marino 	char const	  * lockedby; /* who locks the revision		    */
230*86d7f5d3SJohn Marino 	char const	  * state;    /* state of revision (Exp by default) */
231*86d7f5d3SJohn Marino 	char const	  * name;     /* name (if any) by which retrieved   */
232*86d7f5d3SJohn Marino+	char const        * commitid; /* text string to associate commits   */
233*86d7f5d3SJohn Marino 	struct cbuf	    log;      /* log message requested at checkin   */
234*86d7f5d3SJohn Marino         struct branchhead * branches; /* list of first revisions on branches*/
235*86d7f5d3SJohn Marino 	struct cbuf	    ig;	      /* ignored phrases in admin part	    */
236*86d7f5d3SJohn Marino@@ -662,6 +668,7 @@ extern int               TotalDeltas;
237*86d7f5d3SJohn Marino extern char const *const expand_names[];
238*86d7f5d3SJohn Marino extern char const
239*86d7f5d3SJohn Marino 	Kaccess[], Kauthor[], Kbranch[], Kcomment[],
240*86d7f5d3SJohn Marino+	Kcommitid[],
241*86d7f5d3SJohn Marino 	Kdate[], Kdesc[], Kexpand[], Khead[], Klocks[], Klog[],
242*86d7f5d3SJohn Marino 	Knext[], Kstate[], Kstrict[], Ksymbols[], Ktext[];
243*86d7f5d3SJohn Marino void unexpected_EOF P((void)) exiting;
244*86d7f5d3SJohn MarinoIndex:src/ci.c
245*86d7f5d3SJohn Marino--- src/ci.c~	1995-06-16 06:19:24.000000000 +0000
246*86d7f5d3SJohn Marino+++ src/ci.c	2005-09-29 21:57:57.814504000 +0000
247*86d7f5d3SJohn Marino@@ -262,6 +262,10 @@ static void cleanup P((void));
248*86d7f5d3SJohn Marino static void incnum P((char const*,struct buf*));
249*86d7f5d3SJohn Marino static void addassoclst P((int,char const*));
250*86d7f5d3SJohn Marino
251*86d7f5d3SJohn Marino+enum {RANDOM_BYTES = 8};
252*86d7f5d3SJohn Marino+enum {COMMITID_RAW_SIZE = (sizeof(time_t) + RANDOM_BYTES)};
253*86d7f5d3SJohn Marino+static void convert P((char const input[COMMITID_RAW_SIZE], char *output));
254*86d7f5d3SJohn Marino+
255*86d7f5d3SJohn Marino static FILE *exfile;
256*86d7f5d3SJohn Marino static RILE *workptr;			/* working file pointer		*/
257*86d7f5d3SJohn Marino static struct buf newdelnum;		/* new revision number		*/
258*86d7f5d3SJohn Marino@@ -285,6 +289,7 @@ mainProg(ciId, "ci", "$Id: ci.c,v 5.30 1
259*86d7f5d3SJohn Marino 	char olddate[datesize];
260*86d7f5d3SJohn Marino 	char newdatebuf[datesize + zonelenmax];
261*86d7f5d3SJohn Marino 	char targetdatebuf[datesize + zonelenmax];
262*86d7f5d3SJohn Marino+	char commitid[commitidsize];
263*86d7f5d3SJohn Marino 	char *a, **newargv, *textfile;
264*86d7f5d3SJohn Marino 	char const *author, *krev, *rev, *state;
265*86d7f5d3SJohn Marino 	char const *diffname, *expname;
266*86d7f5d3SJohn Marino@@ -309,6 +314,45 @@ mainProg(ciId, "ci", "$Id: ci.c,v 5.30 1
267*86d7f5d3SJohn Marino 	suffixes = X_DEFAULT;
268*86d7f5d3SJohn Marino 	nextassoc = &assoclst;
269*86d7f5d3SJohn Marino
270*86d7f5d3SJohn Marino+	{
271*86d7f5d3SJohn Marino+		char buf[COMMITID_RAW_SIZE] = { 0, };
272*86d7f5d3SJohn Marino+		ssize_t len = 0;
273*86d7f5d3SJohn Marino+		time_t rightnow = time (NULL);
274*86d7f5d3SJohn Marino+		char *startrand = buf + sizeof (time_t);
275*86d7f5d3SJohn Marino+		unsigned char *p = (unsigned char *) startrand;
276*86d7f5d3SJohn Marino+		size_t randbytes = RANDOM_BYTES;
277*86d7f5d3SJohn Marino+		int flags = O_RDONLY;
278*86d7f5d3SJohn Marino+		int fd;
279*86d7f5d3SJohn Marino+#ifdef O_NOCTTY
280*86d7f5d3SJohn Marino+		flags |= O_NOCTTY;
281*86d7f5d3SJohn Marino+#endif
282*86d7f5d3SJohn Marino+		if (rightnow != (time_t)-1)
283*86d7f5d3SJohn Marino+			while (rightnow > 0) {
284*86d7f5d3SJohn Marino+				*--p = rightnow % (UCHAR_MAX + 1);
285*86d7f5d3SJohn Marino+				rightnow /= UCHAR_MAX + 1;
286*86d7f5d3SJohn Marino+			}
287*86d7f5d3SJohn Marino+		else {
288*86d7f5d3SJohn Marino+			/* try to use more random data */
289*86d7f5d3SJohn Marino+			randbytes = COMMITID_RAW_SIZE;
290*86d7f5d3SJohn Marino+			startrand = buf;
291*86d7f5d3SJohn Marino+		}
292*86d7f5d3SJohn Marino+		fd = open (urandom_dev, flags);
293*86d7f5d3SJohn Marino+		if (fd >= 0) {
294*86d7f5d3SJohn Marino+			len = read (fd, startrand, randbytes);
295*86d7f5d3SJohn Marino+			close (fd);
296*86d7f5d3SJohn Marino+		}
297*86d7f5d3SJohn Marino+		if (len <= 0) {
298*86d7f5d3SJohn Marino+			/* no random data was available so use pid */
299*86d7f5d3SJohn Marino+			long int pid = (long int)getpid ();
300*86d7f5d3SJohn Marino+			p = (unsigned char *) (startrand + sizeof (pid));
301*86d7f5d3SJohn Marino+			while (pid > 0) {
302*86d7f5d3SJohn Marino+			    *--p = pid % (UCHAR_MAX + 1);
303*86d7f5d3SJohn Marino+			    pid /= UCHAR_MAX + 1;
304*86d7f5d3SJohn Marino+			}
305*86d7f5d3SJohn Marino+		}
306*86d7f5d3SJohn Marino+		convert(buf, commitid);
307*86d7f5d3SJohn Marino+	}
308*86d7f5d3SJohn Marino+
309*86d7f5d3SJohn Marino 	argc = getRCSINIT(argc, argv, &newargv);
310*86d7f5d3SJohn Marino 	argv = newargv;
311*86d7f5d3SJohn Marino 	while (a = *++argv,  0<--argc && *a++=='-') {
312*86d7f5d3SJohn Marino@@ -532,6 +576,8 @@ mainProg(ciId, "ci", "$Id: ci.c,v 5.30 1
313*86d7f5d3SJohn Marino 	newdelta.name = 0;
314*86d7f5d3SJohn Marino 	clear_buf(&newdelta.ig);
315*86d7f5d3SJohn Marino 	clear_buf(&newdelta.igtext);
316*86d7f5d3SJohn Marino+	/* set commitid */
317*86d7f5d3SJohn Marino+	newdelta.commitid=commitid;
318*86d7f5d3SJohn Marino 	/* set author */
319*86d7f5d3SJohn Marino 	if (author)
320*86d7f5d3SJohn Marino 		newdelta.author=author;     /* set author given by -w         */
321*86d7f5d3SJohn Marino@@ -1317,3 +1363,38 @@ addassoclst(flag, sp)
322*86d7f5d3SJohn Marino 	*nextassoc = pt;
323*86d7f5d3SJohn Marino 	nextassoc = &pt->nextsym;
324*86d7f5d3SJohn Marino }
325*86d7f5d3SJohn Marino+
326*86d7f5d3SJohn Marino+static char const alphabet[62] =
327*86d7f5d3SJohn Marino+  "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
328*86d7f5d3SJohn Marino+
329*86d7f5d3SJohn Marino+/* Divide BUF by D, returning the remainder.  Replace BUF by the
330*86d7f5d3SJohn Marino+   quotient.  BUF[0] is the most significant part of BUF.
331*86d7f5d3SJohn Marino+   D must not exceed UINT_MAX >> CHAR_BIT.  */
332*86d7f5d3SJohn Marino+static unsigned int
333*86d7f5d3SJohn Marino+divide_by (unsigned char buf[COMMITID_RAW_SIZE], unsigned int d)
334*86d7f5d3SJohn Marino+{
335*86d7f5d3SJohn Marino+  unsigned int carry = 0;
336*86d7f5d3SJohn Marino+  int i;
337*86d7f5d3SJohn Marino+  for (i = 0; i < COMMITID_RAW_SIZE; i++)
338*86d7f5d3SJohn Marino+    {
339*86d7f5d3SJohn Marino+      unsigned int byte = buf[i];
340*86d7f5d3SJohn Marino+      unsigned int dividend = (carry << CHAR_BIT) + byte;
341*86d7f5d3SJohn Marino+      buf[i] = dividend / d;
342*86d7f5d3SJohn Marino+      carry = dividend % d;
343*86d7f5d3SJohn Marino+    }
344*86d7f5d3SJohn Marino+  return carry;
345*86d7f5d3SJohn Marino+}
346*86d7f5d3SJohn Marino+
347*86d7f5d3SJohn Marino+static void
348*86d7f5d3SJohn Marino+convert (char const input[COMMITID_RAW_SIZE], char *output)
349*86d7f5d3SJohn Marino+{
350*86d7f5d3SJohn Marino+  static char const zero[COMMITID_RAW_SIZE] = { 0, };
351*86d7f5d3SJohn Marino+  unsigned char buf[COMMITID_RAW_SIZE];
352*86d7f5d3SJohn Marino+  size_t o = 0;
353*86d7f5d3SJohn Marino+  memcpy (buf, input, COMMITID_RAW_SIZE);
354*86d7f5d3SJohn Marino+  while (memcmp (buf, zero, COMMITID_RAW_SIZE) != 0)
355*86d7f5d3SJohn Marino+    output[o++] = alphabet[divide_by (buf, sizeof alphabet)];
356*86d7f5d3SJohn Marino+  if (! o)
357*86d7f5d3SJohn Marino+    output[o++] = '0';
358*86d7f5d3SJohn Marino+  output[o] = '\0';
359*86d7f5d3SJohn Marino+}
360*86d7f5d3SJohn MarinoIndex:src/rcsgen.c
361*86d7f5d3SJohn Marino--- src/rcsgen.c~	1995-06-16 06:19:24.000000000 +0000
362*86d7f5d3SJohn Marino+++ src/rcsgen.c	2005-09-27 22:08:47.421504000 +0000
363*86d7f5d3SJohn Marino@@ -547,6 +547,9 @@ putdelta(node, fout)
364*86d7f5d3SJohn Marino
365*86d7f5d3SJohn Marino 	aprintf(fout, ";\n%s\t%s;\n", Knext, node->next?node->next->num:"");
366*86d7f5d3SJohn Marino 	awrite(node->ig.string, node->ig.size, fout);
367*86d7f5d3SJohn Marino+
368*86d7f5d3SJohn Marino+	if (node->commitid)
369*86d7f5d3SJohn Marino+		aprintf(fout, "%s\t%s;\n", Kcommitid, node->commitid);
370*86d7f5d3SJohn Marino }
371*86d7f5d3SJohn Marino
372*86d7f5d3SJohn Marino
373*86d7f5d3SJohn MarinoIndex:src/rcssyn.c
374*86d7f5d3SJohn Marino--- src/rcssyn.c~	1995-06-16 06:19:24.000000000 +0000
375*86d7f5d3SJohn Marino+++ src/rcssyn.c	2005-09-27 22:08:47.429504000 +0000
376*86d7f5d3SJohn Marino@@ -171,6 +171,7 @@ char const
377*86d7f5d3SJohn Marino 	Kauthor[]   = "author",
378*86d7f5d3SJohn Marino 	Kbranch[]   = "branch",
379*86d7f5d3SJohn Marino 	Kcomment[]  = "comment",
380*86d7f5d3SJohn Marino+	Kcommitid[] = "commitid",
381*86d7f5d3SJohn Marino 	Kdate[]     = "date",
382*86d7f5d3SJohn Marino 	Kdesc[]     = "desc",
383*86d7f5d3SJohn Marino 	Kexpand[]   = "expand",
384*86d7f5d3SJohn Marino@@ -433,6 +434,13 @@ getdelta()
385*86d7f5d3SJohn Marino 	Delta->lockedby = 0;
386*86d7f5d3SJohn Marino 	Delta->log.string = 0;
387*86d7f5d3SJohn Marino 	Delta->selector = true;
388*86d7f5d3SJohn Marino+
389*86d7f5d3SJohn Marino+	if (getkeyopt(Kcommitid)) {
390*86d7f5d3SJohn Marino+		Delta->commitid = NextString;
391*86d7f5d3SJohn Marino+		nextlex();
392*86d7f5d3SJohn Marino+		getsemi(Kcommitid);
393*86d7f5d3SJohn Marino+        }
394*86d7f5d3SJohn Marino+
395*86d7f5d3SJohn Marino 	Delta->ig = getphrases(Kdesc);
396*86d7f5d3SJohn Marino         TotalDeltas++;
397*86d7f5d3SJohn Marino         return (true);
398*86d7f5d3SJohn MarinoIndex:src/rlog.c
399*86d7f5d3SJohn Marino--- src/rlog.c~	1995-06-16 06:19:24.000000000 +0000
400*86d7f5d3SJohn Marino+++ src/rlog.c	2005-09-26 17:23:55.257504000 +0000
401*86d7f5d3SJohn Marino@@ -591,6 +591,10 @@ putadelta(node,editscript,trunk)
402*86d7f5d3SJohn Marino 	      aprintf(out, insDelFormat,
403*86d7f5d3SJohn Marino                              editscript->insertlns, editscript->deletelns);
404*86d7f5d3SJohn Marino
405*86d7f5d3SJohn Marino+	if ( node->commitid )
406*86d7f5d3SJohn Marino+	   aprintf(out, "%s commitid: %s", (editscript) ? ";" : "",
407*86d7f5d3SJohn Marino+		   node->commitid);
408*86d7f5d3SJohn Marino+
409*86d7f5d3SJohn Marino         newbranch = node->branches;
410*86d7f5d3SJohn Marino         if ( newbranch ) {
411*86d7f5d3SJohn Marino 	   bufautobegin(&branchnum);
412