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

1.1     ! root        1: /*
        !             2:  *                     RCS stream editor
        !             3:  */
        !             4: #ifndef lint
        !             5: static char rcsid[]= "$Id: rcsedit.c,v 3.11 89/08/15 21:37:31 bostic Exp $ Purdue CS";
        !             6: #endif
        !             7: /**********************************************************************************
        !             8:  *                       edits the input file according to a
        !             9:  *                       script from stdin, generated by diff -n
        !            10:  *                       performs keyword expansion
        !            11:  **********************************************************************************
        !            12:  */
        !            13: 
        !            14: /* Copyright (C) 1982, 1988, 1989 Walter Tichy
        !            15:  * All rights reserved.
        !            16:  *
        !            17:  * Redistribution and use in source and binary forms are permitted
        !            18:  * provided that the above copyright notice and this paragraph are
        !            19:  * duplicated in all such forms and that any documentation,
        !            20:  * advertising materials, and other materials related to such
        !            21:  * distribution and use acknowledge that the software was developed
        !            22:  * by Walter Tichy.
        !            23:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            26:  *
        !            27:  * Report all problems and direct all questions to:
        !            28:  *   [email protected]
        !            29:  * 
        !            30: 
        !            31: 
        !            32: 
        !            33: 
        !            34: 
        !            35: 
        !            36: 
        !            37: */
        !            38: 
        !            39: 
        !            40: /* $Log:       rcsedit.c,v $
        !            41:  * Revision 3.11  89/08/15  21:37:31  bostic
        !            42:  * Version 4 from Tom Narten at Purdue
        !            43:  * 
        !            44:  * Revision 4.8  89/05/01  15:12:35  narten
        !            45:  * changed copyright header to reflect current distribution rules
        !            46:  * 
        !            47:  * Revision 4.7  88/11/08  13:54:14  narten
        !            48:  * misplaced semicolon caused infinite loop
        !            49:  * 
        !            50:  * Revision 4.6  88/11/08  12:01:41  narten
        !            51:  * changes from  [email protected] (Paul Eggert)
        !            52:  * 
        !            53:  * Revision 4.6  88/08/09  19:12:45  eggert
        !            54:  * Shrink stdio code size; allow cc -R.
        !            55:  * 
        !            56:  * Revision 4.5  87/12/18  11:38:46  narten
        !            57:  * Changes from the 43. version. Don't know the significance of the
        !            58:  * first change involving "rewind". Also, additional "lint" cleanup.
        !            59:  * (Guy Harris)
        !            60:  * 
        !            61:  * Revision 4.4  87/10/18  10:32:21  narten
        !            62:  * Updating version numbers. Changes relative to version 1.1 actually
        !            63:  * relative to 4.1
        !            64:  * 
        !            65:  * Revision 1.4  87/09/24  13:59:29  narten
        !            66:  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
        !            67:  * warnings)
        !            68:  * 
        !            69:  * Revision 1.3  87/09/15  16:39:39  shepler
        !            70:  * added an initializatin of the variables editline and linecorr
        !            71:  * this will be done each time a file is processed.
        !            72:  * (there was an obscure bug where if co was used to retrieve multiple files
        !            73:  *  it would dump)
        !            74:  * fix attributed to  Roy Morris @FileNet Corp ...!felix!roy
        !            75:  * 
        !            76:  * Revision 1.2  87/03/27  14:22:17  jenkins
        !            77:  * Port to suns
        !            78:  * 
        !            79:  * Revision 1.1  84/01/23  14:50:20  kcs
        !            80:  * Initial revision
        !            81:  * 
        !            82:  * Revision 4.1  83/05/12  13:10:30  wft
        !            83:  * Added new markers Id and RCSfile; added locker to Header and Id.
        !            84:  * Overhauled expandline completely() (problem with $01234567890123456789@).
        !            85:  * Moved trymatch() and marker table to rcskeys.c.
        !            86:  * 
        !            87:  * Revision 3.7  83/05/12  13:04:39  wft
        !            88:  * Added retry to expandline to resume after failed match which ended in $.
        !            89:  * Fixed truncation problem for $19chars followed by@@.
        !            90:  * Log no longer expands full path of RCS file.
        !            91:  * 
        !            92:  * Revision 3.6  83/05/11  16:06:30  wft
        !            93:  * added retry to expandline to resume after failed match which ended in $.
        !            94:  * Fixed truncation problem for $19chars followed by@@.
        !            95:  * 
        !            96:  * Revision 3.5  82/12/04  13:20:56  wft
        !            97:  * Added expansion of keyword Locker.
        !            98:  *
        !            99:  * Revision 3.4  82/12/03  12:26:54  wft
        !           100:  * Added line number correction in case editing does not start at the
        !           101:  * beginning of the file.
        !           102:  * Changed keyword expansion to always print a space before closing KDELIM;
        !           103:  * Expansion for Header shortened.
        !           104:  *
        !           105:  * Revision 3.3  82/11/14  14:49:30  wft
        !           106:  * removed Suffix from keyword expansion. Replaced fclose with ffclose.
        !           107:  * keyreplace() gets log message from delta, not from curlogmsg.
        !           108:  * fixed expression overflow in while(c=putc(GETC....
        !           109:  * checked nil printing.
        !           110:  *
        !           111:  * Revision 3.2  82/10/18  21:13:39  wft
        !           112:  * I added checks for write errors during the co process, and renamed
        !           113:  * expandstring() to xpandstring().
        !           114:  *
        !           115:  * Revision 3.1  82/10/13  15:52:55  wft
        !           116:  * changed type of result of getc() from char to int.
        !           117:  * made keyword expansion loop in expandline() portable to machines
        !           118:  * without sign-extension.
        !           119:  */
        !           120: 
        !           121: 
        !           122: #include "rcsbase.h"
        !           123: 
        !           124: 
        !           125: extern FILE * fopen();
        !           126: extern char * mktempfile();
        !           127: extern char * bindex();
        !           128: extern FILE * finptr, * frewrite;
        !           129: extern int rewriteflag;
        !           130: extern int nextc;
        !           131: extern char * RCSfilename, * workfilename;
        !           132: extern char * bindex();
        !           133: extern char * getfullRCSname();
        !           134: extern enum markers trymatch();
        !           135: 
        !           136: 
        !           137: FILE  * fcopy,  * fedit; /* result and edit file descriptors                */
        !           138: char  *resultfile;       /* result file name                                */
        !           139: char  * editfile;        /* edit   file name                                */
        !           140: int editline;  /*line counter in fedit; starts with 1, is always #lines+1   */
        !           141: int linecorr;  /*contains #adds - #deletes in each edit run.                */
        !           142:                /*used to correct editline in case file is not rewound after */
        !           143:                /* applying one delta                                        */
        !           144: 
        !           145: initeditfiles(dir)
        !           146: char * dir;
        !           147: /* Function: Initializes resultfile and editfile with temporary filenames
        !           148:  * in directory dir. Opens resultfile for reading and writing, with fcopy
        !           149:  * as file descriptor. fedit is set to nil.
        !           150:  */
        !           151: {
        !           152:        editline = linecorr = 0;    /* make sure we start from the beginning*/
        !           153:         resultfile=mktempfile(dir,TMPFILE1);
        !           154:         editfile  =mktempfile(dir,TMPFILE2);
        !           155:         fedit=nil;
        !           156:         if ((fcopy=fopen(resultfile,"w+"))==NULL) {
        !           157:                 faterror("Can't open working file %s",resultfile);
        !           158:         }
        !           159: }
        !           160: 
        !           161: 
        !           162: swapeditfiles(tostdout)
        !           163: /* Function: swaps resultfile and editfile, assigns fedit=fcopy,
        !           164:  * rewinds fedit for reading, and opens resultfile for reading and
        !           165:  * writing, using fcopy. If tostdout, fcopy is set to stdout.
        !           166:  */
        !           167: {       char * tmpptr;
        !           168:         if(ferror(fcopy))
        !           169:                 faterror("write failed on %s -- file system full?",resultfile);
        !           170:         fedit=fcopy;
        !           171:         rewind(fedit);
        !           172:         editline = 1; linecorr=0;
        !           173:         tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
        !           174:         if (tostdout)
        !           175:                 fcopy=stdout;
        !           176:         elsif ((fcopy=fopen(resultfile,"w+"))==NULL) {
        !           177:                 faterror("Can't open working file %s",resultfile);
        !           178:         }
        !           179: }
        !           180: 
        !           181: 
        !           182: finishedit(delta)
        !           183: struct hshentry * delta;
        !           184: /* copy the rest of the edit file and close it (if it exists).
        !           185:  * if delta!=nil, perform keyword substitution at the same time.
        !           186:  */
        !           187: {
        !           188:         register int c;
        !           189:         if (fedit!=nil) {
        !           190:                 if (delta!=nil) {
        !           191:                         while (expandline(fedit,fcopy,delta,false,false)) editline++;
        !           192:                 } else {
        !           193:                         while((c=getc(fedit))!=EOF) {
        !           194:                                 VOID putc(c,fcopy);
        !           195:                                 if (c=='\n') editline++;
        !           196:                         }
        !           197:                 }
        !           198:                 ffclose(fedit);
        !           199:         }
        !           200: }
        !           201: 
        !           202: 
        !           203: copylines(line,delta)
        !           204: register int line; struct hshentry * delta;
        !           205: /* Function: copies input lines editline..line-1 from fedit to fcopy.
        !           206:  * If delta != nil, keyword expansion is done simultaneously.
        !           207:  * editline is updated. Rewinds a file only if necessary.
        !           208:  */
        !           209: {
        !           210: 
        !           211:         if (editline>line) {
        !           212:                 /* swap files */
        !           213:                 finishedit((struct hshentry *)nil); swapeditfiles(false);
        !           214:                 /* assumes edit only during last pass, from the beginning*/
        !           215:         }
        !           216:         while (editline<line) {
        !           217:                 /*copy another line*/
        !           218:                 if (delta)
        !           219:                         VOID expandline(fedit,fcopy,delta,false,false);
        !           220:                 else
        !           221:                         while (putc(getc(fedit),fcopy)!='\n');
        !           222:                 editline++;
        !           223:         }
        !           224: }
        !           225: 
        !           226: 
        !           227: 
        !           228: xpandstring(delta)
        !           229: struct hshentry * delta;
        !           230: /* Function: Reads a string terminated by SDELIM from finptr and writes it
        !           231:  * to fcopy. Double SDELIM is replaced with single SDELIM.
        !           232:  * Keyword expansion is performed with data from delta.
        !           233:  * If rewriteflag==true, the string is also copied unchanged to frewrite.
        !           234:  * editline is updated.
        !           235:  */
        !           236: {
        !           237:         editline=1;
        !           238:         while (expandline(finptr,fcopy,delta,true,rewriteflag)) editline++;
        !           239:         nextc='\n';
        !           240: }
        !           241: 
        !           242: 
        !           243: copystring()
        !           244: /* Function: copies a string terminated with a single SDELIM from finptr to
        !           245:  * fcopy, replacing all double SDELIM with a single SDELIM.
        !           246:  * If rewriteflag==true, the string also copied unchanged to frewrite.
        !           247:  * editline is set to (number of lines copied)+1.
        !           248:  * Assumption: next character read is first string character.
        !           249:  */
        !           250: {      register c;
        !           251:        register FILE *fin, *frew, *fcop;
        !           252:        register write;
        !           253: 
        !           254:        fin=finptr; frew=frewrite; fcop=fcopy;
        !           255:         write=rewriteflag;
        !           256:         editline=1;
        !           257:         while ((c=GETC(fin,frew,write)) != EOF) {
        !           258:                 if ((c==SDELIM)&&((c=GETC(fin,frew,write)) != SDELIM)){
        !           259:                         /* end of string */
        !           260:                         nextc = c;
        !           261:                         return;
        !           262:                 }
        !           263:                 VOID putc(c,fcop);
        !           264:                 if (c=='\n') editline++;
        !           265:         }
        !           266:         nextc = c;
        !           267:         serror("Unterminated string");
        !           268:         return;
        !           269: }
        !           270: 
        !           271: 
        !           272: 
        !           273: 
        !           274: editstring(delta)
        !           275: struct hshentry * delta;
        !           276: /* Function: reads an edit script from finptr and applies it to
        !           277:  * file fedit; the result is written to fcopy.
        !           278:  * If delta!=nil, keyword expansion is performed simultaneously.
        !           279:  * If frewrite==true, the edit script is also copied verbatim to frewrite.
        !           280:  * Assumes that all these files are open.
        !           281:  * If running out of lines in fedit, fedit and fcopy are swapped.
        !           282:  * resultfile and editfile are the names of the files that go with fcopy
        !           283:  * and fedit, respectively.
        !           284:  * Assumes the next input character from finptr is the first character of
        !           285:  * the edit script. Resets nextc on exit.
        !           286:  */
        !           287: {
        !           288:         int ed; /* editor command */
        !           289:         register int c;
        !           290:        register FILE *fin, *frew;
        !           291:         register int write, i;
        !           292:         int line, length;
        !           293: 
        !           294:        fin=finptr;  frew=frewrite;
        !           295:         editline += linecorr; linecorr=0; /*correct line number*/
        !           296:         write=rewriteflag;
        !           297:         for (;;) {
        !           298:                 /* read next command and decode */
        !           299:                 /* assume next non-white character is command name*/
        !           300:                 while((ed=GETC(fin,frew,write))=='\n'||
        !           301:                         ed==' ' || ed=='\t');
        !           302:                 if (ed==SDELIM) break;
        !           303:                 /* now attempt to read numbers. */
        !           304:                 /* fscanf causes trouble because of the required echoing */
        !           305:                 while ((c=GETC(fin,frew,write))==' ');  /*skip spaces*/
        !           306:                 if (!('0'<=c && c<='9')) {
        !           307:                         faterror("missing line number in edit script");
        !           308:                         break;
        !           309:                 }
        !           310:                 line= c -'0';
        !           311:                 while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
        !           312:                         line = line*10 + c-'0';
        !           313:                 }
        !           314:                 while (c==' ') c=GETC(fin,frew,write);
        !           315:                 if (!('0'<=c && c<='9')) {
        !           316:                         faterror("incorrect range in edit script");
        !           317:                         break;
        !           318:                 }
        !           319:                 length= c -'0';
        !           320:                 while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
        !           321:                         length = length*10 + c-'0';
        !           322:                 }
        !           323:                 while(c!='\n'&&c!=EOF) c=GETC(fin,frew,write); /* skip to end of line */
        !           324: 
        !           325:                 switch (ed) {
        !           326:                 case 'd':
        !           327:                         copylines(line,delta);
        !           328:                         /* skip over unwanted lines */
        !           329:                         for (i=length;i>0;i--) {
        !           330:                                 /*skip next line*/
        !           331:                                 while ((c=getc(fedit))!='\n')
        !           332:                                        if (c==EOF)
        !           333:                                                faterror("EOF during edit");
        !           334:                                 editline++;
        !           335:                         }
        !           336:                         linecorr -= length;
        !           337:                         break;
        !           338:                 case 'a':
        !           339:                         copylines(line+1,delta); /*copy only; no delete*/
        !           340:                         for (i=length;i>0;i--) {
        !           341:                                 /*copy next line from script*/
        !           342:                                 if (delta!=nil)
        !           343:                                        VOID expandline(fin,fcopy,delta,true,write);
        !           344:                                 else {
        !           345:                                        c = GETC(fin,frew,write);
        !           346:                                        while (putc(c,fcopy)!='\n'){
        !           347:                                                if ((c==SDELIM)&&((c=GETC(fin,frew,write))!=SDELIM)){
        !           348:                                                        serror("Missing string delimiter in edit script");
        !           349:                                                        VOID putc(c,fcopy);
        !           350:                                                }
        !           351:                                                c = GETC(fin,frew,write);
        !           352:                                        }
        !           353:                                 }
        !           354:                         }
        !           355:                         linecorr += length;
        !           356:                         break;
        !           357:                 default:
        !           358:                         faterror("unknown command in edit script: %c", ed);
        !           359:                         break;
        !           360:                 }
        !           361:         }
        !           362:         nextc=GETC(fin,frew,write);
        !           363: }
        !           364: 
        !           365: 
        !           366: 
        !           367: /* The rest is for keyword expansion */
        !           368: 
        !           369: 
        !           370: 
        !           371: expandline(in, out, delta,delimstuffed,write)
        !           372: register FILE * in, * out; struct hshentry * delta;
        !           373: int delimstuffed, write;
        !           374: /* Function: Reads a line from in and writes it to out.
        !           375:  * If delimstuffed==true, double SDELIM is replaced with single SDELIM.
        !           376:  * Keyword expansion is performed with data from delta.
        !           377:  * If write==true, the string is also copied unchanged to frewrite.
        !           378:  * Returns false if end-of-string or end-of-line is detected, true otherwise.
        !           379:  */
        !           380: {
        !           381:        register c;
        !           382:        register FILE * frew;
        !           383:        register w, ds;
        !           384:        register char * tp;
        !           385:        char keystring[keylength+2];
        !           386:        char keyval[keyvallength+2];
        !           387:         enum markers matchresult;
        !           388: 
        !           389:        frew = frewrite;
        !           390:        w = write;
        !           391:        ds = delimstuffed;
        !           392:        c=GETC(in,frew,w);
        !           393:         for (;;) {
        !           394:                 if (c==EOF) {
        !           395:                         if(ds) {
        !           396:                                 error("unterminated string");
        !           397:                                 nextc=c;
        !           398:                         }
        !           399:                         return(false);
        !           400:                 }
        !           401: 
        !           402:                 if (c==SDELIM && ds) {
        !           403:                         if ((c=GETC(in,frew,w))!=SDELIM) {
        !           404:                                 /* end of string */
        !           405:                                 nextc=c;
        !           406:                                 return false;
        !           407:                         }
        !           408:                 }
        !           409:                 VOID putc(c,out);
        !           410: 
        !           411:                 if (c=='\n') return true; /* end of line */
        !           412: 
        !           413:                if (c==KDELIM) {
        !           414:                         /* check for keyword */
        !           415:                         /* first, copy a long enough string into keystring */
        !           416:                        tp=keystring;
        !           417:                        while (((c=GETC(in,frew,w))!=EOF) && (tp<keystring+keylength) && (c!='\n')
        !           418:                               && (c!=SDELIM) && (c!=KDELIM) && (c!=VDELIM)) {
        !           419:                               VOID putc(c,out);
        !           420:                              *tp++ = c;
        !           421:                         }
        !           422:                        *tp++ = c; *tp = '\0';
        !           423:                        matchresult=trymatch(keystring,false);
        !           424:                        if (matchresult==Nomatch) continue;
        !           425:                        /* last c will be dealt with properly by continue*/
        !           426: 
        !           427:                        /* Now we have a keyword terminated with a K/VDELIM */
        !           428:                        if (c==VDELIM) {
        !           429:                              /* try to find closing KDELIM, and replace value */
        !           430:                              tp=keyval;
        !           431:                              while (((c=GETC(in,frew,w)) != EOF)
        !           432:                                     && (c!='\n') && (c!=KDELIM) && (tp<keyval+keyvallength)) {
        !           433:                                      *tp++ =c;
        !           434:                                      if (c==SDELIM && ds) { /*skip next SDELIM */
        !           435:                                                c=GETC(in,frew,w);
        !           436:                                                /* Can't be at end of string.
        !           437:                                                /* always a \n before closing SDELIM */
        !           438:                                      }
        !           439:                              }
        !           440:                              if (c!=KDELIM) {
        !           441:                                    /* couldn't find closing KDELIM -- give up */
        !           442:                                    VOID putc(VDELIM,out); *tp='\0';
        !           443:                                    VOID fputs(keyval,out);
        !           444:                                    continue;   /* last c handled properly */
        !           445:                              }
        !           446:                        }
        !           447:                        /* now put out the new keyword value */
        !           448:                        keyreplace(matchresult,delta,out);
        !           449:                 }
        !           450:                 c=GETC(in,frew,w);
        !           451:         } /* end for */
        !           452: }
        !           453: 
        !           454: 
        !           455: 
        !           456: keyreplace(marker,delta,out)
        !           457: enum markers marker; struct hshentry * delta; register FILE * out;
        !           458: /* function: ouputs the keyword value(s) corresponding to marker.
        !           459:  * Attributes are derived from delta.
        !           460:  */
        !           461: {
        !           462:         char * date;
        !           463:         register char * sp;
        !           464: 
        !           465:         date= delta->date;
        !           466: 
        !           467:         switch (marker) {
        !           468:         case Author:
        !           469:                 VOID fprintf(out,"%c %s %c",VDELIM,delta->author,KDELIM);
        !           470:                 break;
        !           471:         case Date:
        !           472:                 VOID putc(VDELIM,out);VOID putc(' ',out);
        !           473:                 VOID PRINTDATE(out,date);VOID putc(' ',out);
        !           474:                 VOID PRINTTIME(out,date);VOID putc(' ',out);VOID putc(KDELIM,out);
        !           475:                 break;
        !           476:         case Id:
        !           477:        case Header:
        !           478:                VOID putc(VDELIM,out); VOID putc(' ',out);
        !           479:                if (marker==Id)
        !           480:                         VOID fputs(bindex(RCSfilename,'/'),out);
        !           481:                else     VOID fputs(getfullRCSname(),out);
        !           482:                VOID fprintf(out," %s ", delta->num);
        !           483:                 VOID PRINTDATE(out,date);VOID putc(' ',out);VOID PRINTTIME(out,date);
        !           484:                VOID fprintf(out, " %s %s ",delta->author,delta->state);
        !           485:                if (delta->lockedby!=nil)
        !           486:                         VOID fprintf(out,"Locker: %s ",delta->lockedby);
        !           487:                VOID putc(KDELIM,out);
        !           488:                 break;
        !           489:         case Locker:
        !           490:                 VOID fprintf(out,"%c %s %c", VDELIM,
        !           491:                         delta->lockedby==nil?"":delta->lockedby,KDELIM);
        !           492:                 break;
        !           493:         case Log:
        !           494:                 VOID fprintf(out, "%c\t%s %c\n%sRevision %s  ",
        !           495:                         VDELIM, bindex(RCSfilename,'/'), KDELIM, Comment, delta->num);
        !           496:                 VOID PRINTDATE(out,date);VOID fputs("  ",out);VOID PRINTTIME(out,date);
        !           497:                 VOID fprintf(out, "  %s\n%s",delta->author,Comment);
        !           498:                 /* do not include state here because it may change and is not updated*/
        !           499:                 sp = delta->log;
        !           500:                 while (*sp) if (putc(*sp++,out)=='\n') VOID fputs(Comment,out);
        !           501:                 /* Comment is the comment leader */
        !           502:                 break;
        !           503:         case RCSfile:
        !           504:                 VOID fprintf(out,"%c %s %c",VDELIM,bindex(RCSfilename,'/'),KDELIM);
        !           505:                 break;
        !           506:         case Revision:
        !           507:                 VOID fprintf(out,"%c %s %c",VDELIM,delta->num,KDELIM);
        !           508:                 break;
        !           509:         case Source:
        !           510:                 VOID fprintf(out,"%c %s %c",VDELIM,getfullRCSname(),KDELIM);
        !           511:                 break;
        !           512:         case State:
        !           513:                 VOID fprintf(out,"%c %s %c",VDELIM,delta->state,KDELIM);
        !           514:                 break;
        !           515:         case Nomatch:
        !           516:                 VOID putc(KDELIM,out);
        !           517:                 break;
        !           518:         }
        !           519: }
        !           520: 
        !           521: 

unix.superglobalmegacorp.com

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