xref: /386bsd/usr/src/usr.bin/rcs/src/rcsfcmp.c (revision a2142627)
1 /*
2  *                     RCS file comparison
3  */
4 #ifndef lint
5 static char rcsid[]= "$Id: rcsfcmp.c,v 4.5 89/05/01 15:12:42 narten Exp $ Purdue CS";
6 #endif
7 /*****************************************************************************
8  *                       rcsfcmp()
9  *                       Testprogram: define FCMPTEST
10  *****************************************************************************
11  */
12 
13 /* Copyright (C) 1982, 1988, 1989 Walter Tichy
14  * All rights reserved.
15  *
16  * Redistribution and use in source and binary forms are permitted
17  * provided that the above copyright notice and this paragraph are
18  * duplicated in all such forms and that any documentation,
19  * advertising materials, and other materials related to such
20  * distribution and use acknowledge that the software was developed
21  * by Walter Tichy.
22  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25  *
26  * Report all problems and direct all questions to:
27  *   rcs-bugs@cs.purdue.edu
28  *
29 
30 
31 
32 
33 
34 
35 
36 */
37 
38 
39 
40 
41 
42 /* $Log:	rcsfcmp.c,v $
43  * Revision 4.5  89/05/01  15:12:42  narten
44  * changed copyright header to reflect current distribution rules
45  *
46  * Revision 4.4  88/11/08  12:01:33  narten
47  * changes from  eggert@sm.unisys.com (Paul Eggert)
48  *
49  * Revision 4.4  88/08/09  19:12:50  eggert
50  * Shrink stdio code size.
51  *
52  * Revision 4.3  87/12/18  11:40:02  narten
53  * lint cleanups (Guy Harris)
54  *
55  * Revision 4.2  87/10/18  10:33:06  narten
56  * updting version number. Changes relative to 1.1 actually relative to
57  * 4.1
58  *
59  * Revision 1.2  87/03/27  14:22:19  jenkins
60  * Port to suns
61  *
62  * Revision 1.1  84/01/23  14:50:23  kcs
63  * Initial revision
64  *
65  * Revision 4.1  83/05/10  16:24:04  wft
66  * Marker matching now uses trymatch(). Marker pattern is now
67  * checked precisely.
68  *
69  * Revision 3.1  82/12/04  13:21:40  wft
70  * Initial revision.
71  *
72  */
73 
74 /*
75 #define FCMPTEST
76 /* Testprogram; prints out whether two files are identical,
77  * except for keywords
78  */
79 
80 #include  "rcsbase.h"
81 extern FILE * fopen();
82 extern enum markers trymatch(); /* check for keywords */
83 
84 
rcsfcmp(xfname,uxfname,delta)85 rcsfcmp(xfname,uxfname,delta)
86 char * xfname, *uxfname; struct hshentry *delta;
87 /* Function: compares the files xfname and uxfname. Returns true
88  * if xfname has the same contents as uxfname, while disregarding
89  * keyword values. For the LOG-keyword, rcsfcmp skips the log message
90  * given by the parameter delta in xfname. Thus, rcsfcmp returns true
91  * if xfname contains the same as uxfname, with the keywords expanded.
92  * Implementation: character-by-character comparison until $ is found.
93  * If a $ is found, read in the marker keywords; if they are real keywords
94  * and identical, read in keyword value. If value is terminated properly,
95  * disregard it and optionally skip log message; otherwise, compare value.
96  */
97 {
98     register int xc,uxc;
99     char xkeyword[keylength+2],   uxkeyword[keylength+2];
100     char xkeyval[keyvallength+1], uxkeyval[keyvallength+1];
101     register FILE * xfp, * uxfp;
102     register char * tp;
103     int result;
104     enum markers match1,match2;
105 
106     if ((xfp=fopen(tp=xfname,"r"))==NULL || (uxfp=fopen(tp=uxfname,"r"))==NULL) {
107        faterror("Can't open %s\n", tp);
108        return false;
109     }
110     result=false;
111     xc=getc(xfp); uxc=getc(uxfp);
112     while( xc == uxc) { /* comparison loop */
113         if (xc==EOF) { /* finished; everything is the same*/
114             result=true;
115             break;
116         }
117         if ( xc!=KDELIM) {
118             /* get the next characters */
119             xc=getc(xfp); uxc=getc(uxfp);
120         } else {
121             /* try to get both keywords */
122             tp = xkeyword;
123             while( (xc=getc(xfp))!=EOF && (tp< xkeyword+keylength) && (xc!='\n')
124                    && (xc!=KDELIM) && (xc!=VDELIM))
125                 *tp++ = xc;
126 	    *tp++ = xc;  /* add closing K/VDELIM */
127             *tp='\0';
128             tp = uxkeyword;
129             while( (uxc=getc(uxfp))!=EOF && (tp< uxkeyword+keylength) && (uxc!='\n')
130                    && (uxc!=KDELIM) && (uxc!=VDELIM))
131                 *tp++ = uxc;
132 	    *tp++ = xc;  /* add closing K/VDELIM */
133             *tp='\0';
134             /* now we have 2 keywords, or something thal looks like it.*/
135 	    match1=trymatch(xkeyword,false);
136 	    match2=trymatch(uxkeyword,false);
137 	    if (match1 != match2) break; /* not identical */
138 #ifdef FCMPTEST
139 	    VOID printf("found potential keywords %s and %s\n",xkeyword,uxkeyword);
140 #endif
141 
142 	    if (match1 == Nomatch) {
143 		/* not a keyword pattern, but could still be identical */
144 		if (strcmp(xkeyword,uxkeyword)==0)
145 		     continue;
146 		else break;
147 	    }
148 #ifdef FCMPTEST
149 	    VOID printf("found common keyword %s\n",xkeyword);
150 #endif
151 	    tp=xkeyval;
152 	    if (xc==VDELIM) {/* get value */
153 		while (((xc=getc(xfp))!=KDELIM) && (xc!='\n') && (xc!=EOF) &&
154 			(tp<xkeyval+keyvallength))
155 		    *tp++ = xc;
156 	    }
157 	    *tp = '\0';   /*xkeyval now filled with value; possibly empty*/
158 	    tp=uxkeyval;
159 	    if (uxc==VDELIM) {/* get value */
160 		while (((uxc=getc(uxfp))!=KDELIM) && (uxc!='\n') && (uxc!=EOF) &&
161 			(tp<uxkeyval+keyvallength))
162 		    *tp++ = uxc;
163 	    }
164 	    *tp = '\0';   /*uxkeyval now filled with value; possibly empty*/
165 	    if (xc!=uxc) break; /* not the same */
166 	    if (xc==KDELIM) {
167 		xc=getc(xfp); uxc=getc(uxfp); /* skip closing KDELIM */
168 		/* if the keyword is LOG, also skip the log message in xfp*/
169 		if (match1==Log) {
170 		    /* first, compute the number of line feeds in log msg */
171 		    int lncnt, ccnt;
172 		    lncnt=2; tp=delta->log;
173 		    while(*tp) if(*tp++=='\n') lncnt++;
174 		    while(xc!=EOF) {
175 			if (xc=='\n')
176 			    if(--lncnt==0) break;
177 			xc=getc(xfp);
178 		    }
179 		    /* skip last comment leader */
180 		    /* Can't just skip another line here, because there may be */
181 		    /* additional characters on the line (after the Log....$)  */
182 		    for (ccnt=strlen(Comment); ccnt>=0; lncnt--) {
183 			xc=getc(xfp);
184 			if(xc=='\n') break;
185 			/* reads to the end of the comment leader or '\n',     */
186 			/* whatever comes first. This is because some editors  */
187 			/* strip off trailing blanks from a leader like " * ". */
188 		    }
189 		}
190 	    } else {
191 		/* both end in the same character, but not a KDELIM */
192 		/* must compare string values.*/
193 #ifdef FCMPTEST
194 		VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
195 #endif
196 		if (strcmp(xkeyval,uxkeyval)!=0) break; /*different */
197 		xc=getc(xfp); uxc=getc(uxfp); /* skip closing char  */
198             }
199         }
200     }
201     VOID fclose(xfp); VOID fclose(uxfp);
202     return result;
203 }
204 
205 
206 
207 #ifdef FCMPTEST
208 char * RCSfilename, * workfilename;
209 
210 char * Comment;
211 
main(argc,argv)212 main(argc, argv)
213 int  argc; char  *argv[];
214 /* first argument: comment leader; 2nd: log message, 3rd: expanded file,
215  * 4th: unexpanded file
216  */
217 {       struct hshentry delta;
218 
219         cmdid="rcsfcmp";
220         Comment=argv[1];
221         delta.log=argv[2];
222         if (rcsfcmp(argv[3],argv[4],&delta))
223                 VOID printf("files are the same\n");
224         else    VOID printf("files are different\n");
225 }
226 #endif
227