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
copystring defined in line 216; used 2 times
editstring defined in line 243; used 4 times
expandline defined in line 338; used 5 times
finishedit defined in line 155; used 6 times
initeditfiles defined in line 118; used 3 times
keyreplace defined in line 418; used 1 times
swapeditfiles defined in line 135; used 3 times
xpandstring defined in line 201; used 1 times

Defined variables

editfile defined in line 112; used 3 times
editline defined in line 113; used 13 times
linecorr defined in line 114; used 6 times
rcsid defined in line 5; never used
resultfile defined in line 111; used 12 times
Last modified: 1988-02-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3025
Valid CSS Valid XHTML 1.0 Strict