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