Annotation of 43BSD/contrib/rcs/src/rcsedit.c, revision 1.1.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.