1 /* Compare working files, ignoring RCS keyword strings. */
3 /*****************************************************************************
5 * Testprogram: define FCMPTEST
6 *****************************************************************************
9 /* Copyright 1982, 1988, 1989 Walter Tichy
10 Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
11 Distributed under license by the Free Software Foundation, Inc.
13 This file is part of RCS.
15 RCS is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2, or (at your option)
20 RCS is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with RCS; see the file COPYING.
27 If not, write to the Free Software Foundation,
28 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 Report problems and direct all questions to:
32 rcs-bugs@cs.purdue.edu
41 * Revision 5.14 1995/06/16 06:19:24 eggert
44 * Revision 5.13 1995/06/01 16:23:43 eggert
45 * (rcsfcmp): Add -kb support.
47 * Revision 5.12 1994/03/17 14:05:48 eggert
48 * Normally calculate the $Log prefix from context, not from RCS file.
49 * Calculate line numbers correctly even if the $Log prefix contains newlines.
52 * Revision 5.11 1993/11/03 17:42:27 eggert
53 * Fix yet another off-by-one error when comparing Log string expansions.
55 * Revision 5.10 1992/07/28 16:12:44 eggert
56 * Statement macro names now end in _.
58 * Revision 5.9 1991/10/07 17:32:46 eggert
59 * Count log lines correctly.
61 * Revision 5.8 1991/08/19 03:13:55 eggert
64 * Revision 5.7 1991/04/21 11:58:22 eggert
65 * Fix errno bug. Add MS-DOS support.
67 * Revision 5.6 1991/02/28 19:18:47 eggert
68 * Open work file at most once.
70 * Revision 5.5 1990/11/27 09:26:05 eggert
71 * Fix comment leader bug.
73 * Revision 5.4 1990/11/01 05:03:42 eggert
74 * Permit arbitrary data in logs and comment leaders.
76 * Revision 5.3 1990/09/11 02:41:15 eggert
77 * Don't ignore differences inside keyword strings if -ko is set.
79 * Revision 5.1 1990/08/29 07:13:58 eggert
80 * Clean old log messages too.
82 * Revision 5.0 1990/08/22 08:12:49 eggert
83 * Don't append "checked in with -k by " log to logs,
84 * so that checking in a program with -k doesn't change it.
85 * Ansify and Posixate. Remove lint.
87 * Revision 4.5 89/05/01 15:12:42 narten
88 * changed copyright header to reflect current distribution rules
90 * Revision 4.4 88/08/09 19:12:50 eggert
91 * Shrink stdio code size.
93 * Revision 4.3 87/12/18 11:40:02 narten
94 * lint cleanups (Guy Harris)
96 * Revision 4.2 87/10/18 10:33:06 narten
97 * updting version number. Changes relative to 1.1 actually relative to
100 * Revision 1.2 87/03/27 14:22:19 jenkins
103 * Revision 4.1 83/05/10 16:24:04 wft
104 * Marker matching now uses trymatch(). Marker pattern is now
107 * Revision 3.1 82/12/04 13:21:40 wft
115 /* Testprogram; prints out whether two files are identical,
116 * except for keywords
121 libId(fcmpId, "$FreeBSD$")
123 static int discardkeyval P((int,RILE*));
135 Igeteof_(f, c, return EOF;)
141 rcsfcmp(xfp, xstatp, uname, delta)
143 struct stat const *xstatp;
145 struct hshentry const *delta;
146 /* Compare the files xfp and uname. Return zero
147 * if xfp has the same contents as uname and neither has keywords,
148 * otherwise -1 if they are the same ignoring keyword values,
149 * and 1 if they differ even ignoring
150 * keyword values. For the LOG-keyword, rcsfcmp skips the log message
151 * given by the parameter delta in xfp. Thus, rcsfcmp returns nonpositive
152 * if xfp contains the same as uname, with the keywords expanded.
153 * Implementation: character-by-character comparison until $ is found.
154 * If a $ is found, read in the marker keywords; if they are real keywords
155 * and identical, read in keyword value. If value is terminated properly,
156 * disregard it and optionally skip log message; otherwise, compare value.
160 char xkeyword[keylength+2];
163 register int xeof, ueof;
165 register char const *sp;
166 register size_t leaderlen;
171 if (!(ufp = Iopen(uname, FOPEN_R_WORK, &ustat))) {
175 if (MIN_UNEXPAND <= Expand) {
176 if (!(result = xstatp->st_size!=ustat.st_size)) {
177 # if large_memory && maps_memory
178 result = !!memcmp(xfp->base,ufp->base,(size_t)xstatp->st_size);
181 /* get the next characters */
182 Igeteof_(xfp, xc, xeof=true;)
183 Igeteof_(ufp, uc, ueof=true;)
193 uc = 0; /* Keep lint happy. */
199 /* get the next characters */
200 Igeteof_(xfp, xc, xeof=true;)
201 Igeteof_(ufp, uc, ueof=true;)
205 /* try to get both keywords */
208 Igeteof_(xfp, xc, xeof=true;)
209 Igeteof_(ufp, uc, ueof=true;)
216 if (xkeyword+keylength <= tp)
220 case '\n': case KDELIM: case VDELIM:
226 (xc==KDELIM || xc==VDELIM) && (uc==KDELIM || uc==VDELIM) &&
227 (*tp = xc, (match1 = trymatch(xkeyword)) != Nomatch)
230 VOID printf("found common keyword %s\n",xkeyword);
235 xc = discardkeyval(xc, xfp);
236 uc = discardkeyval(uc, ufp);
237 if ((xeof = xc==EOF) | (ueof = uc==EOF))
244 Igeteof_(xfp, xc, xeof=true;)
245 Igeteof_(ufp, uc, ueof=true;)
250 case '\n': case KDELIM:
259 /* Skip closing KDELIM. */
260 Igeteof_(xfp, xc, xeof=true;)
261 Igeteof_(ufp, uc, ueof=true;)
264 /* if the keyword is LOG, also skip the log message in xfp*/
266 /* first, compute the number of line feeds in log msg */
269 sp = delta->log.string;
270 ls = delta->log.size;
271 if (ls<sizeof(ciklog)-1 || memcmp(sp,ciklog,sizeof(ciklog)-1)) {
273 * This log message was inserted. Skip its header.
274 * The number of newlines to skip is
275 * 1 + (C+1)*(1+L+1), where C is the number of newlines
276 * in the comment leader, and L is the number of
277 * newlines in the log string.
280 for (ccnt=Comment.size; ccnt--; )
281 c1 += Comment.string[ccnt] == '\n';
283 while (ls--) if (*sp++=='\n') lncnt += c1;
286 if(--lncnt==0) break;
287 Igeteof_(xfp, xc, goto returnresult;)
289 /* skip last comment leader */
290 /* Can't just skip another line here, because there may be */
291 /* additional characters on the line (after the Log....$) */
292 ccnt = RCSversion<VERSION(5) ? Comment.size : leaderlen;
294 Igeteof_(xfp, xc, goto returnresult;)
296 * Read to the end of the comment leader or '\n',
297 * whatever comes first, because the leader's
298 * trailing white space was probably stripped.
300 } while (ccnt-- && (xc!='\n' || --c1));
304 /* both end in the same character, but not a KDELIM */
305 /* must compare string values.*/
307 VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
337 char const cmdid[] = "rcsfcmp";
340 int argc; char *argv[];
341 /* first argument: comment leader; 2nd: log message, 3rd: expanded file,
342 * 4th: unexpanded file
344 { struct hshentry delta;
346 Comment.string = argv[1];
347 Comment.size = strlen(argv[1]);
348 delta.log.string = argv[2];
349 delta.log.size = strlen(argv[2]);
350 if (rcsfcmp(Iopen(argv[3], FOPEN_R_WORK, (struct stat*)0), argv[4], &delta))
351 VOID printf("files are the same\n");
352 else VOID printf("files are different\n");