Annotation of 43BSD/contrib/rcs/src/rcsedit.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *                     RCS stream editor
        !             3:  */
        !             4:  static char rcsid[]=
        !             5:  "$Header: rcsedit.c,v 3.8 86/05/15 02:15:43 lepreau Exp $ Purdue CS";
        !             6: /**********************************************************************************
        !             7:  *                       edits the input file according to a
        !             8:  *                       script from stdin, generated by diff -n
        !             9:  *                       performs keyword expansion
        !            10:  **********************************************************************************
        !            11:  *
        !            12:  * Copyright (C) 1982 by Walter F. Tichy
        !            13:  *                       Purdue University
        !            14:  *                       Computer Science Department
        !            15:  *                       West Lafayette, IN 47907
        !            16:  *
        !            17:  * All rights reserved. No part of this software may be sold or distributed
        !            18:  * in any form or by any means without the prior written permission of the
        !            19:  * author.
        !            20:  * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
        !            21:  */
        !            22: 
        !            23: 
        !            24: /* $Log:       rcsedit.c,v $
        !            25:  * Revision 3.8  86/05/15  02:15:43  lepreau
        !            26:  * Use "Locked" instead of state in $Head expansion if locked.
        !            27:  * 
        !            28:  * Revision 3.7  83/05/12  13:04:39  wft
        !            29:  * *** empty log message ***
        !            30:  * 
        !            31:  * Revision 3.7  83/05/12  13:04:39  wft
        !            32:  * Added retry to expandline to resume after failed match which ended in $.
        !            33:  * Fixed truncation problem for $19chars followed by@@.
        !            34:  * Log no longer expands full path of RCS file.
        !            35:  * 
        !            36:  * Revision 3.5  82/12/04  13:20:56  wft
        !            37:  * Added expansion of keyword Locker.
        !            38:  * 
        !            39:  * Revision 3.4  82/12/03  12:26:54  wft
        !            40:  * Added line number correction in case editing does not start at the
        !            41:  * beginning of the file.
        !            42:  * Changed keyword expansion to always print a space before closing KDELIM;
        !            43:  * Expansion for Header shortened.
        !            44:  *
        !            45:  * Revision 3.3  82/11/14  14:49:30  wft
        !            46:  * removed Suffix from keyword expansion. Replaced fclose with ffclose.
        !            47:  * keyreplace() gets log message from delta, not from curlogmsg.
        !            48:  * fixed expression overflow in while(c=putc(GETC....
        !            49:  * checked nil printing.
        !            50:  *
        !            51:  * Revision 3.2  82/10/18  21:13:39  wft
        !            52:  * I added checks for write errors during the co process, and renamed
        !            53:  * expandstring() to xpandstring().
        !            54:  *
        !            55:  * Revision 3.1  82/10/13  15:52:55  wft
        !            56:  * changed type of result of getc() from char to int.
        !            57:  * made keyword expansion loop in expandline() portable to machines
        !            58:  * without sign-extension.
        !            59:  */
        !            60: 
        !            61: 
        !            62: #include "rcsbase.h"
        !            63: 
        !            64: 
        !            65: extern FILE * fopen();
        !            66: extern char * mktempfile();
        !            67: extern FILE * finptr, * frewrite;
        !            68: extern int rewriteflag;
        !            69: extern int nextc;
        !            70: extern char * getfullRCSname();
        !            71: extern char * RCSfilename;
        !            72: 
        !            73: 
        !            74: FILE  * fcopy,  * fedit; /* result and edit file descriptors                */
        !            75: char  *resultfile = nil; /* result file name                                */
        !            76: char  * editfile  = nil; /* edit   file name                                */
        !            77: int editline;  /*line counter in fedit; starts with 1, is always #lines+1   */
        !            78: int linecorr;  /*contains #adds - #deletes in each edit run.                */
        !            79:                /*used to correct editline in case file is not rewound after */
        !            80:                /* applying one delta                                        */
        !            81: 
        !            82: initeditfiles(dir)
        !            83: char * dir;
        !            84: /* Function: Initializes resultfile and editfile with temporary filenames
        !            85:  * in directory dir. Opens resultfile for reading and writing, with fcopy
        !            86:  * as file descriptor. fedit is set to nil.
        !            87:  */
        !            88: {
        !            89:         resultfile=mktempfile(dir,TMPFILE1);
        !            90:         editfile  =mktempfile(dir,TMPFILE2);
        !            91:         fedit=nil;
        !            92:         if ((fcopy=fopen(resultfile,"w+"))==NULL) {
        !            93:                 faterror("Can't open working file %s",resultfile);
        !            94:         }
        !            95: }
        !            96: 
        !            97: 
        !            98: swapeditfiles(tostdout)
        !            99: /* Function: swaps resultfile and editfile, assigns fedit=fcopy,
        !           100:  * rewinds fedit for reading, and opens resultfile for reading and
        !           101:  * writing, using fcopy. If tostdout, fcopy is set to stdout.
        !           102:  */
        !           103: {       char * tmpptr;
        !           104:         if(ferror(fcopy))
        !           105:                 faterror("write failed on %s -- file system full?",resultfile);
        !           106:         fedit=fcopy;
        !           107:         rewind(fedit);
        !           108:         editline = 1; linecorr=0;
        !           109:         tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
        !           110:         if (tostdout)
        !           111:                 fcopy=stdout;
        !           112:         elsif ((fcopy=fopen(resultfile,"w+"))==NULL) {
        !           113:                 faterror("Can't open working file %s",resultfile);
        !           114:         }
        !           115: }
        !           116: 
        !           117: 
        !           118: finishedit(delta)
        !           119: struct hshentry * delta;
        !           120: /* copy the rest of the edit file and close it (if it exists).
        !           121:  * if delta!=nil, perform keyword substitution at the same time.
        !           122:  */
        !           123: {
        !           124:         register int c;
        !           125:         if (fedit!=nil) {
        !           126:                 if (delta!=nil) {
        !           127:                         while (expandline(fedit,fcopy,delta,false,false)) editline++;
        !           128:                 } else {
        !           129:                         while((c=getc(fedit))!=EOF) {
        !           130:                                 putc(c,fcopy);
        !           131:                                 if (c=='\n') editline++;
        !           132:                         }
        !           133:                 }
        !           134:                 ffclose(fedit);
        !           135:         }
        !           136: }
        !           137: 
        !           138: 
        !           139: copylines(line,delta)
        !           140: register int line; struct hshentry * delta;
        !           141: /* Function: copies input lines editline..line-1 from fedit to fcopy.
        !           142:  * If delta != nil, keyword expansion is done simultaneously.
        !           143:  * editline is updated. Rewinds a file only if necessary.
        !           144:  */
        !           145: {
        !           146: 
        !           147:         if (editline>line) {
        !           148:                 /* swap files */
        !           149:                 finishedit(nil); swapeditfiles(false);
        !           150:                 /* assumes edit only during last pass, from the beginning*/
        !           151:         }
        !           152:         while (editline<line) {
        !           153:                 /*copy another line*/
        !           154:                 if (delta)
        !           155:                         expandline(fedit,fcopy,delta,false,false);
        !           156:                 else
        !           157:                         while (putc(getc(fedit),fcopy)!='\n');
        !           158:                 editline++;
        !           159:         }
        !           160: }
        !           161: 
        !           162: 
        !           163: 
        !           164: xpandstring(delta)
        !           165: struct hshentry * delta;
        !           166: /* Function: Reads a string terminated by SDELIM from finptr and writes it
        !           167:  * to fcopy. Double SDELIM is replaced with single SDELIM.
        !           168:  * Keyword expansion is performed with data from delta.
        !           169:  * If rewriteflag==true, the string is also copied unchanged to frewrite.
        !           170:  * editline is updated.
        !           171:  */
        !           172: {
        !           173:         editline=1;
        !           174:         while (expandline(finptr,fcopy,delta,true,rewriteflag)) editline++;
        !           175:         nextc='\n';
        !           176: }
        !           177: 
        !           178: 
        !           179: copystring()
        !           180: /* Function: copies a string terminated with a single SDELIM from finptr to
        !           181:  * fcopy, replacing all double SDELIM with a single SDELIM.
        !           182:  * If rewriteflag==true, the string also copied unchanged to frewrite.
        !           183:  * editline is set to (number of lines copied)+1.
        !           184:  * Assumption: next character read is first string character.
        !           185:  */
        !           186: {       register c, write;
        !           187:         write=rewriteflag;
        !           188:         editline=1;
        !           189:         while ((c=GETC(finptr,frewrite,write)) != EOF) {
        !           190:                 if ((c==SDELIM)&&((c=GETC(finptr,frewrite,write)) != SDELIM)){
        !           191:                         /* end of string */
        !           192:                         nextc = c;
        !           193:                         return;
        !           194:                 }
        !           195:                 putc(c,fcopy);
        !           196:                 if (c=='\n') editline++;
        !           197:         }
        !           198:         nextc = c;
        !           199:         serror("Unterminated string");
        !           200:         return;
        !           201: }
        !           202: 
        !           203: 
        !           204: 
        !           205: 
        !           206: editstring(delta)
        !           207: struct hshentry * delta;
        !           208: /* Function: reads an edit script from finptr and applies it to
        !           209:  * file fedit; the result is written to fcopy.
        !           210:  * If delta!=nil, keyword expansion is performed simultaneously.
        !           211:  * If frewrite==true, the edit script is also copied verbatim to frewrite.
        !           212:  * Assumes that all these files are open.
        !           213:  * If running out of lines in fedit, fedit and fcopy are swapped.
        !           214:  * resultfile and editfile are the names of the files that go with fcopy
        !           215:  * and fedit, respectively.
        !           216:  * Assumes the next input character from finptr is the first character of
        !           217:  * the edit script. Resets nextc on exit.
        !           218:  */
        !           219: {
        !           220:         int ed; /* editor command */
        !           221:         register int c;
        !           222:         register int write, i;
        !           223:         int line, length;
        !           224: 
        !           225:         editline += linecorr; linecorr=0; /*correct line number*/
        !           226:         write=rewriteflag;
        !           227:         for (;;) {
        !           228:                 /* read next command and decode */
        !           229:                 /* assume next non-white character is command name*/
        !           230:                 while((ed=GETC(finptr,frewrite,write))=='\n'||
        !           231:                         ed==' ' || ed=='\t');
        !           232:                 if (ed==SDELIM) break;
        !           233:                 /* now attempt to read numbers. */
        !           234:                 /* fscanf causes trouble because of the required echoing */
        !           235:                 while ((c=GETC(finptr,frewrite,write))==' ');  /*skip spaces*/
        !           236:                 if (!('0'<=c && c<='9')) {
        !           237:                         faterror("missing line number in edit script");
        !           238:                         break;
        !           239:                 }
        !           240:                 line= c -'0';
        !           241:                 while ('0'<=(c=GETC(finptr,frewrite,write)) && c<='9') {
        !           242:                         line = line*10 + c-'0';
        !           243:                 }
        !           244:                 while (c==' ') c=GETC(finptr,frewrite,write);
        !           245:                 if (!('0'<=c && c<='9')) {
        !           246:                         faterror("incorrect range in edit script");
        !           247:                         break;
        !           248:                 }
        !           249:                 length= c -'0';
        !           250:                 while ('0'<=(c=GETC(finptr,frewrite,write)) && c<='9') {
        !           251:                         length = length*10 + c-'0';
        !           252:                 }
        !           253:                 while(c!='\n'&&c!=EOF) c=GETC(finptr,frewrite,write); /* skip to end of line */
        !           254: 
        !           255:                 switch (ed) {
        !           256:                 case 'd':
        !           257:                         copylines(line,delta);
        !           258:                         /* skip over unwanted lines */
        !           259:                         for (i=length;i>0;i--) {
        !           260:                                 /*skip next line*/
        !           261:                                 while ((c=getc(fedit))!='\n')
        !           262:                                        if (c==EOF)
        !           263:                                                faterror("EOF during edit");
        !           264:                                 editline++;
        !           265:                         }
        !           266:                         linecorr -= length;
        !           267:                         break;
        !           268:                 case 'a':
        !           269:                         copylines(line+1,delta); /*copy only; no delete*/
        !           270:                         for (i=length;i>0;i--) {
        !           271:                                 /*copy next line from script*/
        !           272:                                 if (delta!=nil)
        !           273:                                        expandline(finptr,fcopy,delta,true,write);
        !           274:                                 else {
        !           275:                                        c = GETC(finptr,frewrite,write);
        !           276:                                        while (putc(c,fcopy)!='\n'){
        !           277:                                                if ((c==SDELIM)&&((c=GETC(finptr,frewrite,write))!=SDELIM)){
        !           278:                                                        serror("Missing string delimiter in edit script");
        !           279:                                                        putc(c,fcopy);
        !           280:                                                }
        !           281:                                                c = GETC(finptr,frewrite,write);
        !           282:                                        }
        !           283:                                 }
        !           284:                         }
        !           285:                         linecorr += length;
        !           286:                         break;
        !           287:                 default:
        !           288:                         faterror("unknown command in edit script: %c", ed);
        !           289:                         break;
        !           290:                 }
        !           291:         }
        !           292:         nextc=GETC(finptr,frewrite,write);
        !           293: }
        !           294: 
        !           295: 
        !           296: 
        !           297: /* The rest if for keyword expansion */
        !           298: 
        !           299: struct { char * keyword; enum markers marker;} markertable[] =
        !           300:         {{AUTHOR,   Author  },
        !           301:          {DATE,     Date    },
        !           302:          {HEADER,   Header  },
        !           303:          {LOCKER,   Locker  },
        !           304:          {LOG,      Log     },
        !           305:          {REVISION, Revision},
        !           306:          {SOURCE,   Source  },
        !           307:          {STATE,    State   },
        !           308:          {nil,      Nomatch }};
        !           309: 
        !           310: enum markers trymatch(string)
        !           311: char * string;
        !           312: /* function: Checks whether string is a keyword.
        !           313:  * If so, returns the appropriate marker, otherwise Nomatch.
        !           314:  */
        !           315: {
        !           316:         register int j;
        !           317:         for (j=0; markertable[j].keyword!=nil; j++ ) {
        !           318:                 if (strcmp(string, markertable[j].keyword) ==0)
        !           319:                         return(markertable[j].marker);
        !           320:         }
        !           321:         return(Nomatch);
        !           322: }
        !           323: 
        !           324: 
        !           325: 
        !           326: expandline(in, out, delta,delimstuffed,write)
        !           327: FILE * in, * out; struct hshentry * delta;
        !           328: register int delimstuffed, write;
        !           329: /* Function: Reads a line from in and writes it to out.
        !           330:  * If delimstuffed==true, double SDELIM is replaced with single SDELIM.
        !           331:  * Keyword expansion is performed with data from delta.
        !           332:  * If write==true, the string is also copied unchanged to frewrite.
        !           333:  * Returns false if end-of-string or end-of-line is detected, true otherwise.
        !           334:  */
        !           335: {
        !           336:         register c, j;
        !           337:         char keystring[keylength];
        !           338:         char keyval[keyvallength];
        !           339:         enum markers matchresult;
        !           340: 
        !           341:         for (;;) {
        !           342:                 c=GETC(in,frewrite,write);
        !           343:                 if (c==EOF) {
        !           344:                         if(delimstuffed) {
        !           345:                                 error("unterminated string");
        !           346:                                 nextc=c;
        !           347:                         }
        !           348:                         return(false);
        !           349:                 }
        !           350: 
        !           351:                 if (c==SDELIM && delimstuffed) {
        !           352:                         if ((c=GETC(in,frewrite,write))!=SDELIM) {
        !           353:                                 /* end of string */
        !           354:                                 nextc=c;
        !           355:                                 return false;
        !           356:                         }
        !           357:                 }
        !           358:                 putc(c,out);
        !           359: 
        !           360:                 if (c=='\n') return true; /* end of line */
        !           361: 
        !           362: retry:          if (c==KDELIM) {
        !           363:                         /* check for keyword */
        !           364:                         /* first, copy a long enough string into keystring */
        !           365:                         j=0;
        !           366:                         while (((c=GETC(in,frewrite,write))!=EOF) && (j<keylength-1) && (c!='\n')
        !           367:                                && (c!=KDELIM) && (c!=VDELIM)) {
        !           368:                               putc(c,out);
        !           369:                               keystring[j++] = c;
        !           370:                               if (c==SDELIM && delimstuffed) { /*skip next SDELIM */
        !           371:                                         c=GETC(in,frewrite,write);
        !           372:                                         /* Can't be at end of string -- always a '\n' before*/
        !           373:                                         /* closing SDELIM */
        !           374:                               }
        !           375:                         }
        !           376:                         if (!((c==KDELIM) || (c==VDELIM))) {
        !           377:                                 /* no match */
        !           378:                                /* can get SDELIM here if have $...keylength-1 chars...@@ */
        !           379:                                if (c==SDELIM && delimstuffed) {
        !           380:                                        c=GETC(in,frewrite,write);
        !           381:                                }
        !           382:                                 putc(c,out);
        !           383:                                 if (c=='\n') return true; /* end of line */
        !           384:                         } else {
        !           385:                                 /* no we have something that looks like a  */
        !           386:                                 /* keyword, and is terminated with K/VDELIM*/
        !           387:                                 keystring[j]= '\0';
        !           388:                                 if ((matchresult=trymatch(keystring))==Nomatch) {
        !           389:                                       /* no match */
        !           390:                                       putc(c,out);
        !           391:                                      if (c==KDELIM) goto retry;
        !           392:                                 } elsif (c==VDELIM) {
        !           393:                                       /* try to find closing KDELIM, and replace value */
        !           394:                                       j=0;
        !           395:                                       while (((c=GETC(in,frewrite,write)) != EOF)
        !           396:                                              && (c!='\n') && (c!=KDELIM) && (j<keyvallength-2)) {
        !           397:                                              keyval[j++] =c;
        !           398:                                               if (c==SDELIM && delimstuffed) { /*skip next SDELIM */
        !           399:                                                         c=GETC(in,frewrite,write);
        !           400:                                                         /* Can't be at end of string -- always a '\n' before*/
        !           401:                                                         /* closing SDELIM */
        !           402:                                               }
        !           403:                                       }
        !           404:                                      keyval[j++] =c;
        !           405:                                       if (c!=KDELIM) {
        !           406:                                             /* couldn't find closing KDELIM -- give up */
        !           407:                                             putc(VDELIM,out); keyval[j]='\0';fputs(keyval,out);
        !           408:                                             if (c=='\n') return true; /* end of line */
        !           409:                                       } else {
        !           410:                                             /* found complete pattern -- replace */
        !           411:                                             keyreplace(matchresult,delta,out);
        !           412:                                       }
        !           413:                                 } else {
        !           414:                                       /* string of the form $keyword$ */
        !           415:                                       keyreplace(matchresult,delta,out);
        !           416:                                 }
        !           417:                         }
        !           418:                 }
        !           419:         } /* end for */
        !           420: }
        !           421: 
        !           422: 
        !           423: 
        !           424: keyreplace(marker,delta,out)
        !           425: enum markers marker; struct hshentry * delta; FILE * out;
        !           426: /* function: ouputs the keyword value(s) corresponding to marker.
        !           427:  * Attributes are derived from delta.
        !           428:  */
        !           429: {
        !           430:         char * date;
        !           431:         register char * sp;
        !           432: 
        !           433:         date= delta->date;
        !           434: 
        !           435:         switch (marker) {
        !           436:         case Author:
        !           437:                 fprintf(out,"%c %s %c",VDELIM,delta->author,KDELIM);
        !           438:                 break;
        !           439:         case Date:
        !           440:                 putc(VDELIM,out);putc(' ',out);
        !           441:                 PRINTDATE(out,date);putc(' ',out);
        !           442:                 PRINTTIME(out,date);putc(' ',out);putc(KDELIM,out);
        !           443:                 break;
        !           444:         case Header:
        !           445:                 fprintf(out,"%c %s %s ",VDELIM,bindex(RCSfilename,'/'),
        !           446:                                        delta->num);
        !           447:                 PRINTDATE(out,date);putc(' ',out);PRINTTIME(out,date);
        !           448:                if (delta->lockedby == nil)
        !           449:                        fprintf(out, " %s %s ", delta->author, delta->state);
        !           450:                else
        !           451:                        fprintf(out," %s Locked ", delta->lockedby);
        !           452:                putc(KDELIM, out);
        !           453:                 break;
        !           454:         case Locker:
        !           455:                 fprintf(out,"%c %s %c", VDELIM,
        !           456:                         delta->lockedby==nil?"":delta->lockedby,KDELIM);
        !           457:                 break;
        !           458:         case Log:
        !           459:                 fprintf(out, "%c\t%s %c\n%sRevision %s  ",
        !           460:                        VDELIM, bindex(RCSfilename,'/'), KDELIM, Comment, delta->num);
        !           461:                 PRINTDATE(out,date);fputs("  ",out);PRINTTIME(out,date);
        !           462:                 fprintf(out, "  %s\n%s",delta->author,Comment);
        !           463:                 /* do not include state here because it may change and is not updated*/
        !           464:                 sp = delta->log;
        !           465:                 while (*sp) if (putc(*sp++,out)=='\n') fputs(Comment,out);
        !           466:                 /* Comment is the comment leader */
        !           467:                 break;
        !           468:         case Revision:
        !           469:                 fprintf(out,"%c %s %c",VDELIM,delta->num,KDELIM);
        !           470:                 break;
        !           471:         case Source:
        !           472:                 fprintf(out,"%c %s %c",VDELIM,getfullRCSname(),KDELIM);
        !           473:                 break;
        !           474:         case State:
        !           475:                 fprintf(out,"%c %s %c",VDELIM,delta->state,KDELIM);
        !           476:                 break;
        !           477:         case Nomatch:
        !           478:                 putc(KDELIM,out);
        !           479:                 break;
        !           480:         }
        !           481: }
        !           482: 
        !           483: 

unix.superglobalmegacorp.com

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