⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rcsedit.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *                     RCS stream editor *//********************************************************************************** *                       edits the input file according to a *                       script from stdin, generated by diff -n *                       performs keyword expansion ********************************************************************************** *//* Copyright (C) 1982, 1988, 1989 Walter Tichy   Copyright 1990, 1991 by Paul Eggert   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 modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with RCS; see the file COPYING.  If not, write tothe 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 5.11  1991/11/03  01:11:44  eggert * Move the warning about link breaking to where they're actually being broken. * * Revision 5.10  1991/10/07  17:32:46  eggert * Support piece tables even if !has_mmap.  Fix rare NFS bugs. * * Revision 5.9  1991/09/17  19:07:40  eggert * SGI readlink() yields ENXIO, not EINVAL, for nonlinks. * * Revision 5.8  1991/08/19  03:13:55  eggert * Add piece tables, NFS bug workarounds.  Catch odd filenames.  Tune. * * Revision 5.7  1991/04/21  11:58:21  eggert * Fix errno bugs.  Add -x, RCSINIT, MS-DOS support. * * Revision 5.6  1991/02/25  07:12:40  eggert * Fix setuid bug.  Support new link behavior.  Work around broken "w+" fopen. * * Revision 5.5  1990/12/30  05:07:35  eggert * Fix report of busy RCS files when !defined(O_CREAT) | !defined(O_EXCL). * * Revision 5.4  1990/11/01  05:03:40  eggert * Permit arbitrary data in comment leaders. * * Revision 5.3  1990/09/11  02:41:13  eggert * Tune expandline(). * * Revision 5.2  1990/09/04  08:02:21  eggert * Count RCS lines better.  Improve incomplete line handling. * * Revision 5.1  1990/08/29  07:13:56  eggert * Add -kkvl. * Fix bug when getting revisions to files ending in incomplete lines. * Fix bug in comment leader expansion. * * Revision 5.0  1990/08/22  08:12:47  eggert * Don't require final newline. * Don't append "checked in with -k by " to logs, * so that checking in a program with -k doesn't change it. * Don't generate trailing white space for empty comment leader. * Remove compile-time limits; use malloc instead.  Add -k, -V. * Permit dates past 1999/12/31.  Make lock and temp files faster and safer. * Ansify and Posixate.  Check diff's output. * * 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/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 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"libId(editId, "$Id: rcsedit.c,v 5.11 1991/11/03 01:11:44 eggert Exp $")static void keyreplace P((enum markers,struct hshentry const*,FILE*));FILE *fcopy;		 /* result file descriptor			    */char const *resultfile;  /* result file name				    */int locker_expansion;	 /* should the locker name be appended to Id val?   */#if !large_memory	static RILE *fedit; /* edit file descriptor */	static char const *editfile; /* edit pathname */#endifstatic unsigned long editline; /* edit line counter; #lines before cursor   */static long linecorr; /* #adds - #deletes in each edit run.		    */               /*used to correct editline in case file is not rewound after */               /* applying one delta                                        */#define DIRTEMPNAMES 2enum maker {notmade, real, effective};struct buf dirtfname[DIRTEMPNAMES];		/* unlink these when done */static enum maker volatile dirtfmaker[DIRTEMPNAMES];	/* if these are set */#if has_NFS || bad_unlink	intun_link(s)	char const *s;/* * Remove S, even if it is unwritable. * Ignore unlink() ENOENT failures; NFS generates bogus ones. */{#	if bad_unlink		int e;		if (unlink(s) == 0)			return 0;		e = errno;#		if has_NFS			if (e == ENOENT)				return 0;#		endif		if (chmod(s, S_IWUSR) != 0) {			errno = e;			return -1;		}#	endif#	if has_NFS		return unlink(s)==0 || errno==ENOENT  ?  0  :  -1;#	else		return unlink(s);#	endif}#endif#if !has_rename#  if !has_NFS#	define do_link(s,t) link(s,t)#  else	static intdo_link(s, t)	char const *s, *t;/* Link S to T, ignoring bogus EEXIST problems due to NFS failures.  */{	struct stat sb, tb;	if (link(s,t) == 0)		return 0;	if (errno != EEXIST)		return -1;	if (	    stat(s, &sb) == 0  &&	    stat(t, &tb) == 0  &&	    sb.st_ino == tb.st_ino  &&	    sb.st_dev == tb.st_dev	)		return 0;	errno = EEXIST;	return -1;}#  endif#endif	static exiting voideditEndsPrematurely(){	fatserror("edit script ends prematurely");}	static exiting voideditLineNumberOverflow(){	fatserror("edit script refers to line past end of file");}#if large_memory#if has_memmove#	define movelines(s1, s2, n) VOID memmove(s1, s2, (n)*sizeof(Iptr_type))#else	static voidmovelines(s1, s2, n)	register Iptr_type *s1;	register Iptr_type const *s2;	register unsigned long n;{	if (s1 < s2)		do {			*s1++ = *s2++;		} while (--n);	else {		s1 += n;		s2 += n;		do {			*--s1 = *--s2;		} while (--n);	}}#endif/* * `line' contains pointers to the lines in the currently `edited' file. * It is a 0-origin array that represents linelim-gapsize lines. * line[0..gap-1] and line[gap+gapsize..linelim-1] contain pointers to lines. * line[gap..gap+gapsize-1] contains garbage. * * Any @s in lines are duplicated. * Lines are terminated by \n, or (for a last partial line only) by single @. */static Iptr_type *line;static unsigned long gap, gapsize, linelim;	static voidinsertline(n, l)	unsigned long n;	Iptr_type l;/* Before line N, insert line L.  N is 0-origin.  */{	if (linelim-gapsize < n)	    editLineNumberOverflow();	if (!gapsize)	    line =		!linelim ?			tnalloc(Iptr_type, linelim = gapsize = 1024)		: (			gap = gapsize = linelim,			trealloc(Iptr_type, line, linelim <<= 1)		);	if (n < gap)	    movelines(line+n+gapsize, line+n, gap-n);	else if (gap < n)	    movelines(line+gap, line+gap+gapsize, n-gap);	line[n] = l;	gap = n + 1;	gapsize--;}	static voiddeletelines(n, nlines)	unsigned long n, nlines;/* Delete lines N through N+NLINES-1.  N is 0-origin.  */{	unsigned long l = n + nlines;	if (linelim-gapsize < l  ||  l < n)	    editLineNumberOverflow();	if (l < gap)	    movelines(line+l+gapsize, line+l, gap-l);	else if (gap < n)	    movelines(line+gap, line+gap+gapsize, n-gap);	gap = n;	gapsize += nlines;}	static voidsnapshotline(f, l)	register FILE *f;	register Iptr_type l;{	register int c;	do {		if ((c = *l++) == SDELIM  &&  *l++ != SDELIM)			return;		aputc(c, f);	} while (c != '\n');}	voidsnapshotedit(f)	FILE *f;/* Copy the current state of the edits to F.  */{	register Iptr_type *p, *lim, *l=line;	for (p=l, lim=l+gap;  p<lim;  )		snapshotline(f, *p++);	for (p+=gapsize, lim=l+linelim;  p<lim;  )		snapshotline(f, *p++);}	static voidfinisheditline(fin, fout, l, delta)	RILE *fin;	FILE *fout;	Iptr_type l;	struct hshentry const *delta;{	Iseek(fin, l);	if (expandline(fin, fout, delta, true, (FILE*)0)  <  0)		faterror("finisheditline internal error");}	voidfinishedit(delta, outfile, done)	struct hshentry const *delta;	FILE *outfile;	int done;/* * Doing expansion if DELTA is set, output the state of the edits to OUTFILE. * But do nothing unless DONE is set (which means we are on the last pass). */{	if (done) {		openfcopy(outfile);		outfile = fcopy;		if (!delta)			snapshotedit(outfile);		else {			register Iptr_type *p, *lim, *l = line;			register RILE *fin = finptr;			Iptr_type here = Itell(fin);			for (p=l, lim=l+gap;  p<lim;  )				finisheditline(fin, outfile, *p++, delta);			for (p+=gapsize, lim=l+linelim;  p<lim;  )				finisheditline(fin, outfile, *p++, delta);			Iseek(fin, here);		}	}}/* Open a temporary FILENAME for output, truncating any previous contents.  */#   define fopen_update_truncate(filename) fopen(filename, FOPEN_W_WORK)#else /* !large_memory */    static FILE *fopen_update_truncate(filename)    char const *filename;{#	if bad_fopen_wplus		if (un_link(filename) != 0)			efaterror(filename);#	endif	return fopen(filename, FOPEN_WPLUS_WORK);}#endif	voidopenfcopy(f)	FILE *f;{	if (!(fcopy = f)) {		if (!resultfile)			resultfile = maketemp(2);		if (!(fcopy = fopen_update_truncate(resultfile)))			efaterror(resultfile);	}}#if !large_memory	static voidswapeditfiles(outfile)	FILE *outfile;/* Function: swaps resultfile and editfile, assigns fedit=fcopy, * and rewinds fedit for reading.  Set fcopy to outfile if nonnull; * otherwise, set fcopy to be resultfile opened for reading and writing. */{	char const *tmpptr;	editline = 0;  linecorr = 0;	if (fseek(fcopy, 0L, SEEK_SET) != 0)		Oerror();	fedit = fcopy;        tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;	openfcopy(outfile);}	voidsnapshotedit(f)	FILE *f;/* Copy the current state of the edits to F.  */{	finishedit((struct hshentry *)nil, (FILE*)0, false);	fastcopy(fedit, f);	Irewind(fedit);}	voidfinishedit(delta, outfile, done)	struct hshentry const *delta;	FILE *outfile;	int done;/* copy the rest of the edit file and close it (if it exists). * if delta!=nil, perform keyword substitution at the same time. * If DONE is set, we are finishing the last pass. */{	register RILE *fe;	register FILE *fc;	fe = fedit;	if (fe) {		fc = fcopy;                if (delta!=nil) {			while (1 < expandline(fe,fc,delta,false,(FILE*)0))				;                } else {			fastcopy(fe,fc);                }		Ifclose(fe);        }	if (!done)		swapeditfiles(outfile);}#endif#if large_memory#	define copylines(upto,delta) (editline = (upto))#else	static voidcopylines(upto,delta)	register unsigned long upto;	struct hshentry const *delta;/* * Copy input lines editline+1..upto from fedit to fcopy. * If delta != nil, keyword expansion is done simultaneously. * editline is updated. Rewinds a file only if necessary. */{	register int c;	declarecache;	register FILE *fc;	register RILE *fe;	if (upto < editline) {                /* swap files */		finishedit((struct hshentry *)nil, (FILE*)0, false);                /* assumes edit only during last pass, from the beginning*/        }	fe = fedit;	fc = fcopy;	if (editline < upto)	    if (delta)		do {			if (expandline(fe,fc,delta,false,(FILE*)0) <= 1)				editLineNumberOverflow();		} while (++editline < upto);	    else {		setupcache(fe); cache(fe);		do {			do {				cachegeteof(c, editLineNumberOverflow(););				aputc(c, fc);			} while (c != '\n');		} while (++editline < upto);		uncache(fe);	    }}#endif	voidxpandstring(delta)	struct hshentry const *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 foutptr is nonnull, the string is also copied unchanged to foutptr. */{	while (1 < expandline(finptr,fcopy,delta,true,foutptr))		;}	voidcopystring()/* Function: copies a string terminated with a single SDELIM from finptr to * fcopy, replacing all double SDELIM with a single SDELIM. * If foutptr is nonnull, the string also copied unchanged to foutptr.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -