Annotation of 43BSDReno/contrib/rcs/src/rcsrev.c, revision 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.