Annotation of 43BSDReno/contrib/rcs/src/rcsrev.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *                     RCS revision number handling
                      3:  */
                      4: #ifndef lint
                      5: static char rcsid[]= "$Id: rcsrev.c,v 4.5 89/05/01 15:13:22 narten Exp $ Purdue CS";
                      6: #endif
                      7: 
                      8: /* Copyright (C) 1982, 1988, 1989 Walter Tichy
                      9:  * All rights reserved.
                     10:  *
                     11:  * Redistribution and use in source and binary forms are permitted
                     12:  * provided that the above copyright notice and this paragraph are
                     13:  * duplicated in all such forms and that any documentation,
                     14:  * advertising materials, and other materials related to such
                     15:  * distribution and use acknowledge that the software was developed
                     16:  * by Walter Tichy.
                     17:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     18:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     19:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     20:  *
                     21:  * Report all problems and direct all questions to:
                     22:  *   [email protected]
                     23:  * 
                     24: 
                     25: 
                     26: 
                     27: 
                     28: 
                     29: 
                     30: 
                     31: */
                     32: 
                     33: 
                     34: 
                     35: 
                     36: /* $Log:       rcsrev.c,v $
                     37:  * Revision 4.5  89/05/01  15:13:22  narten
                     38:  * changed copyright header to reflect current distribution rules
                     39:  * 
                     40:  * Revision 4.4  87/12/18  11:45:22  narten
                     41:  * more lint cleanups. Also, the NOTREACHED comment is no longer necessary, 
                     42:  * since there's now a return value there with a value. (Guy Harris)
                     43:  * 
                     44:  * Revision 4.3  87/10/18  10:38:42  narten
                     45:  * Updating version numbers. Changes relative to version 1.1 actually 
                     46:  * relative to 4.1
                     47:  * 
                     48:  * Revision 1.3  87/09/24  14:00:37  narten
                     49:  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
                     50:  * warnings)
                     51:  * 
                     52:  * Revision 1.2  87/03/27  14:22:37  jenkins
                     53:  * Port to suns
                     54:  * 
                     55:  * Revision 1.1  84/01/23  14:50:37  kcs
                     56:  * Initial revision
                     57:  * 
                     58:  * Revision 4.1  83/03/25  21:10:45  wft
                     59:  * Only changed $Header to $Id.
                     60:  * 
                     61:  * Revision 3.4  82/12/04  13:24:08  wft
                     62:  * Replaced getdelta() with gettree().
                     63:  *
                     64:  * Revision 3.3  82/11/28  21:33:15  wft
                     65:  * fixed compartial() and compnum() for nil-parameters; fixed nils
                     66:  * in error messages. Testprogram output shortenend.
                     67:  *
                     68:  * Revision 3.2  82/10/18  21:19:47  wft
                     69:  * renamed compnum->cmpnum, compnumfld->cmpnumfld,
                     70:  * numericrevno->numricrevno.
                     71:  *
                     72:  * Revision 3.1  82/10/11  19:46:09  wft
                     73:  * changed expandsym() to check for source==nil; returns zero length string
                     74:  * in that case.
                     75:  */
                     76: 
                     77: 
                     78: 
                     79: /*
                     80: #define REVTEST
                     81: /* version REVTEST is for testing the routines that generate a sequence
                     82:  * of delta numbers needed to regenerate a given delta.
                     83:  */
                     84: 
                     85: #include "rcsbase.h"
                     86: 
                     87: extern FILE * finptr;   /* RCS input file */
                     88: extern char * getid();
                     89: extern struct hshentry * getnum();
                     90: extern int    getkey();
                     91: extern int    getlex();
                     92: 
                     93: extern char * getkeyval();
                     94: struct hshentry * genbranch(); /* forward */
                     95: 
                     96: 
                     97: 
                     98: int countnumflds(s)
                     99: char * s;
                    100: /* Given a pointer s to a dotted number (date or revision number),
                    101:  * countnumflds returns the number of digitfields in s.
                    102:  */
                    103: {       register char * sp;
                    104:         register int    count;
                    105:         if ((sp=s)==nil) return(0);
                    106:         if (*sp == '\0') return(0);
                    107:         count = 1;
                    108:         while (*sp) {
                    109:                 if (*sp++ == '.') count++;
                    110:         }
                    111:         if (*(--sp) == '.') count--; /*trailing periods don't count*/
                    112:         return(count);
                    113: }
                    114: 
                    115: getbranchno(revno,branchno)
                    116: char * revno, * branchno;
                    117: /* Given a non-nil revision number revno, getbranchno copies the number of the branch
                    118:  * on which revno is into branchnumber. If revno itself is a branch number,
                    119:  * it is copied unchanged.
                    120:  */
                    121: {
                    122:         register int i, numflds;
                    123:         register char * tp, * sp;
                    124: 
                    125:         numflds=countnumflds(revno);
                    126:         if (numflds%2 == 1)
                    127:                 VOID strcpy(branchno,revno);
                    128:         else {
                    129:                 sp=revno; tp=branchno;
                    130:                 for (i=1;i<numflds;i++) {
                    131:                         while(*sp!='.') *tp++ = *sp++;
                    132:                         *tp++ = *sp++;
                    133:                 }
                    134:                 *(tp-1)='\0';
                    135:         }
                    136: }
                    137: 
                    138: 
                    139: 
                    140: int cmpnum(num1, num2)
                    141: char * num1, * num2;
                    142: /* compares the two dotted numbers num1 and num2 lexicographically
                    143:  * by field. Individual fields are compared numerically.
                    144:  * returns <0, 0, >0 if num1<num2, num1==num2, and num1>num2, resp.
                    145:  * omitted fields are assumed to be higher than the existing ones.
                    146: */
                    147: {
                    148:         register char * s1, *s2;
                    149:         register int n1, n2;
                    150: 
                    151:         s1=num1==nil?"":num1;
                    152:         s2=num2==nil?"":num2;
                    153: 
                    154:         do {
                    155:                 n1 = 0;
                    156:                 while (('0' <= *s1) && (*s1 <= '9')) {
                    157:                         n1 = n1*10 + (*s1 - '0');
                    158:                         s1++;
                    159:                 }
                    160:                 /* skip '.' */
                    161:                 if (*s1=='.') s1++;
                    162: 
                    163:                 n2 = 0;
                    164:                 while (('0' <= *s2) && (*s2 <= '9')) {
                    165:                         n2 = n2*10 + (*s2 - '0');
                    166:                         s2++;
                    167:                 }
                    168:                 /* skip '.' */
                    169:                 if (*s2=='.') s2++;
                    170: 
                    171:         } while ((n1==n2) && (*s1!='\0') && (*s2!='\0'));
                    172: 
                    173:         if (((*s1=='\0') && (*s2=='\0')) || (n1!=n2))
                    174:                 return (n1 - n2);
                    175:         /*now n1==n2 and one of s1 or s2 is shorter*/
                    176:         /*give precedence to shorter one*/
                    177:         if (*s1=='\0') return 1;
                    178:         else           return -1;
                    179: 
                    180: }
                    181: 
                    182: 
                    183: 
                    184: int cmpnumfld(num1, num2, fld)
                    185: char * num1, * num2; int fld;
                    186: /* compares the two dotted numbers at field fld and returns
                    187:  * num1[fld]-num2[fld]. Assumes that num1 and num2 have at least fld fields.
                    188: */
                    189: {
                    190:         register char * s1, *s2;
                    191:         register int n1, n2;
                    192: 
                    193:         s1=num1; n1=fld-1;
                    194:         /* skip fld-1 fields */
                    195:         while (n1) {
                    196:                 while(*s1 != '.') s1++;
                    197:                 n1--; s1++;
                    198:         }
                    199:         s2 = num2; n2=fld-1;
                    200:         while (n2) {
                    201:                 while(*s2 != '.') s2++;
                    202:                 n2--; s2++;
                    203:         }
                    204:         /* Don't put the above into a single loop! */
                    205:         /* Now s1 and s2 point to the beginning of the respective fields */
                    206:         /* compute numerical value and compare */
                    207:         n1 = 0;
                    208:         while (('0' <= *s1) && (*s1 <= '9')) {
                    209:                 n1 = n1*10 + (*s1 - '0');
                    210:                 s1++;
                    211:         }
                    212:         n2 = 0;
                    213:         while (('0' <= *s2) && (*s2 <= '9')) {
                    214:                 n2 = n2*10 + (*s2 - '0');
                    215:                 s2++;
                    216:         }
                    217:         return (n1 - n2);
                    218: }
                    219: 
                    220: 
                    221: int compartial(num1, num2, length)
                    222: char    * num1;
                    223: char    * num2;
                    224: int     length;
                    225: 
                    226: /*   compare the first "length" fields of two dot numbers;
                    227:      the omitted field is considered to be larger than any number  */
                    228: /*   restriction:  at least one number has length or more fields   */
                    229: 
                    230: {
                    231:         register        char    *s1, *s2;
                    232:         register        int     n1, n2;
                    233: 
                    234: 
                    235:         s1 = num1;      s2 = num2;
                    236:         if ( s1==nil || *s1 == '\0' ) return 1;
                    237:         if ( s2==nil || *s2 == '\0' ) return -1;
                    238: 
                    239:         do {
                    240:             n1 = 0;
                    241:             while( ('0' <= *s1) && (*s1 <= '9') ) {
                    242:                 n1 = n1 * 10 + (*s1 - '0') ;
                    243:                 s1++;
                    244:             }
                    245:             if ( *s1 == '.' ) s1++;    /*  skip .   */
                    246: 
                    247:             n2 = 0;
                    248:             while( ( '0' <= *s2) && ( *s2 <= '9' ) ) {
                    249:                    n2 = n2 * 10 + ( *s2 - '0' ) ;
                    250:                 s2++;
                    251:             }
                    252:             if (*s2 == '.') s2++;
                    253:         }   while(  ( n1 == n2) && ((--length) != 0) &&
                    254:                     ( *s1 != '\0') && (*s2 != '\0')  );
                    255: 
                    256:         if ( (n1 != n2) || (length == 0) ){
                    257:                 return(n1-n2);   }
                    258: 
                    259:         if ( *s1 == '\0' ) return 1;
                    260:         if ( *s2 == '\0' ) return -1;
                    261:        VOID fprintf(stderr, "RCS Internal error, routine: compartial\n");
                    262:        return(0);
                    263: }
                    264: 
                    265: 
                    266: 
                    267: incnum(onum,nnum)
                    268: char * onum, *nnum;
                    269: /* increments the last field of revision number onum by one and
                    270:  * places the result into nnum
                    271:  */
                    272: {
                    273:         register char * sp, *tp;
                    274:         register int i;
                    275: 
                    276:         sp = onum; tp = nnum;
                    277:         for (i=countnumflds(onum)-1; i>0; i--) {
                    278:                 while (*sp != '.') *tp++ = *sp++;
                    279:                 *tp++ = *sp++;  /* copy dot also */
                    280:         }
                    281:         VOID sprintf(tp,"%d",atoi(sp)+1);
                    282: }
                    283: 
                    284: 
                    285: char * partialno(rev1,rev2,length)
                    286: char * rev1, * rev2; register int length;
                    287: /* Function: Copies length fields of revision number rev2 into rev1.
                    288:  * returns rev1.
                    289:  */
                    290: {       register char * r1,* r2;
                    291: 
                    292:         r1=rev1; r2=rev2;
                    293:         while (length) {
                    294:                 while(*r2 != '.' && *r2!='\0') *r1++ = *r2++;
                    295:                 *r1++ = *r2++;
                    296:                 length--;
                    297:         }
                    298:         /* eliminate last '.'*/
                    299:         *(r1-1)='\0';
                    300:         return rev1;
                    301: }
                    302: 
                    303: 
                    304: 
                    305: char * getancestor(r1, r2, r3)
                    306: char * r1, *r2, *r3;
                    307: /* function: finds the common ancestor of r1 and r2 and
                    308:  * places it into r3.
                    309:  * returns r3 if successful, false otherwise.
                    310:  * works reliably only if r1 and r2 are not branch numbers.
                    311:  */
                    312: {       int l1, l2, l3;
                    313:         char t1[revlength], t2[revlength];
                    314: 
                    315:         l1=countnumflds(r1); l2=countnumflds(r2);
                    316:         if ((l1<=2 && l2<=2)||(cmpnum(r1,r2)==0)) {
                    317:                 /* on main trunk or identical */
                    318:                 error("Common ancestor of %s and %s undefined.", r1, r2);
                    319:                 return false;
                    320:         }
                    321: 
                    322:         l3=0;
                    323:         while ((cmpnumfld(r1, r2, l3+1)==0) && (cmpnumfld(r1, r2, l3+2)==0)){
                    324:                 l3=l3+2;
                    325:         }
                    326:         /* This will terminate since r1 and r2 are not the same; see above*/
                    327:         if (l3==0) {
                    328:                 /* no common prefix. Common ancestor on main trunk. */
                    329:                 VOID partialno(t1,r1,l1>2?2:l1); VOID partialno(t2,r2,l2>2?2:l2);
                    330:                 if (cmpnum(t1,t2)<0)
                    331:                         VOID strcpy(r3,t1);
                    332:                 else    VOID strcpy(r3,t2);
                    333:                 if ((cmpnum(r3,r1)==0)||(cmpnum(r3,r2)==0)) {
                    334:                         error("Ancestor for %s and %s undefined.",r1,r2);
                    335:                         return false;
                    336:                 }
                    337:                 return r3;
                    338:         } else {
                    339:                if (cmpnumfld(r1,r2,l3+1)==0) {
                    340:                         error("Ancestor for %s and %s undefined.",r1,r2);
                    341:                         return false;
                    342:                 }
                    343:                 return(partialno(r3,r1,l3));
                    344:         }
                    345: }
                    346: 
                    347: 
                    348: 
                    349: 
                    350: struct hshentry * genrevs(revno,date,author,state,store)
                    351: char * revno, * date, * author, * state;
                    352: struct hshentry * * store;
                    353: /* Function: finds the deltas needed for reconstructing the
                    354:  * revision given by revno, date, author, and state, and stores pointers
                    355:  * to these deltas into an array whose starting address is given by store.
                    356:  * The last pointer stored is nil. The last delta (target delta) is returned.
                    357:  * If the proper delta could not be found, nil is returned.
                    358:  */
                    359: {
                    360:         int length;
                    361:         register struct hshentry * next;
                    362:         int result;
                    363:         char * branchnum;
                    364:         char t[revlength];
                    365: 
                    366:         if (Head == nil) {
                    367:                 error("RCSfile empty.");
                    368:                 return nil;
                    369:         }
                    370: 
                    371:         length = countnumflds(revno);
                    372:         next=Head;
                    373: 
                    374:         if (length >= 1) {
                    375:                 /* at least one field; find branch exactly */
                    376:                 while ((next!=nil) &&
                    377:                        ((result=cmpnumfld(revno,next->num,1))<0)) {
                    378:                         /*puts(next->num);*/
                    379:                         *store++ = next;
                    380:                         next = next->next;
                    381:                 }
                    382: 
                    383:                 if (next==nil) {error("Branch number %s too low.",partialno(t,revno,1));return nil;}
                    384:                 if (result>0)  {error("Branch number %s not present.",partialno(t,revno,1));return nil;}
                    385:         }
                    386:         if (length<=1){
                    387:                 /* pick latest one on given branch */
                    388:                 branchnum = next->num; /* works even for empty revno*/
                    389:                 while ((next!=nil) &&
                    390:                        (cmpnumfld(branchnum,next->num,1)==0) &&
                    391:                        !(
                    392:                         (date==nil?1:(cmpnum(date,next->date)>=0)) &&
                    393:                         (author==nil?1:(strcmp(author,next->author)==0)) &&
                    394:                         (state ==nil?1:(strcmp(state, next->state) ==0))
                    395:                         )
                    396:                        )
                    397:                 {       /*puts(next->num);*/
                    398:                         *store ++ = next;
                    399:                         next=next->next;
                    400:                 }
                    401:                 if ((next==nil) ||
                    402:                     (cmpnumfld(branchnum,next->num,1)!=0))/*overshot*/ {
                    403:                         error("Cannot find revision on branch %s with a date before %s, author %s, and state %s.",
                    404:                                 length==0?partialno(t,branchnum,1):revno,date==nil?"<now>":date,
                    405:                                 author==nil?"<any>":author, state==nil?"<any>":state);
                    406:                         return nil;
                    407:                 } else {
                    408:                         /*puts(next->num);*/
                    409:                         *store++ = next;
                    410:                 }
                    411:                 *store = nil;
                    412:                 return next;
                    413:         }
                    414: 
                    415:         /* length >=2 */
                    416:         /* find revision; may go low if length==2*/
                    417:         while ((next!=nil) &&
                    418:                ((result =cmpnumfld(revno,next->num,2)) <0) &&
                    419:                (cmpnumfld(revno,next->num,1)==0) ) {
                    420:                 /*puts(next->num);*/
                    421:                 *store++ = next;
                    422:                 next = next->next;
                    423:         }
                    424: 
                    425:         if ((next==nil) || (cmpnumfld(revno,next->num,1)!=0)) {
                    426:                 error("Revision number %s too low.",partialno(t,revno,2));
                    427:                 return nil;
                    428:         }
                    429:         if ((length>2) && (result!=0)) {
                    430:                 error("Revision %s not present.",partialno(t,revno,2));
                    431:                 return nil;
                    432:         }
                    433: 
                    434:         /* print last one */
                    435:         /*puts(next->num);*/
                    436:         *store++ = next;
                    437: 
                    438:         if (length>2)
                    439:                 return genbranch(next,revno,length,date,author,state,store);
                    440:         else { /* length == 2*/
                    441:                 if ((date!=nil) && (cmpnum(date,next->date)<0)){
                    442:                         error("Revision %s has date %s.",next->num, next->date);
                    443:                         return nil;
                    444:                 }
                    445:                 if ((author!=nil)&&(strcmp(author,next->author)!=0)) {
                    446:                         error("Revision %s has author %s.",next->num,next->author);
                    447:                         return nil;
                    448:                 }
                    449:                 if ((state!=nil)&&(strcmp(state,next->state)!=0)) {
                    450:                         error("Revision %s has state %s.",next->num,
                    451:                                next->state==nil?"<empty>":next->state);
                    452:                         return nil;
                    453:                 }
                    454:                 *store=nil;
                    455:                 return next;
                    456:         }
                    457: }
                    458: 
                    459: 
                    460: 
                    461: 
                    462: struct hshentry * genbranch(bpoint, revno, length,date,author,state,store)
                    463: struct hshentry * bpoint;
                    464: char * revno; int length;
                    465: char * date, * author, * state;
                    466: struct hshentry ** store;
                    467: /* Function: given a branchpoint, a revision number, date, author, and state,
                    468:  * genbranch finds the deltas necessary to reconstruct the given revision
                    469:  * from the branch point on.
                    470:  * Pointers to the found deltas are stored in an array beginning with store.
                    471:  * revno must be on a side branch.
                    472:  * return nil on error
                    473:  */
                    474: {
                    475:         int field;
                    476:         register struct hshentry * next, * trail;
                    477:         register struct branchhead * bhead;
                    478:         int result;
                    479:         char t[revlength];
                    480: 
                    481:         bhead = bpoint->branches;
                    482: 
                    483:         for (field=3; field<=length; field=field+2) {
                    484: 
                    485:                 if (bhead==nil) {error("No side branches present for %s.",partialno(t,revno,field-1));return nil;}
                    486: 
                    487:                 /*find branch head*/
                    488:                 /*branches are arranged in increasing order*/
                    489:                 while ((bhead!=nil) &&
                    490:                        ((result=cmpnumfld(revno,bhead->hsh->num,field))>0)) {
                    491:                         bhead = bhead->nextbranch;
                    492:                 }
                    493: 
                    494:                 if (bhead==nil) {error("Branch number %s too high.",partialno(t,revno,field));return nil;}
                    495:                 if (result<0)   {error("Branch number %s not present.",partialno(t,revno,field));return nil;}
                    496: 
                    497:                 next = bhead->hsh;
                    498:                 if (length==field) {
                    499:                         /* pick latest one on that branch */
                    500:                         trail=nil;
                    501:                         do { if ((date==nil?1:(cmpnum(date,next->date)>=0)) &&
                    502:                                  (author==nil?1:(strcmp(author,next->author)==0)) &&
                    503:                                  (state ==nil?1:(strcmp(state, next->state) ==0))
                    504:                              ) trail = next;
                    505:                              next=next->next;
                    506:                         } while (next!=nil);
                    507: 
                    508:                         if (trail==nil) {
                    509:                              error("Cannot find revision on branch %s with a date before %s, author %s, and state %s.",
                    510:                                         revno, date==nil?"<now>":date,
                    511:                                         author==nil?"<any>":author, state==nil?"<any>":state);
                    512:                              return nil;
                    513:                         } else { /* print up to last one suitable */
                    514:                              next = bhead->hsh;
                    515:                              while (next!=trail) {
                    516:                                   /*puts(next->num);*/
                    517:                                   *store++ = next;
                    518:                                   next=next->next;
                    519:                              }
                    520:                              /*puts(next->num);*/
                    521:                              *store++ = next;
                    522:                         }
                    523:                         *store = nil;
                    524:                         return next;
                    525:                 }
                    526: 
                    527:                 /* length > field */
                    528:                 /* find revision */
                    529:                 /* check low */
                    530:                 if (cmpnumfld(revno,next->num,field+1)<0) {
                    531:                         error("Revision number %s too low.",partialno(t,revno,field+1));
                    532:                         return(nil);
                    533:                 }
                    534:                 do {    /*puts(next->num);*/
                    535:                         *store++ = next;
                    536:                         trail = next;
                    537:                         next = next->next;
                    538:                 } while ((next!=nil) &&
                    539:                        (cmpnumfld(revno,next->num,field+1) >=0));
                    540: 
                    541:                 if ((length>field+1) &&  /*need exact hit */
                    542:                     (cmpnumfld(revno,trail->num,field+1) !=0)){
                    543:                         error("Revision %s not present.",partialno(t,revno,field+1));
                    544:                         return(nil);
                    545:                 }
                    546:                 if (length == field+1) {
                    547:                         if ((date!=nil) && (cmpnum(date,trail->date)<0)){
                    548:                                 error("Revision %s has date %s.",trail->num, trail->date);
                    549:                                 return nil;
                    550:                         }
                    551:                         if ((author!=nil)&&(strcmp(author,trail->author)!=0)) {
                    552:                                 error("Revision %s has author %s.",trail->num,trail->author);
                    553:                                 return nil;
                    554:                         }
                    555:                         if ((state!=nil)&&(strcmp(state,trail->state)!=0)) {
                    556:                                 error("Revision %s has state %s.",trail->num,
                    557:                                        trail->state==nil?"<empty>":trail->state);
                    558:                                 return nil;
                    559:                         }
                    560:                 }
                    561:                 bhead = trail->branches;
                    562: 
                    563:         }
                    564:         * store = nil;
                    565:         return trail;
                    566: }
                    567: 
                    568: 
                    569: char * lookupsym(id)
                    570: char * id;
                    571: /* Function: looks up id in the list of symbolic names starting
                    572:  * with pointer SYMBOLS, and returns a pointer to the corresponding
                    573:  * revision number. Returns nil if not present.
                    574:  */
                    575: {
                    576:         register struct assoc * next;
                    577:         next = Symbols;
                    578:         while (next!=nil) {
                    579:                 if (strcmp(id, next->symbol)==0)
                    580:                         return(next->delta->num);
                    581:                 else    next=next->nextassoc;
                    582:         }
                    583:         return nil;
                    584: }
                    585: 
                    586: int expandsym(source, target)
                    587: char * source, * target;
                    588: /* Function: Source points to a revision number. Expandsym copies
                    589:  * the number to target, but replaces all symbolic fields in the
                    590:  * source number with their numeric values.
                    591:  * A trailing '.' is omitted; leading zeroes are compressed.
                    592:  * returns false on error;
                    593:  */
                    594: {       register char * sp, * tp, *bp;
                    595:         char symbuf[30];
                    596:         register enum tokens d;
                    597: 
                    598:         sp = source; tp=target;
                    599:         if (sp == nil) { /*accept nil pointer as a legal value*/
                    600:                 *tp='\0';
                    601:                 return true;
                    602:         }
                    603: 
                    604:         while (*sp != '\0') {
                    605:                 if (ctab[*sp] == DIGIT) {
                    606:                         if (*sp=='0') {
                    607:                                 /* skip leading zeroes */
                    608:                                 sp++;
                    609:                                 while(*sp == '0') sp++;
                    610:                                 if (*sp=='\0' || *sp=='.') *tp++ = '0'; /*single zero*/
                    611:                         }
                    612:                         while(ctab[*sp] == DIGIT) *tp++ = *sp++;
                    613:                         if ((*sp == '\0') || ((*sp=='.')&&(*(sp+1)=='\0'))) {
                    614:                                 *tp='\0'; return true;
                    615:                         }
                    616:                         if (*sp == '.') *tp++ = *sp++;
                    617:                         else {
                    618:                             error("Improper revision number: %s",source);
                    619:                             *tp = '\0';
                    620:                             return false;
                    621:                         }
                    622:                 } elsif (ctab[*sp] == LETTER) {
                    623:                         bp = symbuf;
                    624:                         do {    *bp++ = *sp++;
                    625:                         } while(((d=ctab[*sp])==LETTER) || (d==DIGIT) ||
                    626:                               (d==IDCHAR));
                    627:                         *bp= '\0';
                    628:                         bp=lookupsym(symbuf);
                    629:                         if (bp==nil) {
                    630:                                 error("Symbolic number %s is undefined.",symbuf);
                    631:                                 *tp='\0';
                    632:                                 return false;
                    633:                         } else { /* copy number */
                    634:                                 while (*tp++ = *bp++); /* copies the trailing \0*/
                    635:                         }
                    636:                         if ((*sp == '\0') || ((*sp=='.')&&(*(sp+1)=='\0')))
                    637:                                 return true;
                    638:                         if (*sp == '.')  {
                    639:                                 *(tp-1) = *sp++;
                    640:                         } else {
                    641:                                 error("Improper revision number: %s",source);
                    642:                                 return false;
                    643:                         }
                    644:                 }else {
                    645:                         error("Improper revision number: %s", source);
                    646:                         *tp = '\0';
                    647:                         return false;
                    648:                 }
                    649:         }
                    650:         *tp = '\0';
                    651:         return true;
                    652: }
                    653: 
                    654: 
                    655: 
                    656: #ifdef REVTEST
                    657: 
                    658: main(argc,argv)
                    659: int argc; char * argv[];
                    660: {
                    661:         char symrevno[revlength];       /* used for input of revision numbers */
                    662:         char numricrevno[revlength];
                    663:         char author[20];
                    664:         char state[20];
                    665:         char date[20];
                    666:         struct hshentry * gendeltas[hshsize/2];
                    667:         struct hshentry * target;
                    668:         int i;
                    669: 
                    670:         cmdid = "revtest";
                    671:         if (argc<2) {
                    672:                 VOID fputs("No input file\n",stderr);
                    673:                 exit(-1);
                    674:         }
                    675:         if ((finptr=fopen(argv[1], "r")) == NULL) {
                    676:                 faterror("Can't open input file %s\n",argv[1]);
                    677:         }
                    678:         Lexinit();
                    679:         getadmin();
                    680: 
                    681:         gettree();
                    682: 
                    683:         getdesc(false);
                    684: 
                    685:         do {
                    686:                 /* all output goes to stderr, to have diagnostics and       */
                    687:                 /* errors in sequence.                                      */
                    688:                 VOID fprintf(stderr,"\nEnter revision number or <return> or '.': ");
                    689:                 if(gets(symrevno)==NULL) break;
                    690:                 if (*symrevno == '.') break;
                    691:                 VOID fprintf(stderr,"%s;\n",symrevno);
                    692:                 expandsym(symrevno,numricrevno);
                    693:                 VOID fprintf(stderr,"expanded number: %s; ",numricrevno);
                    694:                 VOID fprintf(stderr,"Date: ");
                    695:                 gets(date); VOID fprintf(stderr,"%s; ",date);
                    696:                 VOID fprintf(stderr,"Author: ");
                    697:                 gets(author);VOID fprintf(stderr,"%s; ",author);
                    698:                 VOID fprintf(stderr,"State: ");
                    699:                 gets(state); VOID fprintf(stderr, "%s;\n", state);
                    700:                 target=genrevs(numricrevno,*date=='\0'?(char *)nil:date, *author=='\0'?(char *)nil:author,
                    701:                               *state=='\0'?(char *)nil:state,gendeltas);
                    702:                 if (target!=nil) {
                    703:                         i=0;
                    704:                         while (gendeltas[i]!=nil) {
                    705:                                 VOID fprintf(stderr,"%s\n",gendeltas[i++]->num);
                    706:                         }
                    707:                 }
                    708:         } while (true);
                    709:         VOID fprintf(stderr,"done\n");
                    710: 
                    711: }
                    712: 
                    713: cleanup(){}
                    714: /*dummy*/
                    715: 
                    716: #endif REVTEST

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.