# 2.11BSD#431 - /usr/src/new/rcs/src/rcsedit.c

##### Functions

    copylines         X
    copystring        X
    editstring        X
    expandline        X
    finishedit        X
    initeditfiles     X
    keyreplace        X
    swapeditfiles     X
    xpandstring       X

##### Variables

    editfile          X
    editline          X
    linecorr          X
    resultfile        X

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

#### Defined functions

copylines defined in line 176; used 2 times

- in line 294, 306

copystring defined in line 216; used 2 times

- in /usr/src/new/rcs/src/rcs.c line 846
- in /usr/src/new/rcs/src/rcsgen.c line 201

editstring defined in line 243; used 4 times

- in /usr/src/new/rcs/src/rcs.c line 848
- in /usr/src/new/rcs/src/rcsgen.c line 86, 205-207(2)

expandline defined in line 338; used 5 times

- in line 164, 192, 211, 310
- in /usr/src/new/rcs/src/ci.c line 800

finishedit defined in line 155; used 6 times

- in line 186
- in /usr/src/new/rcs/src/rcs.c line 1463, 1471
- in /usr/src/new/rcs/src/rcsgen.c line 155-162(3)

initeditfiles defined in line 118; used 3 times

- in /usr/src/new/rcs/src/rcs.c line 1450
- in /usr/src/new/rcs/src/rcsgen.c line 137, 144

keyreplace defined in line 418; used 1 times

- in line 410

swapeditfiles defined in line 135; used 3 times

- in line 186
- in /usr/src/new/rcs/src/rcs.c line 1465
- in /usr/src/new/rcs/src/rcsgen.c line 160

xpandstring defined in line 201; used 1 times

- in /usr/src/new/rcs/src/rcsgen.c line 203

#### Defined variables

editfile defined in line 112; used 3 times

- in line 127, 146(2)

editline defined in line 113; used 13 times

- in line 125, 145, 164-168(2), 184-189(2), 195, 210-211(2), 225, 233, 262, 301

linecorr defined in line 114; used 6 times

- in line 125, 145, 262(2), 303, 322

rcsid defined in line 5; never used
resultfile defined in line 111; used 12 times

- in line 126-130(3), 142-150(5)
- in /usr/src/new/rcs/src/rcs.c line 1475, 1482
- in /usr/src/new/rcs/src/rcsgen.c line 140, 165

Last modified: 1988-02-19 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1188 |