home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OS9000
/
APPS
/
rcs.lzh
/
rcs1
/
rcsedit.c
< prev
next >
Wrap
Text File
|
1996-04-20
|
19KB
|
553 lines
/*
* RCS stream editor
*/
#ifndef lint
static char rcsid[]= "$Id: rcsedit.c_v 1.2 93/10/31 22:33:24 hiro Exp $ Purdue CS";
#endif
/**********************************************************************************
* edits the input file according to a
* script from stdin, generated by diff -n
* performs keyword expansion
**********************************************************************************
*/
/* Copyright (C) 1982, 1988, 1989 Walter Tichy
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/* $Log: rcsedit.c_v $
* Revision 1.2 93/10/31 22:33:24 hiro
* Prototype
* ================================================================
* Made $Header" print only file naem, not full path name.
* ================================================================
*
* Revision 1.1 93/04/02 01:28:59 hiro
* Initial revision
*
* Revision 1.1 90/07/19 15:21:15 momo
* Initial revision
*
* revision 5.2 koya 90/01/25 00:46:07
* Changed only path name separators.
*
* revision 5.1 koya 90/01/24 06:39:44
* Initial revision
*
* Revision 4.8 89/05/01 15:12:35 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.7 88/11/08 13:54:14 narten
* misplaced semicolon caused infinite loop
*
* Revision 4.6 88/11/08 12:01:41 narten
* changes from eggert@sm.unisys.com (Paul Eggert)
*
* Revision 4.6 88/08/09 19:12:45 eggert
* Shrink stdio code size; allow cc -R.
*
* Revision 4.5 87/12/18 11:38:46 narten
* Changes from the 43. version. Don't know the significance of the
* first change involving "rewind". Also, additional "lint" cleanup.
* (Guy Harris)
*
* Revision 4.4 87/10/18 10:32:21 narten
* Updating version numbers. Changes relative to version 1.1 actually
* relative to 4.1
*
* Revision 1.4 87/09/24 13:59:29 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.3 87/09/15 16:39:39 shepler
* added an initializatin of the variables editline and linecorr
* this will be done each time a file is processed.
* (there was an obscure bug where if co was used to retrieve multiple files
* it would dump)
* fix attributed to Roy Morris @FileNet Corp ...!felix!roy
*
* Revision 1.2 87/03/27 14:22:17 jenkins
* Port to suns
*
* Revision 1.1 84/01/23 14:50:20 kcs
* Initial revision
*
* Revision 4.1 83/05/12 13:10:30 wft
* Added new markers Id and RCSfile; added locker to Header and Id.
* Overhauled expandline completely() (problem with $01234567890123456789@).
* Moved trymatch() and marker table to rcskeys.c.
*
* Revision 3.7 83/05/12 13:04:39 wft
* Added retry to expandline to resume after failed match which ended in $.
* Fixed truncation problem for $19chars followed by@@.
* Log no longer expands full path of RCS file.
*
* Revision 3.6 83/05/11 16:06:30 wft
* added retry to expandline to resume after failed match which ended in $.
* Fixed truncation problem for $19chars followed by@@.
*
* Revision 3.5 82/12/04 13:20:56 wft
* Added expansion of keyword Locker.
*
* Revision 3.4 82/12/03 12:26:54 wft
* Added line number correction in case editing does not start at the
* beginning of the file.
* Changed keyword expansion to always print a space before closing KDELIM;
* Expansion for Header shortened.
*
* Revision 3.3 82/11/14 14:49:30 wft
* removed Suffix from keyword expansion. Replaced fclose with ffclose.
* keyreplace() gets log message from delta, not from curlogmsg.
* fixed expression overflow in while(c=putc(GETC....
* checked nil printing.
*
* Revision 3.2 82/10/18 21:13:39 wft
* I added checks for write errors during the co process, and renamed
* expandstring() to xpandstring().
*
* Revision 3.1 82/10/13 15:52:55 wft
* changed type of result of getc() from char to int.
* made keyword expansion loop in expandline() portable to machines
* without sign-extension.
*/
#include "rcsbase.h"
extern FILE * fopen();
extern char * mktempfile();
extern char * bindex();
extern FILE * finptr, * frewrite;
extern int rewriteflag;
extern int nextc;
extern char * RCSfilename, * workfilename;
extern char * bindex();
extern char * getfullRCSname();
extern enum markers trymatch();
FILE * fcopy, * fedit; /* result and edit file descriptors */
char *resultfile; /* result file name */
char * editfile; /* edit file name */
int editline; /*line counter in fedit; starts with 1, is always #lines+1 */
int linecorr; /*contains #adds - #deletes in each edit run. */
/*used to correct editline in case file is not rewound after */
/* applying one delta */
initeditfiles(dir)
char * dir;
/* Function: Initializes resultfile and editfile with temporary filenames
* in directory dir. Opens resultfile for reading and writing, with fcopy
* as file descriptor. fedit is set to nil.
*/
{
editline = linecorr = 0; /* make sure we start from the beginning*/
resultfile=mktempfile(dir,TMPFILE1);
editfile =mktempfile(dir,TMPFILE2);
fedit=nil;
if ((fcopy=fopen(resultfile,"w+"))==NULL) {
faterror("Can't open working file %s",resultfile);
}
}
swapeditfiles(tostdout)
/* Function: swaps resultfile and editfile, assigns fedit=fcopy,
* rewinds fedit for reading, and opens resultfile for reading and
* writing, using fcopy. If tostdout, fcopy is set to stdout.
*/
{ char * tmpptr;
if(ferror(fcopy))
faterror("write failed on %s -- file system full?",resultfile);
fedit=fcopy;
rewind(fedit);
editline = 1; linecorr=0;
tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
if (tostdout)
fcopy=stdout;
elsif ((fcopy=fopen(resultfile,"w+"))==NULL) {
faterror("Can't open working file %s",resultfile);
}
}
finishedit(delta)
struct hshentry * delta;
/* copy the rest of the edit file and close it (if it exists).
* if delta!=nil, perform keyword substitution at the same time.
*/
{
register int c;
if (fedit!=nil) {
if (delta!=nil) {
while (expandline(fedit,fcopy,delta,false,false)) editline++;
} else {
while((c=getc(fedit))!=EOF) {
VOID putc(c,fcopy);
if (c=='\n') editline++;
}
}
ffclose(fedit);
}
}
copylines(line,delta)
register int line; struct hshentry * delta;
/* Function: copies input lines editline..line-1 from fedit to fcopy.
* If delta != nil, keyword expansion is done simultaneously.
* editline is updated. Rewinds a file only if necessary.
*/
{
if (editline>line) {
/* swap files */
finishedit((struct hshentry *)nil); swapeditfiles(false);
/* assumes edit only during last pass, from the beginning*/
}
while (editline<line) {
/*copy another line*/
if (delta)
VOID expandline(fedit,fcopy,delta,false,false);
else
while (putc(getc(fedit),fcopy)!='\n');
editline++;
}
}
xpandstring(delta)
struct hshentry * delta;
/* Function: Reads a string terminated by SDELIM from finptr and writes it
* to fcopy. Double SDELIM is replaced with single SDELIM.
* Keyword expansion is performed with data from delta.
* If rewriteflag==true, the string is also copied unchanged to frewrite.
* editline is updated.
*/
{
editline=1;
while (expandline(finptr,fcopy,delta,true,rewriteflag)) editline++;
nextc='\n';
}
void copystring()
/* Function: copies a string terminated with a single SDELIM from finptr to
* fcopy, replacing all double SDELIM with a single SDELIM.
* If rewriteflag==true, the string also copied unchanged to frewrite.
* editline is set to (number of lines copied)+1.
* Assumption: next character read is first string character.
*/
{ register c;
register FILE *fin, *frew, *fcop;
register write;
fin=finptr; frew=frewrite; fcop=fcopy;
write=rewriteflag;
editline=1;
while ((c=GETC(fin,frew,write)) != EOF) {
if ((c==SDELIM)&&((c=GETC(fin,frew,write)) != SDELIM)){
/* end of string */
nextc = c;
return;
}
VOID putc(c,fcop);
if (c=='\n') editline++;
}
nextc = c;
serror("Unterminated string");
return;
}
editstring(delta)
struct hshentry * delta;
/* Function: reads an edit script from finptr and applies it to
* file fedit; the result is written to fcopy.
* If delta!=nil, keyword expansion is performed simultaneously.
* If frewrite==true, the edit script is also copied verbatim to frewrite.
* Assumes that all these files are open.
* If running out of lines in fedit, fedit and fcopy are swapped.
* resultfile and editfile are the names of the files that go with fcopy
* and fedit, respectively.
* Assumes the next input character from finptr is the first character of
* the edit script. Resets nextc on exit.
*/
{
int ed; /* editor command */
register int c;
register FILE *fin, *frew;
register int write, i;
int line, length;
fin=finptr; frew=frewrite;
editline += linecorr; linecorr=0; /*correct line number*/
write=rewriteflag;
for (;;) {
/* read next command and decode */
/* assume next non-white character is command name*/
while((ed=GETC(fin,frew,write))=='\n'||
ed==' ' || ed=='\t');
if (ed==SDELIM) break;
/* now attempt to read numbers. */
/* fscanf causes trouble because of the required echoing */
while ((c=GETC(fin,frew,write))==' '); /*skip spaces*/
if (!('0'<=c && c<='9')) {
faterror("missing line number in edit script");
break;
}
line= c -'0';
while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
line = line*10 + c-'0';
}
while (c==' ') c=GETC(fin,frew,write);
if (!('0'<=c && c<='9')) {
faterror("incorrect range in edit script");
break;
}
length= c -'0';
while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
length = length*10 + c-'0';
}
while(c!='\n'&&c!=EOF) c=GETC(fin,frew,write); /* skip to end of line */
switch (ed) {
case 'd':
copylines(line,delta);
/* skip over unwanted lines */
for (i=length;i>0;i--) {
/*skip next line*/
while ((c=getc(fedit))!='\n')
if (c==EOF)
faterror("EOF during edit");
editline++;
}
linecorr -= length;
break;
case 'a':
copylines(line+1,delta); /*copy only; no delete*/
for (i=length;i>0;i--) {
/*copy next line from script*/
if (delta!=nil)
VOID expandline(fin,fcopy,delta,true,write);
else {
c = GETC(fin,frew,write);
while (putc(c,fcopy)!='\n'){
if ((c==SDELIM)&&((c=GETC(fin,frew,write))!=SDELIM)){
serror("Missing string delimiter in edit script");
VOID putc(c,fcopy);
}
c = GETC(fin,frew,write);
}
}
}
linecorr += length;
break;
default:
faterror("unknown command in edit script: %c", ed);
break;
}
}
nextc=GETC(fin,frew,write);
}
/* The rest is for keyword expansion */
expandline(in, out, delta,delimstuffed,write)
register FILE * in, * out; struct hshentry * delta;
int delimstuffed, write;
/* Function: Reads a line from in and writes it to out.
* If delimstuffed==true, double SDELIM is replaced with single SDELIM.
* Keyword expansion is performed with data from delta.
* If write==true, the string is also copied unchanged to frewrite.
* Returns false if end-of-string or end-of-line is detected, true otherwise.
*/
{
register c;
register FILE * frew;
register w, ds;
register char * tp;
char keystring[keylength+2];
char keyval[keyvallength+2];
enum markers matchresult;
frew = frewrite;
w = write;
ds = delimstuffed;
c=GETC(in,frew,w);
for (;;) {
if (c==EOF) {
if(ds) {
error("unterminated string");
nextc=c;
}
return(false);
}
if (c==SDELIM && ds) {
if ((c=GETC(in,frew,w))!=SDELIM) {
/* end of string */
nextc=c;
return false;
}
}
VOID putc(c,out);
if (c=='\n') return true; /* end of line */
if (c==KDELIM) {
/* check for keyword */
/* first, copy a long enough string into keystring */
tp=keystring;
while (((c=GETC(in,frew,w))!=EOF) && (tp<keystring+keylength) && (c!='\n')
&& (c!=SDELIM) && (c!=KDELIM) && (c!=VDELIM)) {
VOID putc(c,out);
*tp++ = c;
}
*tp++ = c; *tp = '\0';
matchresult=trymatch(keystring,false);
if (matchresult==Nomatch) continue;
/* last c will be dealt with properly by continue*/
/* Now we have a keyword terminated with a K/VDELIM */
if (c==VDELIM) {
/* try to find closing KDELIM, and replace value */
tp=keyval;
while (((c=GETC(in,frew,w)) != EOF)
&& (c!='\n') && (c!=KDELIM) && (tp<keyval+keyvallength)) {
*tp++ =c;
if (c==SDELIM && ds) { /*skip next SDELIM */
c=GETC(in,frew,w);
/* Can't be at end of string.
/* always a \n before closing SDELIM */
}
}
if (c!=KDELIM) {
/* couldn't find closing KDELIM -- give up */
VOID putc(VDELIM,out); *tp='\0';
VOID fputs(keyval,out);
continue; /* last c handled properly */
}
}
/* now put out the new keyword value */
keyreplace(matchresult,delta,out);
}
c=GETC(in,frew,w);
} /* end for */
}
keyreplace(marker,delta,out)
enum markers marker; struct hshentry * delta; register FILE * out;
/* function: ouputs the keyword value(s) corresponding to marker.
* Attributes are derived from delta.
*/
{
char * date;
register char * sp;
date= delta->date;
switch (marker) {
case Author:
VOID fprintf(out,"%c %s %c",VDELIM,delta->author,KDELIM);
break;
case Date:
VOID putc(VDELIM,out);VOID putc(' ',out);
VOID PRINTDATE(out,date);VOID putc(' ',out);
VOID PRINTTIME(out,date);VOID putc(' ',out);VOID putc(KDELIM,out);
break;
case Id:
case Header:
VOID putc(VDELIM,out); VOID putc(' ',out);
#if 0 /* make $Header: rcsedit.c_v 1.2 93/10/31 22:33:24 hiro Exp $ print only file name, not full path name */
if (marker==Id)
#else
if (1)
#endif
#ifdef MSDOS
VOID fputs(bindex(RCSfilename,'\\'),out);
#else
VOID fputs(bindex(RCSfilename,'/'),out);
#endif /* MSDOS */
else VOID fputs(getfullRCSname(),out);
VOID fprintf(out," %s ", delta->num);
VOID PRINTDATE(out,date);VOID putc(' ',out);VOID PRINTTIME(out,date);
VOID fprintf(out, " %s %s ",delta->author,delta->state);
if (delta->lockedby!=nil)
VOID fprintf(out,"Locker: %s ",delta->lockedby);
VOID putc(KDELIM,out);
break;
case Locker:
VOID fprintf(out,"%c %s %c", VDELIM,
delta->lockedby==nil?"":delta->lockedby,KDELIM);
break;
case Log:
VOID fprintf(out, "%c\t%s %c\n%sRevision %s ",
#ifdef MSDOS
VDELIM, bindex(RCSfilename,'\\'), KDELIM, Comment, delta->num);
#else
VDELIM, bindex(RCSfilename,'/'), KDELIM, Comment, delta->num);
#endif /* MSDOS */
VOID PRINTDATE(out,date);VOID fputs(" ",out);VOID PRINTTIME(out,date);
VOID fprintf(out, " %s\n%s",delta->author,Comment);
/* do not include state here because it may change and is not updated*/
sp = delta->log;
while (*sp) if (putc(*sp++,out)=='\n') VOID fputs(Comment,out);
/* Comment is the comment leader */
break;
case RCSfile:
#ifdef MSDOS
VOID fprintf(out,"%c %s %c",VDELIM,bindex(RCSfilename,'\\'),KDELIM);
#else
VOID fprintf(out,"%c %s %c",VDELIM,bindex(RCSfilename,'/'),KDELIM);
#endif /* MSDOS */
break;
case Revision:
VOID fprintf(out,"%c %s %c",VDELIM,delta->num,KDELIM);
break;
case Source:
VOID fprintf(out,"%c %s %c",VDELIM,getfullRCSname(),KDELIM);
break;
case State:
VOID fprintf(out,"%c %s %c",VDELIM,delta->state,KDELIM);
break;
case Nomatch:
VOID putc(KDELIM,out);
break;
}
}