2010-02-05 07:50:09 +01:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// All rights reserved. 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;
|
|
|
|
|
2010-02-05 19:43:49 +01:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2010-02-05 07:50:09 +01:00
|
|
|
//
|
|
|
|
// 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) {
|
2010-02-05 19:43:49 +01:00
|
|
|
fprintf (stderr, "Need at least two files and one Match/Replacement string pair\n");
|
|
|
|
Usage (argv[0]);
|
2010-02-05 07:50:09 +01:00
|
|
|
return -1;
|
|
|
|
} else if ((argc % 2) == 0) {
|
2010-02-05 19:43:49 +01:00
|
|
|
fprintf (stderr, "Match and Replace string must come in pairs\n");
|
2010-02-05 07:50:09 +01:00
|
|
|
return -4;
|
|
|
|
}
|
|
|
|
|
|
|
|
In = fopen (argv[1], "r");
|
|
|
|
fseek (In, 0, SEEK_END);
|
|
|
|
InFileSize = ftell (In);
|
|
|
|
if (InFileSize == 0) {
|
2010-02-05 19:43:49 +01:00
|
|
|
fprintf (stderr, "Could not open %s\n", argv[1]);
|
2010-02-05 07:50:09 +01:00
|
|
|
return -6;
|
|
|
|
}
|
|
|
|
fseek (In, 0, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
|
|
Out = fopen (argv[2], "w+");
|
|
|
|
if ((In == NULL) || (Out == NULL)) {
|
2010-02-05 19:43:49 +01:00
|
|
|
fprintf (stderr, "Could not open %s\n", argv[2]);
|
2010-02-05 07:50:09 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-02-05 19:43:49 +01:00
|
|
|
// 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.
|
2010-02-05 07:50:09 +01:00
|
|
|
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++;
|
|
|
|
}
|
|
|
|
|
2010-02-05 19:43:49 +01:00
|
|
|
// 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);
|
|
|
|
}
|
2010-02-05 07:50:09 +01:00
|
|
|
|
|
|
|
fclose (In);
|
|
|
|
fclose (Out);
|
|
|
|
free (Key);
|
2010-02-05 19:43:49 +01:00
|
|
|
free (Match);
|
2010-02-05 07:50:09 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|