Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtappbuilder / src / abmf / merge_c.c
1
2 /*
3  *      $XConsortium: merge_c.c /main/4 1996/10/02 13:38:19 drk $
4  *
5  *      @(#)merge_c.c   1.9 27 Mar 1995 cde_app_builder/src/abmf
6  *
7  *      RESTRICTED CONFIDENTIAL INFORMATION:
8  *      
9  *      The information in this document is subject to special
10  *      restrictions in a confidential disclosure agreement between
11  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
12  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
13  *      Sun's specific written approval.  This document and all copies
14  *      and derivative works thereof must be returned or destroyed at
15  *      Sun's request.
16  *
17  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
18  *
19  */
20
21
22 /*
23  *  merge_c.c - merge C source files with "magic" comments
24  */
25
26 #include <assert.h>
27 #include "parse_cP.h"
28 #include "merge_cP.h"
29
30 /*************************************************************************
31 **                                                                      **
32 **       Constants (#define and const)                                  **
33 **                                                                      **
34 **************************************************************************/
35
36 /*************************************************************************
37 **                                                                      **
38 **       Private Functions (C declarations and macros)                  **
39 **                                                                      **
40 **************************************************************************/
41
42 static int      merge_files_by_segment(
43                         File            oldFile, 
44                         CSegArray       oldSegs, 
45                         STRING          oldFileName,
46                         File            newFile, 
47                         CSegArray       newSegs, 
48                         STRING          newFileName,
49                         File            *mergedFileOutPtr,
50                         File            *deltaFileOutPtr
51                 );
52
53 static int      match_all_segments(CSegArray newSegs, CSegArray oldSegs);
54
55 static CSeg     match_segment(
56                         CSeg            oldSeg, 
57                         CSegArray       oldSegArray,
58                         CSegArray       newSegArray
59 );
60
61
62 /*************************************************************************
63 **                                                                      **
64 **       Data                                                           **
65 **                                                                      **
66 **************************************************************************/
67
68 /*************************************************************************
69 **                                                                      **
70 **       Function Definitions                                           **
71 **                                                                      **
72 **************************************************************************/
73
74 int     
75 abmfP_merge_c_files(
76                         File    oldFile,
77                         STRING  oldFileName,
78                         File    newFile,
79                         STRING  newFileName,
80                         File    *mergedFileOutPtr,
81                         File    *deltaFileOutPtr
82 )
83 {
84     int         return_value = 0;
85     int         rc = 0;                         /* return code */
86     CSegArray   newSegs = NULL;
87     CSegArray   oldSegs = NULL;
88     File        mergedFile = NULL;
89     File        deltaFile = NULL;
90
91     /*
92     if (debugging())
93     {
94         long    off = 0;
95         FILE    *fp = NULL;
96         int     c = 0;
97
98         if (oldFile != NULL)
99         {
100             fp = util_fopen_locked("merge-old", "w");
101             assert(fp != NULL);
102             off = ftell(oldFile);
103             while ((c = fgetc(oldFile)) != EOF)
104             {
105                 fputc(c, fp);
106             }
107             util_fclose(fp);
108             fseek(oldFile, off, SEEK_SET);
109         }
110
111         if (newFile != NULL)
112         {
113             fp = util_fopen_locked("merge-new", "w");
114             assert(fp != NULL);
115             off = ftell(newFile);
116             while ((c = fgetc(newFile)) != EOF)
117             {
118                 fputc(c, fp);
119             }
120             util_fclose(fp);
121             fseek(newFile, off, SEEK_SET);
122         }
123     }
124     */
125
126     if (oldFile != NULL)
127     {
128         rc = abmfP_parse_c_file(oldFile, &oldSegs);
129         return_if_err(rc,rc);
130     }
131     if (newFile != NULL)
132     {
133         rc = abmfP_parse_c_file(newFile, &newSegs);
134         return_if_err(rc,rc);
135     }
136
137     rc = merge_files_by_segment(
138                         oldFile, oldSegs, oldFileName,
139                         newFile, newSegs, newFileName,
140                         &mergedFile, 
141                         &deltaFile);
142     if (rc < 0)
143     {
144         return_value = rc;
145     }
146     else
147     {
148         *mergedFileOutPtr = mergedFile;
149         if (deltaFileOutPtr != NULL)
150         {
151             *deltaFileOutPtr = deltaFile;
152         }
153     }
154
155 epilogue:
156     cseg_array_destroy(oldSegs);
157     cseg_array_destroy(newSegs);
158     return return_value;
159 }
160
161
162 /*
163  * Merges segments in C files
164  *
165  * Assumes: all segments and user segments are sorted by beginning offset.
166  */
167 static int
168 merge_files_by_segment(
169                         File            oldFile, 
170                         CSegArray       oldSegs, 
171                         STRING          oldFileName,
172                         File            newFile, 
173                         CSegArray       newSegs, 
174                         STRING          newFileName,
175                         File            *mergedFileOutPtr,
176                         File            *deltaFileOutPtr
177 )
178 {
179     int         return_value = 0;
180     int         numSegsChanged = 0;
181     int         c = 0;
182     long        oldFileOffset = 0;
183     long        nextModOffset = 0;
184     long        nextDeltaOffset = 0;
185     File        mergedFile = NULL;
186     File        deltaFile = NULL;
187     CUserSeg    oldUserSeg = NULL;
188     CUserSeg    newUserSeg = NULL;
189
190     *mergedFileOutPtr = NULL;
191     *deltaFileOutPtr = NULL;
192
193     numSegsChanged = match_all_segments(oldSegs, newSegs);
194     if (numSegsChanged < 1)
195     {
196         return 0;
197     }
198
199     mergedFile = tmpfile();
200     if (deltaFileOutPtr != NULL)
201     {
202         deltaFile = tmpfile();
203     }
204     rewind(oldFile);
205     oldFileOffset = 0;
206
207     oldUserSeg = oldSegs->firstUserSeg;
208     while ((oldUserSeg != NULL) && (oldUserSeg->clientData == NULL))
209     {
210         oldUserSeg = oldUserSeg->next;
211     }
212     assert(oldUserSeg != NULL);         /* at least one change exists */
213     nextModOffset = oldUserSeg->offset;
214     while ((c = fgetc(oldFile)) != EOF)
215     {
216         ++oldFileOffset;
217         if (oldFileOffset == (nextModOffset+1))
218         {
219             newUserSeg = ((CUserSeg)(oldUserSeg->clientData));
220             if (   (deltaFile != NULL) 
221                 && (!util_streq(oldUserSeg->text, newUserSeg->text)) )
222             {
223                 fprintf(deltaFile, 
224                         "\n========================================\n");
225                 fprintf(deltaFile,
226                         "----- FROM (old file, line %ld) -----\n"
227                         "%s",
228                     oldUserSeg->line, oldUserSeg->text);
229                 fprintf(deltaFile,
230                         "----- TO (new file, line %ld) -----\n"
231                         "%s",
232                     newUserSeg->line, newUserSeg->text);
233                 fprintf(deltaFile,
234                         "-----\n");
235             }
236
237             fputs(newUserSeg->text, mergedFile);
238             oldFileOffset = oldUserSeg->offset + oldUserSeg->length;
239             fseek(oldFile, oldFileOffset, SEEK_SET);
240
241             oldUserSeg = oldUserSeg->next;
242             while ((oldUserSeg != NULL) && (oldUserSeg->clientData == NULL))
243             {
244                 oldUserSeg = oldUserSeg->next;
245             }
246             nextModOffset = (oldUserSeg == NULL? -1:oldUserSeg->offset);
247         }
248         else
249         {
250             fputc(c, mergedFile);
251         }
252     }
253
254     (*mergedFileOutPtr) = mergedFile;
255     (*deltaFileOutPtr) = deltaFile;
256     return return_value;
257 }
258
259
260 /*
261  * Sets clientData to point to corresponding segments and user segments, IFF 
262  * the segments have changed. 
263  *
264  * Returns the # of user segments that have actually changed.
265  */
266 static int
267 match_all_segments(CSegArray oldSegs, CSegArray newSegs)
268 {
269     CSeg        oldSeg = NULL;
270     CSeg        newSeg = NULL;
271     BOOL        segChanged = FALSE;
272     int         userSegChangeCount = 0;
273     int         userSegCount = 0;
274     int         i = 0;
275
276     for (i = 0; i < oldSegs->numSegs; ++i)
277     {
278         oldSeg = &(oldSegs->segs[i]);
279         newSeg = match_segment(oldSeg, oldSegs, newSegs);
280
281         oldSeg->clientData = NULL;
282         segChanged = FALSE;
283         if (newSeg != NULL)
284         {
285             for (userSegCount = 0; 
286                     (userSegCount < oldSeg->userSegs.numSegs)
287                  && (userSegCount < newSeg->userSegs.numSegs);
288                 ++userSegCount)
289             {
290                 if (!util_streq(oldSeg->userSegs.segs[userSegCount].text,
291                                 newSeg->userSegs.segs[userSegCount].text))
292                 {
293                     segChanged = TRUE;
294                     ++userSegChangeCount;
295
296                     oldSeg->userSegs.segs[userSegCount].clientData =
297                         &(newSeg->userSegs.segs[userSegCount]);
298                 }
299
300 #ifdef BOGUS /* (debugging stuff) */
301                     printf("[%s] %ld -> %ld\n",
302                         oldSeg->userSegs.segs[userSegCount].clientData == NULL?
303                                 " ":"X",
304                         oldSeg->userSegs.segs[userSegCount].line,
305                         newSeg->userSegs.segs[userSegCount].line);
306 #endif /* BOGUS */
307             }
308         }
309         if (segChanged)
310         {
311             oldSeg->clientData = (void *)newSeg;
312         }
313     } /* for i */
314
315     return userSegChangeCount;
316 }
317
318
319 static CSeg
320 match_segment(
321                         CSeg            oldSeg, 
322                         CSegArray       oldSegArray,
323                         CSegArray       newSegArray
324 )
325 {
326     CSeg        newSeg = NULL;
327     int         oldSegIndex = -1;
328     int         oldSegNum = -1;
329     int         newSegIndex = -1;
330     int         newSegNum = 0;
331     int         i = 0;
332
333     oldSegIndex = -1;
334     if (oldSeg->type == CSEG_GLOBAL)
335     {
336         /*
337          * Global segments are unnamed - find number of segment
338          */
339         oldSegNum = -1;
340         for (i = 0; i < oldSegArray->numSegs; ++i)
341         {
342             if (oldSegArray->segs[i].type == CSEG_GLOBAL)
343             {
344                 ++oldSegNum;
345             }
346             if (&(oldSegArray->segs[i]) == oldSeg)
347             {
348                 break;
349             }
350         }
351         oldSegIndex = i;
352
353         /* these asserts check to see if seg is in array at all */
354         assert(oldSegNum >= 0);
355         assert((oldSegIndex >= 0) && (oldSegIndex < oldSegArray->numSegs));
356
357
358         /*
359          * Find matching segment in new array
360          */
361         newSegNum = -1;
362         for (i = 0; i < newSegArray->numSegs; ++i)
363         {
364             if (newSegArray->segs[i].type == CSEG_GLOBAL)
365             {
366                 ++newSegNum;
367             }
368             if (oldSegNum == newSegNum)
369             {
370                 break;
371             }
372         }
373         if (newSegNum != oldSegNum)
374         {
375             goto epilogue;
376         }
377         newSegIndex = i;
378
379         newSeg = &(newSegArray->segs[newSegIndex]);
380     }
381     else
382     {
383         /* Not global - find segment by name */
384         for (i = 0; i < newSegArray->numSegs; ++i)
385         {
386             if (util_streq(oldSeg->name, newSegArray->segs[i].name))
387             {
388                 newSeg = &(newSegArray->segs[i]);
389                 break;
390             }
391         }
392     }
393
394 epilogue:
395     return newSeg;
396 }
397
398
399 #ifdef MAIN
400 int
401 main (int argc, char *argv[])
402 {
403     int         rc = 0;                 /* return code */
404     STRING      newFileName = NULL;
405     File        newFile = NULL;
406     STRING      oldFileName = NULL;
407     File        oldFile = NULL;
408     File        mergedFile = NULL;
409     File        deltaFile = NULL;
410     int         c = 0;
411
412     util_init(&argc, &argv);
413     if (argc != 3)
414     {
415         fprintf(stderr, "Usage: %s <old-file> <new-file>\n", argv[0]);
416         exit(1);
417     }
418     oldFileName = argv[1];
419     newFileName = argv[2];
420
421     /*
422      * Open the files
423      */
424     oldFile = util_fopen_locked(oldFileName, "r");
425     if (oldFile == NULL)
426     {
427         perror(oldFileName);
428         exit(1);
429     }
430     newFile = util_fopen_locked(newFileName, "r");
431     if (newFile == NULL)
432     {
433         perror(newFileName);
434         exit(1);
435     }
436
437     /*
438      * Merge 'em!
439      */
440     rc = abmfP_merge_c_files(
441                         oldFile, oldFileName,
442                         newFile, newFileName,
443                         &mergedFile,
444                         &deltaFile);
445
446     if ((rc >= 0) && (mergedFile == NULL))
447     {
448         printf("No changes found.\n");
449     }
450
451     if (deltaFile != NULL)
452     {
453         char    name[1024];
454         File    f = NULL;
455         sprintf(name, "%s.delta", oldFileName);
456         printf("writing %s\n", name);
457         unlink(name);
458         f = util_fopen_locked(name, "w");
459         if (f == NULL)
460         {
461             perror(name);
462             exit(1);
463         }
464         rewind(deltaFile);
465         while ((c = fgetc(deltaFile)) != EOF)
466         {
467             fputc(c, f);
468         }
469         util_fclose(deltaFile);
470         util_fclose(f);
471     }
472
473     if (mergedFile != NULL)
474     {
475         char    name[1024];
476         File    f = NULL;
477         sprintf(name, "%s.merge", oldFileName);
478         printf("writing %s\n", name);
479         unlink(name);
480         f = util_fopen_locked(name, "w");
481         if (f == NULL)
482         {
483             perror(name);
484             exit(1);
485         }
486         rewind(mergedFile);
487         while ((c = fgetc(mergedFile)) != EOF)
488         {
489             fputc(c, f);
490         }
491         util_fclose(mergedFile);
492         util_fclose(f);
493     }
494
495     util_fclose(oldFile);
496     util_fclose(newFile);
497     exit(0);
498     return 0;
499 }
500 #endif /* MAIN */
501