diff options
Diffstat (limited to 'contrib/tcl/unix/bp.c')
-rw-r--r-- | contrib/tcl/unix/bp.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/contrib/tcl/unix/bp.c b/contrib/tcl/unix/bp.c new file mode 100644 index 0000000..b8c7a49 --- /dev/null +++ b/contrib/tcl/unix/bp.c @@ -0,0 +1,127 @@ +/* + * bp.c -- + * + * This file contains the "bp" ("binary patch") program. It is used + * to replace configuration strings in Tcl/Tk binaries as part of + * installation. + * + * Usage: bp file search replace + * + * This program searches file bp for the first occurrence of the + * character string given by "search". If it is found, then the + * first characters of that string get replaced by the string + * given by "replace". The replacement string is NULL-terminated. + * + * Copyright (c) 1996 Sun Microsystems, Inc. + * All rights reserved. + * This file is NOT subject to the terms described in "license.terms". + * + * SCCS: @(#) bp.c 1.2 96/03/12 09:08:26 + */ + +#include <stdio.h> +#include <string.h> + +extern int errno; + +/* + * The array below saves the last few bytes read from the file, so that + * they can be compared against a particular string that we're looking + * for. + */ + +#define BUFFER_SIZE 200 +char buffer[BUFFER_SIZE]; + +int +main(argc, argv) + int argc; /* Number of command-line arguments. */ + char **argv; /* Values of command-line arguments. */ +{ + int length, matchChar, fileChar, cur, fileIndex, stringIndex; + char *s; + FILE *f; + + if (argc != 4) { + fprintf(stderr, + "Wrong # args: should be \"%s fileName string replace\"\n", + argv[0]); + exit(1); + } + f = fopen(argv[1], "r+"); + if (f == NULL) { + fprintf(stderr, + "Couldn't open \"%s\" for writing: %s\n", + argv[1], strerror(errno)); + exit(1); + } + + for (cur = 0; cur < BUFFER_SIZE; cur++) { + buffer[cur] = 0; + } + s = argv[2]; + length = strlen(s); + if (length > BUFFER_SIZE) { + fprintf(stderr, + "String \"%s\" too long; must be %d or fewer chars.\n", + s, BUFFER_SIZE); + exit(1); + } + matchChar = s[length-1]; + + while (1) { + fileChar = getc(f); + if (fileChar == EOF) { + if (ferror(f)) { + goto ioError; + } + fprintf(stderr, "Couldn't find string \"%s\"\n", argv[2]); + exit(1); + } + buffer[cur] = fileChar; + if (fileChar == matchChar) { + /* + * Last character of the string matches the current character + * from the file. Search backwards through the buffer to + * see if the preceding characters from the file match the + * characters from the string. + */ + for (fileIndex = cur-1, stringIndex = length-2; + stringIndex >= 0; fileIndex--, stringIndex--) { + if (fileIndex < 0) { + fileIndex = BUFFER_SIZE-1; + } + if (buffer[fileIndex] != s[stringIndex]) { + goto noMatch; + } + } + + /* + * Matched! Backup to the start of the string, then + * overwrite it with the replacement value. + */ + + if (fseek(f, -length, SEEK_CUR) == -1) { + goto ioError; + } + if (fwrite(argv[3], strlen(argv[3])+1, 1, f) == 0) { + goto ioError; + } + exit(0); + } + + /* + * No match; go on to next character of file. + */ + + noMatch: + cur++; + if (cur >= BUFFER_SIZE) { + cur = 0; + } + } + + ioError: + fprintf(stderr, "I/O error: %s\n", strerror(errno)); + exit(1); +} |