// // Quick hack to work around not having sed, or any other reasonable // way to edit a file from a script on Windows...... // // Copyright (c) 2010, Apple Inc. All rights reserved.<BR> // // This program and the accompanying materials // are licensed and made available under the terms and conditions of the BSD License // which accompanies this distribution. The full text of the license may be found at // http://opensource.org/licenses/bsd-license.php // // THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, // WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // #include <stdio.h> #include <stdlib.h> #include <limits.h> #define TRUE 1 #define FALSE 0 typedef struct { char *Match; int MatchSize; char *Replace; } MATCH_PAIR; void Usage (char *Name) { printf ("\n%s OldFile NewFile MatchString ReplaceString [MatchString2 ReplaceString2]*\n", Name); printf (" OldFile - Must be arg[1] File to search for MatchStrings\n"); printf (" NewFile - Must be arg[2] File where MatchString has been replaced with ReplaceString\n"); printf (" MatchString & ReplaceString. Required arguments.\n"); printf (" More MatchString/ReplaceString pairs are supported.\n"); } // // argv[1] - Old File // argv[2] - New File // argv[3+n] - Match String // argv[4+n] - Replace string int main (int argc, char **argv) { FILE *In, *Out; char *Key, *Replace; int c, i, n, Len, MaxLenKey = 0, MinLenKey = INT_MAX; unsigned long InFileSize, InFilePos; MATCH_PAIR *Match; int MaxMatch; int ReadCount; int Found; if (argc < 5) { fprintf (stderr, "Need at least two files and one Match/Replacement string pair\n"); Usage (argv[0]); return -1; } else if ((argc % 2) == 0) { fprintf (stderr, "Match and Replace string must come in pairs\n"); return -4; } In = fopen (argv[1], "r"); fseek (In, 0, SEEK_END); InFileSize = ftell (In); if (InFileSize == 0) { fprintf (stderr, "Could not open %s\n", argv[1]); return -6; } fseek (In, 0, SEEK_SET); Out = fopen (argv[2], "w+"); if ((In == NULL) || (Out == NULL)) { fprintf (stderr, "Could not open %s\n", argv[2]); return -2; } MaxMatch = (argc - 2)/2; Match = calloc (MaxMatch, sizeof (MATCH_PAIR)); if (Match == NULL) { return -7; } for (n=0; n < MaxMatch; n++) { Match[n].Match = argv[3 + n*2]; Match[n].MatchSize = strlen (argv[3 + n*2]); Match[n].Replace = argv[3 + n*2 + 1]; if (Match[n].MatchSize > MaxLenKey) { // Max size of match/replace string pair MaxLenKey = Match[n].MatchSize; } if (Match[n].MatchSize < MinLenKey) { MinLenKey = Match[n].MatchSize; } } Key = malloc (MaxLenKey); if (Key == NULL) { return -5; } // Search for a match by reading every possition of the file // into a buffer that is as big as the maximum search key size. // Then we can search the keys for a match. If no match // copy the old file character to the new file. If it is a match // then copy the replacement string into the output file. // This code assumes the file system is smart and caches the // file in a buffer. So all the reads don't really hit the disk. InFilePos = 0; while (InFilePos < (InFileSize - MinLenKey)) { fseek (In, InFilePos, SEEK_SET); ReadCount = fread (Key, 1, MaxLenKey, In); for (i = 0, Found = FALSE;i < MaxMatch; i++) { if (ReadCount >= Match[i].MatchSize) { if (!memcmp (Key, Match[i].Match, Match[i].MatchSize)) { InFilePos += (Match[i].MatchSize - 1); fputs (Match[i].Replace, Out); Found = TRUE; break; } } } if (!Found) { fputc (Key[0], Out); } InFilePos++; } // We stoped searching when we got to the point that we could no longer match. // So the last few bytes of the file are not copied in the privous loop fseek (In, InFilePos, SEEK_SET); while ((c = fgetc (In)) != EOF) { fputc (c, Out); } fclose (In); fclose (Out); free (Key); free (Match); return 0; }