Date: Wed, 10 Apr 1996 22:28:06 +0100 Message-Id: <12970.9604102128@lister.prl.research.philips.com> From: Steve Pitchers To: johnh@ISI.EDU Subject: Tags patch John, Here is the patch as it currently stands. I believe that it works correctly, but it will be a while before I have any great confidence in it! Let me know of any problems you have... I recommend that you take a copy of your conf.h before typing make, as it will probably get clobbered as the Makefile will have changed. You may need to manually set large_memory to 1 in order to get rcstag.c to compile. One thing that I have noticed is that the tags don't work if there are gaps in the archive file (eg. revision 1.1 is missing, due to having created the archive using co -k). Enjoy, Steve ~~~ *** Makefile- Wed Apr 10 21:05:29 1996 --- Makefile Wed Apr 10 21:06:20 1996 *************** *** 172,184 **** ci = ci$o rcslex$o rcssyn$o rcsgen$o rcsedit$o rcskeys$o rcsmap$o \ rcsrev$o rcsutil$o rcsfnms$o maketime$o partime$o rcstime$o rcskeep$o \ ! rcsfcmp$o version$o $(LIBOBJS) ci$x : $(ci) $(LINK) $(ci) -o $@ $(LIBS) co = co$o rcslex$o rcssyn$o rcsgen$o rcsedit$o rcskeys$o rcsmap$o \ rcsrev$o rcsutil$o rcsfnms$o maketime$o partime$o rcstime$o rcskeep$o \ ! version$o $(LIBOBJS) co$x : $(co) $(LINK) $(co) -o $@ $(LIBS) --- 172,184 ---- ci = ci$o rcslex$o rcssyn$o rcsgen$o rcsedit$o rcskeys$o rcsmap$o \ rcsrev$o rcsutil$o rcsfnms$o maketime$o partime$o rcstime$o rcskeep$o \ ! rcsfcmp$o version$o rcstag$o $(LIBOBJS) ci$x : $(ci) $(LINK) $(ci) -o $@ $(LIBS) co = co$o rcslex$o rcssyn$o rcsgen$o rcsedit$o rcskeys$o rcsmap$o \ rcsrev$o rcsutil$o rcsfnms$o maketime$o partime$o rcstime$o rcskeep$o \ ! version$o rcstag$o $(LIBOBJS) co$x : $(co) $(LINK) $(co) -o $@ $(LIBS) *************** *** 201,213 **** rcs = rcs$o rcslex$o rcssyn$o rcsrev$o rcsutil$o rcsgen$o \ rcsedit$o rcskeys$o rcsmap$o rcsfnms$o rcskeep$o \ ! maketime$o partime$o rcstime$o version$o $(LIBOBJS) rcs$x : $(rcs) $(LINK) $(rcs) -o $@ $(LIBS) rcsclean = rcsclean$o rcsedit$o rcsfcmp$o rcsfnms$o rcsgen$o rcskeys$o \ rcslex$o rcsmap$o rcsrev$o rcssyn$o rcsutil$o rcskeep$o \ ! maketime$o partime$o rcstime$o version$o $(LIBOBJS) rcsclean$x : $(rcsclean) $(LINK) $(rcsclean) -o $@ $(LIBS) --- 201,213 ---- rcs = rcs$o rcslex$o rcssyn$o rcsrev$o rcsutil$o rcsgen$o \ rcsedit$o rcskeys$o rcsmap$o rcsfnms$o rcskeep$o \ ! maketime$o partime$o rcstime$o version$o rcstag$o $(LIBOBJS) rcs$x : $(rcs) $(LINK) $(rcs) -o $@ $(LIBS) rcsclean = rcsclean$o rcsedit$o rcsfcmp$o rcsfnms$o rcsgen$o rcskeys$o \ rcslex$o rcsmap$o rcsrev$o rcssyn$o rcsutil$o rcskeep$o \ ! maketime$o partime$o rcstime$o version$o rcstag$o $(LIBOBJS) rcsclean$x : $(rcsclean) $(LINK) $(rcsclean) -o $@ $(LIBS) *************** *** 230,236 **** OBJECT= ci$o co$o ident$o maketime$o merge$o merger$o partime$o rcs$o \ rcsclean$o rcsdiff$o rcsedit$o rcsfcmp$o rcsfnms$o rcsgen$o \ rcskeep$o rcskeys$o rcslex$o rcsmap$o rcsmerge$o rcsrev$o rcssyn$o \ ! rcstime$o rcsutil$o rlog$o version$o lint :: conf.h $(LINT) -DRCS_lint=1 $(ALL_CFLAGS) $(SOURCE) --- 230,236 ---- OBJECT= ci$o co$o ident$o maketime$o merge$o merger$o partime$o rcs$o \ rcsclean$o rcsdiff$o rcsedit$o rcsfcmp$o rcsfnms$o rcsgen$o \ rcskeep$o rcskeys$o rcslex$o rcsmap$o rcsmerge$o rcsrev$o rcssyn$o \ ! rcstime$o rcsutil$o rlog$o version$o rcstag$o lint :: conf.h $(LINT) -DRCS_lint=1 $(ALL_CFLAGS) $(SOURCE) *** Makefile.in- Wed Apr 10 21:05:29 1996 --- Makefile.in Wed Apr 10 21:06:20 1996 *************** *** 172,184 **** ci = ci$o rcslex$o rcssyn$o rcsgen$o rcsedit$o rcskeys$o rcsmap$o \ rcsrev$o rcsutil$o rcsfnms$o maketime$o partime$o rcstime$o rcskeep$o \ ! rcsfcmp$o version$o $(LIBOBJS) ci$x : $(ci) $(LINK) $(ci) -o $@ $(LIBS) co = co$o rcslex$o rcssyn$o rcsgen$o rcsedit$o rcskeys$o rcsmap$o \ rcsrev$o rcsutil$o rcsfnms$o maketime$o partime$o rcstime$o rcskeep$o \ ! version$o $(LIBOBJS) co$x : $(co) $(LINK) $(co) -o $@ $(LIBS) --- 172,184 ---- ci = ci$o rcslex$o rcssyn$o rcsgen$o rcsedit$o rcskeys$o rcsmap$o \ rcsrev$o rcsutil$o rcsfnms$o maketime$o partime$o rcstime$o rcskeep$o \ ! rcsfcmp$o version$o rcstag$o $(LIBOBJS) ci$x : $(ci) $(LINK) $(ci) -o $@ $(LIBS) co = co$o rcslex$o rcssyn$o rcsgen$o rcsedit$o rcskeys$o rcsmap$o \ rcsrev$o rcsutil$o rcsfnms$o maketime$o partime$o rcstime$o rcskeep$o \ ! version$o rcstag$o $(LIBOBJS) co$x : $(co) $(LINK) $(co) -o $@ $(LIBS) *************** *** 201,213 **** rcs = rcs$o rcslex$o rcssyn$o rcsrev$o rcsutil$o rcsgen$o \ rcsedit$o rcskeys$o rcsmap$o rcsfnms$o rcskeep$o \ ! maketime$o partime$o rcstime$o version$o $(LIBOBJS) rcs$x : $(rcs) $(LINK) $(rcs) -o $@ $(LIBS) rcsclean = rcsclean$o rcsedit$o rcsfcmp$o rcsfnms$o rcsgen$o rcskeys$o \ rcslex$o rcsmap$o rcsrev$o rcssyn$o rcsutil$o rcskeep$o \ ! maketime$o partime$o rcstime$o version$o $(LIBOBJS) rcsclean$x : $(rcsclean) $(LINK) $(rcsclean) -o $@ $(LIBS) --- 201,213 ---- rcs = rcs$o rcslex$o rcssyn$o rcsrev$o rcsutil$o rcsgen$o \ rcsedit$o rcskeys$o rcsmap$o rcsfnms$o rcskeep$o \ ! maketime$o partime$o rcstime$o version$o rcstag$o $(LIBOBJS) rcs$x : $(rcs) $(LINK) $(rcs) -o $@ $(LIBS) rcsclean = rcsclean$o rcsedit$o rcsfcmp$o rcsfnms$o rcsgen$o rcskeys$o \ rcslex$o rcsmap$o rcsrev$o rcssyn$o rcsutil$o rcskeep$o \ ! maketime$o partime$o rcstime$o version$o rcstag$o $(LIBOBJS) rcsclean$x : $(rcsclean) $(LINK) $(rcsclean) -o $@ $(LIBS) *************** *** 230,236 **** OBJECT= ci$o co$o ident$o maketime$o merge$o merger$o partime$o rcs$o \ rcsclean$o rcsdiff$o rcsedit$o rcsfcmp$o rcsfnms$o rcsgen$o \ rcskeep$o rcskeys$o rcslex$o rcsmap$o rcsmerge$o rcsrev$o rcssyn$o \ ! rcstime$o rcsutil$o rlog$o version$o lint :: conf.h $(LINT) -DRCS_lint=1 $(ALL_CFLAGS) $(SOURCE) --- 230,236 ---- OBJECT= ci$o co$o ident$o maketime$o merge$o merger$o partime$o rcs$o \ rcsclean$o rcsdiff$o rcsedit$o rcsfcmp$o rcsfnms$o rcsgen$o \ rcskeep$o rcskeys$o rcslex$o rcsmap$o rcsmerge$o rcsrev$o rcssyn$o \ ! rcstime$o rcsutil$o rlog$o version$o rcstag$o lint :: conf.h $(LINT) -DRCS_lint=1 $(ALL_CFLAGS) $(SOURCE) *** co.c- Wed Apr 10 21:05:29 1996 --- co.c Wed Apr 10 21:06:21 1996 *************** *** 188,193 **** --- 188,194 ---- static int lastjoin; /* index of last element in joinlist */ static int lockflag; /* -1 -> unlock, 0 -> do nothing, 1 -> lock */ static int mtimeflag; + extern int taglinesflag; /* Boolean: tag lines with their version */ static struct hshentries *gendeltas; /* deltas to be generated */ static struct hshentry *targetdelta; /* final delta to be generated */ static struct stat workstat; *************** *** 315,320 **** --- 316,325 ---- zone_set(a); break; + case 't': + taglinesflag = true; + break; + case 'k': /* set keyword expand mode */ expandarg = *argv; if (0 <= expmode) redefined('k'); *************** *** 449,455 **** locker_expansion = 0 < lockflag; targetdelta->name = namedrev(rev, targetdelta); ! joinname = buildrevision( gendeltas, targetdelta, joinflag&&tostdout ? (FILE*)0 : neworkptr, Expand < MIN_UNEXPAND --- 454,466 ---- locker_expansion = 0 < lockflag; targetdelta->name = namedrev(rev, targetdelta); ! if (taglinesflag) ! joinname = buildtaggedrevision( ! gendeltas, targetdelta, ! joinflag&&tostdout ? (FILE*)0 : neworkptr, ! Expand < MIN_UNEXPAND ! ); ! else joinname = buildrevision( gendeltas, targetdelta, joinflag&&tostdout ? (FILE*)0 : neworkptr, Expand < MIN_UNEXPAND *** rcsbase.h- Wed Apr 10 21:05:31 1996 --- rcsbase.h Wed Apr 10 21:06:22 1996 *************** *** 468,473 **** --- 468,474 ---- void copystring P((void)); void dirtempunlink P((void)); void enterstring P((void)); + void tagenterstring P((void)); void finishedit P((struct hshentry const*,FILE*,int)); void keepdirtemp P((char const*)); void openfcopy P((FILE*)); *************** *** 481,488 **** --- 482,492 ---- #if large_memory void edit_string P((void)); # define editstring(delta) edit_string() + void tag_edit_string P((void)); + # define tageditstring(delta) tag_edit_string() #else void editstring P((struct hshentry const*)); + void tageditstring P((struct hshentry const*)); #endif /* rcsfcmp */ *************** *** 516,521 **** --- 520,526 ---- extern int interactiveflag; extern struct buf curlogbuf; char const *buildrevision P((struct hshentries const*,struct hshentry*,FILE*,int)); + char const *buildtaggedrevision(struct hshentries const *deltas, struct hshentry *target, FILE *outfile, int expandflag); int getcstdin P((void)); int putdtext P((struct hshentry const*,char const*,FILE*,int)); int ttystdin P((void)); *************** *** 533,538 **** --- 538,548 ---- /* rcskeys */ extern char const *const Keyword[]; enum markers trymatch P((char const*)); + + /* for rcstag patch*/ + enum stringwork { enter, copy, edit, expand, edit_expand, tag_enter, tag_edits }; + + void scandeltatext P((struct hshentry*,enum stringwork,int)); /* rcslex */ extern FILE *foutptr; *** rcsedit.c- Wed Apr 10 21:05:31 1996 --- rcsedit.c Wed Apr 10 21:06:22 1996 *************** *** 348,355 **** * 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 size_t gap, gapsize, linelim; static void insertline(n, l) --- 348,355 ---- * Any @s in lines are duplicated. * Lines are terminated by \n, or (for a last partial line only) by single @. */ ! Iptr_type *line; ! size_t gap, gapsize, linelim; static void insertline(n, l) *** rcsgen.c- Wed Apr 10 21:05:31 1996 --- rcsgen.c Wed Apr 10 21:06:22 1996 *************** *** 146,156 **** int interactiveflag; /* Should we act as if stdin is a tty? */ struct buf curlogbuf; /* buffer for current log message */ - enum stringwork { enter, copy, edit, expand, edit_expand }; - static void putdelta P((struct hshentry const*,FILE*)); - static void scandeltatext P((struct hshentry*,enum stringwork,int)); - --- 146,152 ---- *************** *** 176,182 **** * or no keyword expansion is necessary, or if output goes to stdout. */ { ! if (deltas->first == target) { /* only latest revision to generate */ openfcopy(outfile); scandeltatext(target, expandflag?expand:copy, true); --- 172,180 ---- * or no keyword expansion is necessary, or if output goes to stdout. */ { ! extern int taglinesflag; ! ! if (deltas->first == target && !taglinesflag) { /* only latest revision to generate */ openfcopy(outfile); scandeltatext(target, expandflag?expand:copy, true); *************** *** 212,218 **** ! static void scandeltatext(delta, func, needlog) struct hshentry *delta; enum stringwork func; --- 210,216 ---- ! void scandeltatext(delta, func, needlog) struct hshentry *delta; enum stringwork func; *************** *** 257,262 **** --- 255,262 ---- case expand: xpandstring(delta); break; case edit: editstring((struct hshentry *)0); break; case edit_expand: editstring(delta); break; + case tag_enter: tagenterstring(); break; + case tag_edits: tageditstring(delta); break; } } *** rcstag.c- Wed Apr 10 21:11:40 1996 --- rcstag.c Wed Apr 10 21:11:26 1996 *************** *** 0 **** --- 1,545 ---- + /* + * RCS tagged line handling + */ + /* Copyright 1993 by Paul Eggert + Distributed under license by the Free Software Foundation, Inc. + + Portions of this file are contributed to Paul Eggert by John Heidemann + of the UCLA Ficus Project. + + 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 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 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 + + */ + + /* $Id$ */ + + #include "rcsbase.h" + + + /* + * We need to save a list of who owns each line. + */ + static struct hshentry **lineowner; + static int unimportant_line; /* index of a "don't care" line */ + + /* + * We manipulate the lineowner list indirectly through these tag_* + * variables. The algorithm is the same as that for managing lines + * as described in rcsedit.c. + */ + static int *tag_line; /* offset into lineowner */ + static unsigned long tag_gap, tag_gapsize, tag_linelim; + static unsigned long tag_editline; /* edit line counter; #lines before cursor */ + static long tag_linecorr; /* #adds - #deletes in each edit run. */ + + static struct hshentry *tag_olddelta; + + + + + static void + tag_editEndsPrematurely() + { + fatserror("edit script ends prematurely"); + } + + static void + tag_editLineNumberOverflow() + { + fatserror("edit script refers to line past end of file"); + } + + + + + static void + tag_savelines(oldestrev) + struct hshentry *oldestrev; + /* + * We no longer save the lines, but we do set up our line-ownership + * information at this point. + * Never do expansion. + */ + { + unsigned long i; + unsigned long duplinelim; + extern unsigned long gap, gapsize, linelim; + + /* + * Remember how many lines are in our desired revision. + */ + duplinelim = gap + linelim-gapsize-gap; /* BeforeGap + AfterGap */ + + /* + * Init line ownership, defaulting to the oldest possible. + */ + lineowner = testalloc(sizeof(int) * (duplinelim + 1)); + for (i = 0; i < duplinelim; i++) + lineowner[i] = oldestrev; + /* We save a dummy owner for our own vile purposes. */ + lineowner[i] = NULL; + unimportant_line = i; + } + + + static void + tag_savestate() + /* + * Associate our current tag_line buffer with the saved + * revision. + */ + { + int i; + int *ip, *ilim; + + for (i = 0, ip = tag_line, ilim = tag_line+tag_gap; ip < ilim; ) + *ip++ = i++; + for (ip += tag_gapsize, ilim = tag_line + tag_linelim; ip < ilim; ) + *ip++ = i++; + + } + + + static void + tag_showsavedlines(out) + FILE *out; + { + extern Iptr_type *line; + extern unsigned long gap, gapsize, linelim; + Iptr_type *p, *lim, *l = line; + Iptr_type cp; + int i; + + /* + * Dump the file, handling the gap. + */ + for (i=0, p=l, lim=l+gap; pnum); + cp = *p++; + do { + aputc_(*cp, out); + } while (*cp++ != '\n'); + }; + for (p+=gapsize, lim=l+linelim; pnum); + cp = *p++; + do { + aputc_(*cp, out); + } while (*cp++ != '\n'); + }; + } + + + + + + + + /* NEEDSWORK: this should go somewhere else. */ + int taglinesflag = false; /* Boolean: tag lines with their version */ + + char const * + buildtaggedrevision(deltas, target, outfile, expandflag) + struct hshentries const *deltas; + struct hshentry *target; + FILE *outfile; + int expandflag; + /* Function: Generates the revision given by target + * by retrieving all deltas given by parameter deltas and combining them. + * If outfile is set, the revision is output to it, + * otherwise written into a temporary file. + * Temporary files are allocated by maketemp(). + * if expandflag is set, keyword expansion is performed. + * Return nil if outfile is set, the name of the temporary file otherwise. + * + * Algorithm: Copy initial revision unchanged. Then edit all revisions but + * the last one into it, alternating input and output files (resultfile and + * editfile). The last revision is then edited in, performing simultaneous + * keyword substitution (this saves one extra pass). + * All this simplifies if only one revision needs to be generated, + * or no keyword expansion is necessary, or if output goes to stdout. + */ + { + struct hshentries *deltatree; + struct hshentry *oldestdelta; + Iptr_type here; /* remember where we are */ + int marking_changes; + int initial_delta; + + /* + * Go through all but the last revision. + */ + here = finptr->ptr; + if (deltas->first == target) { + scandeltatext(deltas->first, enter, false); + } else { + /* several revisions to generate */ + /* Get initial revision without keyword expansion. */ + scandeltatext(deltas->first, enter, false); + while ((deltas=deltas->rest)->rest) { + /* do all deltas except last one */ + scandeltatext(deltas->first, edit, false); + } + if (expandflag || outfile) { + /* first, get to beginning of file*/ + /* NEEDSWORK: since done==false, why bother to call this fn? */ + finishedit((struct hshentry *)0, outfile, false); + } + scandeltatext(deltas->first, expandflag?edit_expand:edit, true); + }; + + /* + * Now we'll go back in time. First plot our path. + */ + if (!(oldestdelta = genrevs("1.1",NULL,NULL,NULL,&deltatree))) { + return NULL; + }; + + /* + * Now we've got the revision. + * Save our version of the file and setup the ownership tags. + */ + tag_savelines(oldestdelta); + + /* + * Now scan the changes. + */ + finptr->ptr = here; + marking_changes = 0; + initial_delta = 1; + tag_olddelta = oldestdelta; /* default to ownership by 1.1 */ + do { + scandeltatext(deltatree->first, + (initial_delta ? tag_enter : tag_edits), + false); + initial_delta = 0; + tag_olddelta = deltatree->first; + if (deltatree->first == target) { + marking_changes = 1; + tag_savestate(); + }; + } while (deltatree = deltatree->rest); + + /* + * Finally output the changes. + */ + tag_showsavedlines(outfile); + + return NULL; + } + + + + + #if large_memory + # define tag_copylines(upto,delta) (tag_editline = (upto)) + #else + static void + tag_copylines(upto,delta) + register unsigned long upto; + struct hshentry const *delta; + { + faterror("tag_copylines: !large_memory. Rebuild RCS with the large_memory option."); + } + #endif + + + + + #if has_memmove + # define tag_movelines(s1, s2, n) VOID memmove(s1, s2, (n)*sizeof(int)) + #else + static void + tag_movelines(s1, s2, n) + register int *s1; + register int 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 + + + + static void + tag_insertline(n, l) + unsigned long n; + int l; + /* Before line N, insert line L. N is 0-origin. */ + { + if (tag_linelim-tag_gapsize < n) + tag_editLineNumberOverflow(); + if (!tag_gapsize) + tag_line = + !tag_linelim ? + tnalloc(int, tag_linelim = tag_gapsize = 1024) + : ( + tag_gap = tag_gapsize = tag_linelim, + trealloc(int, tag_line, tag_linelim <<= 1) + ); + if (n < tag_gap) + tag_movelines(tag_line+n+tag_gapsize, tag_line+n, tag_gap-n); + else if (tag_gap < n) + tag_movelines(tag_line+tag_gap, tag_line+tag_gap+tag_gapsize, n-tag_gap); + + tag_line[n] = l; + tag_gap = n + 1; + tag_gapsize--; + } + + + static void + tag_deletelines(n, nlines, olddelta) + unsigned long n, nlines; + struct hshentry *olddelta; + /* Delete lines N through N+NLINES-1. N is 0-origin. + * When we delete lines, that means they were created by delta "olddelta". + */ + { + unsigned long l = n + nlines; + unsigned long i; + + /* + * First mark the lines by their creator. + */ + if (l < tag_gap) { + for (i = n; i < l; i++) { + lineowner[tag_line[i]] = olddelta; + }; + } else if (tag_gap < n) { + for (i = n + tag_gapsize; i < l + tag_gapsize; i++) { + lineowner[tag_line[i]] = olddelta; + }; + } else { + for (i = n; i < tag_gap; i++) { + lineowner[tag_line[i]] = olddelta; + }; + for (i = tag_gap + tag_gapsize; i < l + tag_gapsize; i++) { + lineowner[tag_line[i]] = olddelta; + }; + }; + + /* + * Delete the lines. + */ + if (tag_linelim-tag_gapsize < l || l < n) + tag_editLineNumberOverflow(); + if (l < tag_gap) + tag_movelines(tag_line+l+tag_gapsize, tag_line+l, tag_gap-l); + else if (tag_gap < n) + tag_movelines(tag_line+tag_gap, tag_line+tag_gap+tag_gapsize, n-tag_gap); + + tag_gap = n; + tag_gapsize += nlines; + } + + + + + + void + tagenterstring() + { + #if !large_memory + faterror("tag_enter: not implemented for !large_memory.\n"); + #if 0 + editfile = 0; + fedit = 0; + editline = linecorr = 0; + resultfile = maketemp(1); + if (!(fcopy = fopen_update_truncate(resultfile))) + efaterror(resultfile); + copystring(); + #endif + #else + register int c; + declarecache; + register FILE *frew; + register unsigned long e, oe; + register int amidline, oamidline; + register Iptr_type optr; + register RILE *fin; + + e = 0; + tag_gap = 0; + tag_gapsize = tag_linelim; + fin = finptr; + setupcache(fin); cache(fin); + advise_access(fin, MADV_NORMAL); + frew = foutptr; + amidline = false; + for (;;) { + optr = cacheptr(); + GETC_(frew,c); + oamidline = amidline; + oe = e; + switch (c) { + case '\n': + ++e; + ++rcsline; + amidline = false; + break; + case SDELIM: + GETC_(frew,c); + if (c != SDELIM) { + /* end of string */ + nextc = c; + tag_editline = e + amidline; + tag_linecorr = 0; + uncache(fin); + return; + } + /* fall into */ + default: + amidline = true; + break; + } + if (!oamidline) + tag_insertline(oe, unimportant_line); + } + #endif + } + + + + + + /* + * tag_edit_string grabs the current delta out of the global + * variable "tag_olddelta". I did this because paramater passing to + * tag_edit_string is already ugly enough, I don't want to make + * it worse. -JSH 10-Mar-93 + */ + void + #if large_memory + tag_edit_string() + #else + tageditstring(delta) + struct hshentry const *delta; + #endif + { + int ed; /* editor command */ + register int c; + declarecache; + register FILE *frew; + # if !large_memory + register FILE *f; + unsigned long line_lim = ULONG_MAX; + register RILE *fe; + # endif + register unsigned long i; + register RILE *fin; + # if large_memory + register unsigned long j; + # endif + struct diffcmd dc; + + tag_editline += tag_linecorr; tag_linecorr=0; /*correct line number*/ + frew = foutptr; + fin = finptr; + setupcache(fin); + initdiffcmd(&dc); + while (0 <= (ed = getdiffcmd(fin,true,frew,&dc))) + #if !large_memory + if (line_lim <= dc.line1) + tag_editLineNumberOverflow(); + else + #endif + if (!ed) { /* delete */ + tag_copylines(dc.line1-1, delta); + /* skip over unwanted lines */ + i = dc.nlines; + tag_linecorr -= i; + tag_editline += i; + # if large_memory + tag_deletelines(tag_editline+tag_linecorr, i, tag_olddelta); + # else + fe = fedit; + do { + /*skip next line*/ + do { + Igeteof(fe, c, { if (i!=1) tag_editLineNumberOverflow(); line_lim = dc.dafter; break; } ); + } while (c != '\n'); + } while (--i); + # endif + } else { + tag_copylines(dc.line1, delta); /*copy only; no delete*/ + i = dc.nlines; + # if large_memory + j = tag_editline+tag_linecorr; + # endif + tag_linecorr += i; + #if !large_memory + f = fcopy; + if (delta) + do { + switch (expandline(fin,f,delta,true,frew)) { + case 0: case 1: + if (i==1) + return; + /* fall into */ + case -1: + tag_editEndsPrematurely(); + } + } while (--i); + else + #endif + { + cache(fin); + do { + # if large_memory + tag_insertline(j++, unimportant_line); + # endif + for (;;) { + GETC_(frew, c); + # if !large_memory + aputc_(c, f); + # endif + if (c == '\n') + break; + if (c==SDELIM) { + GETC_(frew, c); + if (c!=SDELIM) { + if (--i) + tag_editEndsPrematurely(); + nextc = c; + uncache(fin); + return; + } + } + } + ++rcsline; + } while (--i); + uncache(fin); + } + } + } +