Sync usage with man page.
[netbsd-mini2440.git] / gnu / usr.bin / rcs / lib / rcsfcmp.c
blobf6761cbb2c2efcca2b49c87640896c59abdef4f9
1 /* $NetBSD: rcsfcmp.c,v 1.1.1.2 1996/10/13 21:57:01 veego Exp $ */
3 /* Compare working files, ignoring RCS keyword strings. */
5 /*****************************************************************************
6 * rcsfcmp()
7 * Testprogram: define FCMPTEST
8 *****************************************************************************
9 */
11 /* Copyright 1982, 1988, 1989 Walter Tichy
12 Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
13 Distributed under license by the Free Software Foundation, Inc.
15 This file is part of RCS.
17 RCS is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation; either version 2, or (at your option)
20 any later version.
22 RCS is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with RCS; see the file COPYING.
29 If not, write to the Free Software Foundation,
30 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 Report problems and direct all questions to:
34 rcs-bugs@cs.purdue.edu
43 * $Log: rcsfcmp.c,v $
44 * Revision 5.14 1995/06/16 06:19:24 eggert
45 * Update FSF address.
47 * Revision 5.13 1995/06/01 16:23:43 eggert
48 * (rcsfcmp): Add -kb support.
50 * Revision 5.12 1994/03/17 14:05:48 eggert
51 * Normally calculate the $Log prefix from context, not from RCS file.
52 * Calculate line numbers correctly even if the $Log prefix contains newlines.
53 * Remove lint.
55 * Revision 5.11 1993/11/03 17:42:27 eggert
56 * Fix yet another off-by-one error when comparing Log string expansions.
58 * Revision 5.10 1992/07/28 16:12:44 eggert
59 * Statement macro names now end in _.
61 * Revision 5.9 1991/10/07 17:32:46 eggert
62 * Count log lines correctly.
64 * Revision 5.8 1991/08/19 03:13:55 eggert
65 * Tune.
67 * Revision 5.7 1991/04/21 11:58:22 eggert
68 * Fix errno bug. Add MS-DOS support.
70 * Revision 5.6 1991/02/28 19:18:47 eggert
71 * Open work file at most once.
73 * Revision 5.5 1990/11/27 09:26:05 eggert
74 * Fix comment leader bug.
76 * Revision 5.4 1990/11/01 05:03:42 eggert
77 * Permit arbitrary data in logs and comment leaders.
79 * Revision 5.3 1990/09/11 02:41:15 eggert
80 * Don't ignore differences inside keyword strings if -ko is set.
82 * Revision 5.1 1990/08/29 07:13:58 eggert
83 * Clean old log messages too.
85 * Revision 5.0 1990/08/22 08:12:49 eggert
86 * Don't append "checked in with -k by " log to logs,
87 * so that checking in a program with -k doesn't change it.
88 * Ansify and Posixate. Remove lint.
90 * Revision 4.5 89/05/01 15:12:42 narten
91 * changed copyright header to reflect current distribution rules
93 * Revision 4.4 88/08/09 19:12:50 eggert
94 * Shrink stdio code size.
96 * Revision 4.3 87/12/18 11:40:02 narten
97 * lint cleanups (Guy Harris)
99 * Revision 4.2 87/10/18 10:33:06 narten
100 * updting version number. Changes relative to 1.1 actually relative to
101 * 4.1
103 * Revision 1.2 87/03/27 14:22:19 jenkins
104 * Port to suns
106 * Revision 4.1 83/05/10 16:24:04 wft
107 * Marker matching now uses trymatch(). Marker pattern is now
108 * checked precisely.
110 * Revision 3.1 82/12/04 13:21:40 wft
111 * Initial revision.
116 #define FCMPTEST
118 /* Testprogram; prints out whether two files are identical,
119 * except for keywords
122 #include "rcsbase.h"
124 libId(fcmpId, "Id: rcsfcmp.c,v 5.14 1995/06/16 06:19:24 eggert Exp")
126 static int discardkeyval P((int,RILE*));
127 static int
128 discardkeyval(c, f)
129 register int c;
130 register RILE *f;
132 for (;;)
133 switch (c) {
134 case KDELIM:
135 case '\n':
136 return c;
137 default:
138 Igeteof_(f, c, return EOF;)
139 break;
144 rcsfcmp(xfp, xstatp, uname, delta)
145 register RILE *xfp;
146 struct stat const *xstatp;
147 char const *uname;
148 struct hshentry const *delta;
149 /* Compare the files xfp and uname. Return zero
150 * if xfp has the same contents as uname and neither has keywords,
151 * otherwise -1 if they are the same ignoring keyword values,
152 * and 1 if they differ even ignoring
153 * keyword values. For the LOG-keyword, rcsfcmp skips the log message
154 * given by the parameter delta in xfp. Thus, rcsfcmp returns nonpositive
155 * if xfp contains the same as uname, with the keywords expanded.
156 * Implementation: character-by-character comparison until $ is found.
157 * If a $ is found, read in the marker keywords; if they are real keywords
158 * and identical, read in keyword value. If value is terminated properly,
159 * disregard it and optionally skip log message; otherwise, compare value.
162 register int xc, uc;
163 char xkeyword[keylength+2];
164 int eqkeyvals;
165 register RILE *ufp;
166 register int xeof, ueof;
167 register char * tp;
168 register char const *sp;
169 register size_t leaderlen;
170 int result;
171 enum markers match1;
172 struct stat ustat;
174 if (!(ufp = Iopen(uname, FOPEN_R_WORK, &ustat))) {
175 efaterror(uname);
177 xeof = ueof = false;
178 if (MIN_UNEXPAND <= Expand) {
179 if (!(result = xstatp->st_size!=ustat.st_size)) {
180 # if large_memory && maps_memory
181 result = !!memcmp(xfp->base,ufp->base,(size_t)xstatp->st_size);
182 # else
183 for (;;) {
184 /* get the next characters */
185 Igeteof_(xfp, xc, xeof=true;)
186 Igeteof_(ufp, uc, ueof=true;)
187 if (xeof | ueof)
188 goto eof;
189 if (xc != uc)
190 goto return1;
192 # endif
194 } else {
195 xc = 0;
196 uc = 0; /* Keep lint happy. */
197 leaderlen = 0;
198 result = 0;
200 for (;;) {
201 if (xc != KDELIM) {
202 /* get the next characters */
203 Igeteof_(xfp, xc, xeof=true;)
204 Igeteof_(ufp, uc, ueof=true;)
205 if (xeof | ueof)
206 goto eof;
207 } else {
208 /* try to get both keywords */
209 tp = xkeyword;
210 for (;;) {
211 Igeteof_(xfp, xc, xeof=true;)
212 Igeteof_(ufp, uc, ueof=true;)
213 if (xeof | ueof)
214 goto eof;
215 if (xc != uc)
216 break;
217 switch (xc) {
218 default:
219 if (xkeyword+keylength <= tp)
220 break;
221 *tp++ = xc;
222 continue;
223 case '\n': case KDELIM: case VDELIM:
224 break;
226 break;
228 if (
229 (xc==KDELIM || xc==VDELIM) && (uc==KDELIM || uc==VDELIM) &&
230 (*tp = xc, (match1 = trymatch(xkeyword)) != Nomatch)
232 #ifdef FCMPTEST
233 VOID printf("found common keyword %s\n",xkeyword);
234 #endif
235 result = -1;
236 for (;;) {
237 if (xc != uc) {
238 xc = discardkeyval(xc, xfp);
239 uc = discardkeyval(uc, ufp);
240 if ((xeof = xc==EOF) | (ueof = uc==EOF))
241 goto eof;
242 eqkeyvals = false;
243 break;
245 switch (xc) {
246 default:
247 Igeteof_(xfp, xc, xeof=true;)
248 Igeteof_(ufp, uc, ueof=true;)
249 if (xeof | ueof)
250 goto eof;
251 continue;
253 case '\n': case KDELIM:
254 eqkeyvals = true;
255 break;
257 break;
259 if (xc != uc)
260 goto return1;
261 if (xc==KDELIM) {
262 /* Skip closing KDELIM. */
263 Igeteof_(xfp, xc, xeof=true;)
264 Igeteof_(ufp, uc, ueof=true;)
265 if (xeof | ueof)
266 goto eof;
267 /* if the keyword is LOG, also skip the log message in xfp*/
268 if (match1==Log) {
269 /* first, compute the number of line feeds in log msg */
270 int lncnt;
271 size_t ls, ccnt;
272 sp = delta->log.string;
273 ls = delta->log.size;
274 if (ls<sizeof(ciklog)-1 || memcmp(sp,ciklog,sizeof(ciklog)-1)) {
276 * This log message was inserted. Skip its header.
277 * The number of newlines to skip is
278 * 1 + (C+1)*(1+L+1), where C is the number of newlines
279 * in the comment leader, and L is the number of
280 * newlines in the log string.
282 int c1 = 1;
283 for (ccnt=Comment.size; ccnt--; )
284 c1 += Comment.string[ccnt] == '\n';
285 lncnt = 2*c1 + 1;
286 while (ls--) if (*sp++=='\n') lncnt += c1;
287 for (;;) {
288 if (xc=='\n')
289 if(--lncnt==0) break;
290 Igeteof_(xfp, xc, goto returnresult;)
292 /* skip last comment leader */
293 /* Can't just skip another line here, because there may be */
294 /* additional characters on the line (after the Log....$) */
295 ccnt = RCSversion<VERSION(5) ? Comment.size : leaderlen;
296 do {
297 Igeteof_(xfp, xc, goto returnresult;)
299 * Read to the end of the comment leader or '\n',
300 * whatever comes first, because the leader's
301 * trailing white space was probably stripped.
303 } while (ccnt-- && (xc!='\n' || --c1));
306 } else {
307 /* both end in the same character, but not a KDELIM */
308 /* must compare string values.*/
309 #ifdef FCMPTEST
310 VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
311 #endif
312 if (!eqkeyvals)
313 goto return1;
317 if (xc != uc)
318 goto return1;
319 if (xc == '\n')
320 leaderlen = 0;
321 else
322 leaderlen++;
326 eof:
327 if (xeof==ueof)
328 goto returnresult;
329 return1:
330 result = 1;
331 returnresult:
332 Ifclose(ufp);
333 return result;
338 #ifdef FCMPTEST
340 char const cmdid[] = "rcsfcmp";
342 main(argc, argv)
343 int argc; char *argv[];
344 /* first argument: comment leader; 2nd: log message, 3rd: expanded file,
345 * 4th: unexpanded file
347 { struct hshentry delta;
349 Comment.string = argv[1];
350 Comment.size = strlen(argv[1]);
351 delta.log.string = argv[2];
352 delta.log.size = strlen(argv[2]);
353 if (rcsfcmp(Iopen(argv[3], FOPEN_R_WORK, (struct stat*)0), argv[4], &delta))
354 VOID printf("files are the same\n");
355 else VOID printf("files are different\n");
357 #endif