• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Quick hack to work around not having sed, or any other reasonable
3 // way to edit a file from a script on Windows......
4 //
5 // Copyright (c) 2010, Apple Inc. All rights reserved.<BR>
6 //
7 //  This program and the accompanying materials
8 //  are licensed and made available under the terms and conditions of the BSD License
9 //  which accompanies this distribution.  The full text of the license may be found at
10 //  http://opensource.org/licenses/bsd-license.php
11 //
12 //  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 //  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 //
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <limits.h>
19 
20 #define TRUE  1
21 #define FALSE 0
22 
23 typedef struct {
24   char  *Match;
25   int   MatchSize;
26   char  *Replace;
27 } MATCH_PAIR;
28 
29 void
Usage(char * Name)30 Usage (char *Name)
31 {
32   printf ("\n%s OldFile NewFile MatchString ReplaceString [MatchString2 ReplaceString2]*\n", Name);
33   printf ("    OldFile - Must be arg[1] File to search for MatchStrings\n");
34   printf ("    NewFile - Must be arg[2] File where MatchString has been replaced with ReplaceString\n");
35   printf ("    MatchString & ReplaceString. Required arguments.\n");
36   printf ("    More MatchString/ReplaceString pairs are supported.\n");
37 }
38 
39 //
40 // argv[1] - Old File
41 // argv[2] - New File
42 // argv[3+n] - Match String
43 // argv[4+n] - Replace string
44 int
main(int argc,char ** argv)45 main (int argc, char **argv)
46 {
47   FILE *In, *Out;
48   char *Key, *Replace;
49   int  c, i, n, Len, MaxLenKey = 0, MinLenKey = INT_MAX;
50   unsigned long  InFileSize, InFilePos;
51   MATCH_PAIR *Match;
52   int MaxMatch;
53   int ReadCount;
54   int Found;
55 
56   if (argc < 5) {
57     fprintf (stderr, "Need at least two files and one Match/Replacement string pair\n");
58     Usage (argv[0]);
59     return -1;
60   } else if ((argc % 2) == 0) {
61     fprintf (stderr, "Match and Replace string must come in pairs\n");
62     return -4;
63   }
64 
65   In  = fopen (argv[1], "r");
66   fseek (In, 0, SEEK_END);
67   InFileSize = ftell (In);
68   if (InFileSize == 0) {
69     fprintf (stderr, "Could not open %s\n", argv[1]);
70     return -6;
71   }
72   fseek (In, 0, SEEK_SET);
73 
74 
75   Out = fopen (argv[2], "w+");
76   if ((In == NULL) || (Out == NULL)) {
77     fprintf (stderr, "Could not open %s\n", argv[2]);
78     return -2;
79   }
80 
81   MaxMatch = (argc - 2)/2;
82   Match = calloc (MaxMatch, sizeof (MATCH_PAIR));
83   if (Match == NULL) {
84     return -7;
85   }
86 
87   for (n=0; n < MaxMatch; n++) {
88     Match[n].Match   = argv[3 + n*2];
89     Match[n].MatchSize = strlen (argv[3 + n*2]);
90     Match[n].Replace = argv[3 + n*2 + 1];
91     if (Match[n].MatchSize > MaxLenKey) {
92       // Max size of match/replace string pair
93       MaxLenKey = Match[n].MatchSize;
94     }
95     if (Match[n].MatchSize < MinLenKey) {
96       MinLenKey = Match[n].MatchSize;
97     }
98   }
99 
100   Key = malloc (MaxLenKey);
101   if (Key == NULL) {
102     return -5;
103   }
104 
105   // Search for a match by reading every possition of the file
106   // into a buffer that is as big as the maximum search key size.
107   // Then we can search the keys for a match. If no match
108   // copy the old file character to the new file. If it is a match
109   // then copy the replacement string into the output file.
110   // This code assumes the file system is smart and caches the
111   // file in a buffer. So all the reads don't really hit the disk.
112   InFilePos = 0;
113   while (InFilePos < (InFileSize - MinLenKey)) {
114     fseek (In, InFilePos, SEEK_SET);
115     ReadCount = fread (Key, 1, MaxLenKey, In);
116     for (i = 0, Found = FALSE;i < MaxMatch; i++) {
117       if (ReadCount >= Match[i].MatchSize) {
118         if (!memcmp (Key, Match[i].Match, Match[i].MatchSize)) {
119           InFilePos += (Match[i].MatchSize - 1);
120           fputs (Match[i].Replace, Out);
121           Found = TRUE;
122           break;
123         }
124       }
125     }
126     if (!Found) {
127       fputc (Key[0], Out);
128     }
129 
130     InFilePos++;
131   }
132 
133   // We stoped searching when we got to the point that we could no longer match.
134   // So the last few bytes of the file are not copied in the privous loop
135   fseek (In, InFilePos, SEEK_SET);
136   while ((c = fgetc (In)) != EOF) {
137     fputc (c, Out);
138   }
139 
140   fclose (In);
141   fclose (Out);
142   free (Key);
143   free (Match);
144   return 0;
145 }
146 
147