]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - gnu/usr.bin/rcs/lib/rcsfcmp.c
This is the Linux generic soundcard driver, version 1.0c. Supports
[FreeBSD/FreeBSD.git] / gnu / usr.bin / rcs / lib / rcsfcmp.c
1 /*
2  *                     RCS file comparison
3  */
4 /*****************************************************************************
5  *                       rcsfcmp()
6  *                       Testprogram: define FCMPTEST
7  *****************************************************************************
8  */
9
10 /* Copyright (C) 1982, 1988, 1989 Walter Tichy
11    Copyright 1990, 1991 by Paul Eggert
12    Distributed under license by the Free Software Foundation, Inc.
13
14 This file is part of RCS.
15
16 RCS is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 2, or (at your option)
19 any later version.
20
21 RCS is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with RCS; see the file COPYING.  If not, write to
28 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29
30 Report problems and direct all questions to:
31
32     rcs-bugs@cs.purdue.edu
33
34 */
35
36
37
38
39
40 /* $Log: rcsfcmp.c,v $
41  * Revision 5.9  1991/10/07  17:32:46  eggert
42  * Count log lines correctly.
43  *
44  * Revision 5.8  1991/08/19  03:13:55  eggert
45  * Tune.
46  *
47  * Revision 5.7  1991/04/21  11:58:22  eggert
48  * Fix errno bug.  Add MS-DOS support.
49  *
50  * Revision 5.6  1991/02/28  19:18:47  eggert
51  * Open work file at most once.
52  *
53  * Revision 5.5  1990/11/27  09:26:05  eggert
54  * Fix comment leader bug.
55  *
56  * Revision 5.4  1990/11/01  05:03:42  eggert
57  * Permit arbitrary data in logs and comment leaders.
58  *
59  * Revision 5.3  1990/09/11  02:41:15  eggert
60  * Don't ignore differences inside keyword strings if -ko is set.
61  *
62  * Revision 5.1  1990/08/29  07:13:58  eggert
63  * Clean old log messages too.
64  *
65  * Revision 5.0  1990/08/22  08:12:49  eggert
66  * Don't append "checked in with -k by " log to logs,
67  * so that checking in a program with -k doesn't change it.
68  * Ansify and Posixate.  Remove lint.
69  *
70  * Revision 4.5  89/05/01  15:12:42  narten
71  * changed copyright header to reflect current distribution rules
72  * 
73  * Revision 4.4  88/08/09  19:12:50  eggert
74  * Shrink stdio code size.
75  * 
76  * Revision 4.3  87/12/18  11:40:02  narten
77  * lint cleanups (Guy Harris)
78  * 
79  * Revision 4.2  87/10/18  10:33:06  narten
80  * updting version number. Changes relative to 1.1 actually relative to 
81  * 4.1
82  * 
83  * Revision 1.2  87/03/27  14:22:19  jenkins
84  * Port to suns
85  * 
86  * Revision 4.1  83/05/10  16:24:04  wft
87  * Marker matching now uses trymatch(). Marker pattern is now
88  * checked precisely.
89  * 
90  * Revision 3.1  82/12/04  13:21:40  wft
91  * Initial revision.
92  *
93  */
94
95 /*
96 #define FCMPTEST
97 */
98 /* Testprogram; prints out whether two files are identical,
99  * except for keywords
100  */
101
102 #include  "rcsbase.h"
103
104 libId(fcmpId, "$Id: rcsfcmp.c,v 5.9 1991/10/07 17:32:46 eggert Exp $")
105
106         static int
107 discardkeyval(c, f)
108         register int c;
109         register RILE *f;
110 {
111         for (;;)
112                 switch (c) {
113                         case KDELIM:
114                         case '\n':
115                                 return c;
116                         default:
117                                 Igeteof(f, c, return EOF;);
118                                 break;
119                 }
120 }
121
122         int
123 rcsfcmp(xfp, xstatp, ufname, delta)
124         register RILE *xfp;
125         struct stat const *xstatp;
126         char const *ufname;
127         struct hshentry const *delta;
128 /* Compare the files xfp and ufname.  Return zero
129  * if xfp has the same contents as ufname and neither has keywords,
130  * otherwise -1 if they are the same ignoring keyword values,
131  * and 1 if they differ even ignoring
132  * keyword values. For the LOG-keyword, rcsfcmp skips the log message
133  * given by the parameter delta in xfp.  Thus, rcsfcmp returns nonpositive
134  * if xfp contains the same as ufname, with the keywords expanded.
135  * Implementation: character-by-character comparison until $ is found.
136  * If a $ is found, read in the marker keywords; if they are real keywords
137  * and identical, read in keyword value. If value is terminated properly,
138  * disregard it and optionally skip log message; otherwise, compare value.
139  */
140 {
141     register int xc, uc;
142     char xkeyword[keylength+2];
143     int eqkeyvals;
144     register RILE *ufp;
145     register int xeof, ueof;
146     register char * tp;
147     register char const *sp;
148     int result;
149     enum markers match1;
150     struct stat ustat;
151
152     if (!(ufp = Iopen(ufname, FOPEN_R_WORK, &ustat))) {
153        efaterror(ufname);
154     }
155     xeof = ueof = false;
156     if (Expand==OLD_EXPAND) {
157         if (!(result = xstatp->st_size!=ustat.st_size)) {
158 #           if has_mmap && large_memory
159                 result = !!memcmp(xfp->base,ufp->base,(size_t)xstatp->st_size);
160 #           else
161                 for (;;) {
162                     /* get the next characters */
163                     Igeteof(xfp, xc, xeof=true;);
164                     Igeteof(ufp, uc, ueof=true;);
165                     if (xeof | ueof)
166                         goto eof;
167                     if (xc != uc)
168                         goto return1;
169                 }
170 #           endif
171         }
172     } else {
173         xc = 0;
174         uc = 0; /* Keep lint happy.  */
175         result = 0;
176
177         for (;;) {
178           if (xc != KDELIM) {
179             /* get the next characters */
180             Igeteof(xfp, xc, xeof=true;);
181             Igeteof(ufp, uc, ueof=true;);
182             if (xeof | ueof)
183                 goto eof;
184           } else {
185             /* try to get both keywords */
186             tp = xkeyword;
187             for (;;) {
188                 Igeteof(xfp, xc, xeof=true;);
189                 Igeteof(ufp, uc, ueof=true;);
190                 if (xeof | ueof)
191                     goto eof;
192                 if (xc != uc)
193                     break;
194                 switch (xc) {
195                     default:
196                         if (xkeyword+keylength <= tp)
197                             break;
198                         *tp++ = xc;
199                         continue;
200                     case '\n': case KDELIM: case VDELIM:
201                         break;
202                 }
203                 break;
204             }
205             if (
206                 (xc==KDELIM || xc==VDELIM)  &&  (uc==KDELIM || uc==VDELIM)  &&
207                 (*tp = xc,  (match1 = trymatch(xkeyword)) != Nomatch)
208             ) {
209 #ifdef FCMPTEST
210               VOID printf("found common keyword %s\n",xkeyword);
211 #endif
212               result = -1;
213               for (;;) {
214                   if (xc != uc) {
215                       xc = discardkeyval(xc, xfp);
216                       uc = discardkeyval(uc, ufp);
217                       if ((xeof = xc==EOF)  |  (ueof = uc==EOF))
218                           goto eof;
219                       eqkeyvals = false;
220                       break;
221                   }
222                   switch (xc) {
223                       default:
224                           Igeteof(xfp, xc, xeof=true;);
225                           Igeteof(ufp, uc, ueof=true;);
226                           if (xeof | ueof)
227                               goto eof;
228                           continue;
229
230                       case '\n': case KDELIM:
231                           eqkeyvals = true;
232                           break;
233                   }
234                   break;
235               }
236               if (xc != uc)
237                   goto return1;
238               if (xc==KDELIM) {
239                   /* Skip closing KDELIM.  */
240                   Igeteof(xfp, xc, xeof=true;);
241                   Igeteof(ufp, uc, ueof=true;);
242                   if (xeof | ueof)
243                       goto eof;
244                   /* if the keyword is LOG, also skip the log message in xfp*/
245                   if (match1==Log) {
246                       /* first, compute the number of line feeds in log msg */
247                       unsigned lncnt;
248                       size_t ls, ccnt;
249                       sp = delta->log.string;
250                       ls = delta->log.size;
251                       if (ls<sizeof(ciklog)-1 || memcmp(sp,ciklog,sizeof(ciklog)-1)) {
252                         /* This log message was inserted.  */
253                         lncnt = 3;
254                         while (ls--) if (*sp++=='\n') lncnt++;
255                         for (;;) {
256                             if (xc=='\n')
257                                 if(--lncnt==0) break;
258                             Igeteof(xfp, xc, goto returnresult;);
259                         }
260                         /* skip last comment leader */
261                         /* Can't just skip another line here, because there may be */
262                         /* additional characters on the line (after the Log....$)  */
263                         for (ccnt=Comment.size; ccnt--; ) {
264                             Igeteof(xfp, xc, goto returnresult;);
265                             if(xc=='\n') break;
266                             /*
267                              * Read to the end of the comment leader or '\n',
268                              * whatever comes first.  Some editors strip
269                              * trailing white space from a leader like " * ".
270                              */
271                         }
272                       }
273                   }
274               } else {
275                   /* both end in the same character, but not a KDELIM */
276                   /* must compare string values.*/
277 #ifdef FCMPTEST
278                   VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
279 #endif
280                   if (!eqkeyvals)
281                       goto return1;
282               }
283             }
284           }
285           if (xc != uc)
286               goto return1;
287         }
288     }
289
290   eof:
291     if (xeof==ueof)
292         goto returnresult;
293   return1:
294     result = 1;
295   returnresult:
296     Ifclose(ufp);
297     return result;
298 }
299
300
301
302 #ifdef FCMPTEST
303
304 char const cmdid[] = "rcsfcmp";
305
306 main(argc, argv)
307 int  argc; char  *argv[];
308 /* first argument: comment leader; 2nd: log message, 3rd: expanded file,
309  * 4th: unexpanded file
310  */
311 {       struct hshentry delta;
312
313         Comment.string = argv[1];
314         Comment.size = strlen(argv[1]);
315         delta.log.string = argv[2];
316         delta.log.size = strlen(argv[2]);
317         if (rcsfcmp(Iopen(argv[3], FOPEN_R_WORK, (struct stat*)0), argv[4], &delta))
318                 VOID printf("files are the same\n");
319         else    VOID printf("files are different\n");
320 }
321 #endif