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

unix.superglobalmegacorp.com

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