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 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 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