1: /*
2: * RCS file comparison
3: */
4: #ifndef lint
5: static char rcsid[]= "$Id: rcsfcmp.c,v 4.3 87/12/18 11:40:02 narten Exp $ Purdue CS";
6: #endif
7: /*****************************************************************************
8: * rcsfcmp()
9: * Testprogram: define FCMPTEST
10: *****************************************************************************
11: *
12: * Copyright (C) 1982 by Walter F. Tichy
13: * Purdue University
14: * Computer Science Department
15: * West Lafayette, IN 47907
16: *
17: * All rights reserved. No part of this software may be sold or distributed
18: * in any form or by any means without the prior written permission of the
19: * author.
20: * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
21: */
22:
23:
24:
25: /* $Log: rcsfcmp.c,v $
26: * Revision 4.3 87/12/18 11:40:02 narten
27: * lint cleanups (Guy Harris)
28: *
29: * Revision 4.2 87/10/18 10:33:06 narten
30: * updting version number. Changes relative to 1.1 actually relative to
31: * 4.1
32: *
33: * Revision 1.2 87/03/27 14:22:19 jenkins
34: * Port to suns
35: *
36: * Revision 1.1 84/01/23 14:50:23 kcs
37: * Initial revision
38: *
39: * Revision 4.1 83/05/10 16:24:04 wft
40: * Marker matching now uses trymatch(). Marker pattern is now
41: * checked precisely.
42: *
43: * Revision 3.1 82/12/04 13:21:40 wft
44: * Initial revision.
45: *
46: */
47:
48: /*
49: #define FCMPTEST
50: /* Testprogram; prints out whether two files are identical,
51: * except for keywords
52: */
53:
54: #include "rcsbase.h"
55: extern FILE * fopen();
56: extern enum markers trymatch(); /* check for keywords */
57:
58:
59: rcsfcmp(xfname,uxfname,delta)
60: char * xfname, *uxfname; struct hshentry *delta;
61: /* Function: compares the files xfname and uxfname. Returns true
62: * if xfname has the same contents as uxfname, while disregarding
63: * keyword values. For the LOG-keyword, rcsfcmp skips the log message
64: * given by the parameter delta in xfname. Thus, rcsfcmp returns true
65: * if xfname contains the same as uxfname, with the keywords expanded.
66: * Implementation: character-by-character comparison until $ is found.
67: * If a $ is found, read in the marker keywords; if they are real keywords
68: * and identical, read in keyword value. If value is terminated properly,
69: * disregard it and optionally skip log message; otherwise, compare value.
70: */
71: {
72: register int xc,uxc;
73: char xkeyword[keylength+2], uxkeyword[keylength+2];
74: char xkeyval[keyvallength+1], uxkeyval[keyvallength+1];
75: register char * tp;
76: FILE * xfp, * uxfp;
77: int result;
78: enum markers match1,match2;
79:
80: if ((xfp=fopen(tp=xfname,"r"))==NULL || (uxfp=fopen(tp=uxfname,"r"))==NULL) {
81: faterror("Can't open %s\n", tp);
82: return false;
83: }
84: result=false;
85: xc=getc(xfp); uxc=getc(uxfp);
86: while( xc == uxc) { /* comparison loop */
87: if (xc==EOF) { /* finished; everything is the same*/
88: result=true;
89: break;
90: }
91: if ( xc!=KDELIM) {
92: /* get the next characters */
93: xc=getc(xfp); uxc=getc(uxfp);
94: } else {
95: /* try to get both keywords */
96: tp = xkeyword;
97: while( (xc=getc(xfp))!=EOF && (tp< xkeyword+keylength) && (xc!='\n')
98: && (xc!=KDELIM) && (xc!=VDELIM))
99: *tp++ = xc;
100: *tp++ = xc; /* add closing K/VDELIM */
101: *tp='\0';
102: tp = uxkeyword;
103: while( (uxc=getc(uxfp))!=EOF && (tp< uxkeyword+keylength) && (uxc!='\n')
104: && (uxc!=KDELIM) && (uxc!=VDELIM))
105: *tp++ = uxc;
106: *tp++ = xc; /* add closing K/VDELIM */
107: *tp='\0';
108: /* now we have 2 keywords, or something thal looks like it.*/
109: match1=trymatch(xkeyword,false);
110: match2=trymatch(uxkeyword,false);
111: if (match1 != match2) break; /* not identical */
112: #ifdef FCMPTEST
113: VOID printf("found potential keywords %s and %s\n",xkeyword,uxkeyword);
114: #endif
115:
116: if (match1 == Nomatch) {
117: /* not a keyword pattern, but could still be identical */
118: if (strcmp(xkeyword,uxkeyword)==0)
119: continue;
120: else break;
121: }
122: #ifdef FCMPTEST
123: VOID printf("found common keyword %s\n",xkeyword);
124: #endif
125: tp=xkeyval;
126: if (xc==VDELIM) {/* get value */
127: while (((xc=getc(xfp))!=KDELIM) && (xc!='\n') && (xc!=EOF) &&
128: (tp<xkeyval+keyvallength))
129: *tp++ = xc;
130: }
131: *tp = '\0'; /*xkeyval now filled with value; possibly empty*/
132: tp=uxkeyval;
133: if (uxc==VDELIM) {/* get value */
134: while (((uxc=getc(uxfp))!=KDELIM) && (uxc!='\n') && (uxc!=EOF) &&
135: (tp<uxkeyval+keyvallength))
136: *tp++ = uxc;
137: }
138: *tp = '\0'; /*uxkeyval now filled with value; possibly empty*/
139: if (xc!=uxc) break; /* not the same */
140: if (xc==KDELIM) {
141: xc=getc(xfp); uxc=getc(uxfp); /* skip closing KDELIM */
142: /* if the keyword is LOG, also skip the log message in xfp*/
143: if (match1==Log) {
144: /* first, compute the number of line feeds in log msg */
145: int lncnt, ccnt;
146: lncnt=2; tp=delta->log;
147: while(*tp) if(*tp++=='\n') lncnt++;
148: while(xc!=EOF) {
149: if (xc=='\n')
150: if(--lncnt==0) break;
151: xc=getc(xfp);
152: }
153: /* skip last comment leader */
154: /* Can't just skip another line here, because there may be */
155: /* additional characters on the line (after the Log....$) */
156: for (ccnt=strlen(Comment); ccnt>=0; lncnt--) {
157: xc=getc(xfp);
158: if(xc=='\n') break;
159: /* reads to the end of the comment leader or '\n', */
160: /* whatever comes first. This is because some editors */
161: /* strip off trailing blanks from a leader like " * ". */
162: }
163: }
164: } else {
165: /* both end in the same character, but not a KDELIM */
166: /* must compare string values.*/
167: #ifdef FCMPTEST
168: VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
169: #endif
170: if (strcmp(xkeyval,uxkeyval)!=0) break; /*different */
171: xc=getc(xfp); uxc=getc(uxfp); /* skip closing char */
172: }
173: }
174: }
175: VOID fclose(xfp); VOID fclose(uxfp);
176: return result;
177: }
178:
179:
180:
181: #ifdef FCMPTEST
182: char * RCSfilename, * workfilename;
183:
184: char * ;
185:
186: main(argc, argv)
187: int argc; char *argv[];
188: /* first argument: comment leader; 2nd: log message, 3rd: expanded file,
189: * 4th: unexpanded file
190: */
191: { struct hshentry delta;
192:
193: cmdid="rcsfcmp";
194: Comment=argv[1];
195: delta.log=argv[2];
196: if (rcsfcmp(argv[3],argv[4],&delta))
197: VOID printf("files are the same\n");
198: else VOID printf("files are different\n");
199: }
200: #endif