summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am13
-rw-r--r--src/file.c197
-rw-r--r--src/file.h85
-rw-r--r--src/rep.195
-rw-r--r--src/rep.c703
-rw-r--r--src/rep.dsp114
-rw-r--r--src/repc.173
-rw-r--r--src/repc.c192
-rw-r--r--src/repc.dsp110
9 files changed, 1582 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..59b1a23
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,13 @@
+bin_PROGRAMS = rep repc
+
+rep_SOURCES = rep.c file.c file.h ../common/compat.c ../common/xstring.c ../common/repfile.c
+rep_LDADD = -lrlib -lpcre
+rep_CFLAGS = -O0 -I${top_srcdir} -I/usr/local/include
+rep_LDFLAGS = -L${top_srcdir}/lib/.libs -L${top_srcdir}/lib -L/usr/local/lib
+
+repc_SOURCES = repc.c ../common/compat.c ../common/xstring.c ../common/binfile.c ../common/repfile.c
+repc_LDADD = -lrlib -lpcre
+repc_CFLAGS = -O0 -I${top_srcdir} -I/usr/local/include
+repc_LDFLAGS = -L${top_srcdir}/lib/.libs -L${top_srcdir}/lib -L/usr/local/lib
+
+EXTRA_DIST = rep.dsp repc.dsp
diff --git a/src/file.c b/src/file.c
new file mode 100644
index 0000000..4f42a5d
--- /dev/null
+++ b/src/file.c
@@ -0,0 +1,197 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "common/compat.h"
+#include "file.h"
+
+
+#if HAVE_UNISTD_H && HAVE_DIRENT_H
+
+int dir_next(DIR* handle, const char* wildcard, struct dirent* entry)
+{
+ struct dirent* ent = 0;
+
+#ifndef HAVE_FNMATCH
+ if(wildcard != NULL)
+ {
+ errno = EOPNOTSUPPORTED;
+ return 0;
+ }
+#endif
+
+ if(!wildcard)
+ wildcard = "*";
+
+ do
+ {
+ ent = readdir(handle);
+ if(ent == NULL)
+ {
+ errno = ENOENT;
+ break;
+ }
+ }
+#ifdef HAVE_FNMATCH
+ while(0);
+#else
+ while(fnmatch(wildcard, ent->d_name, FNM_PATHNAME) == FNM_NOMATCH);
+#endif
+
+ if(ent)
+ memcpy(entry, ent, sizeof(struct dirent));
+
+ return ent != NULL;
+}
+
+DIR* dir_first(const char* folder, const char* wildcard, struct dirent* entry)
+{
+ DIR* handle = opendir((folder && strlen(folder) > 0) ? folder : ".");
+ if(handle == NULL)
+ return INVALID_DIR;
+
+ if(dir_next(handle, wildcard, entry))
+ return handle;
+ else
+ {
+ errno = ENOENT;
+ dir_close(handle);
+ return INVALID_DIR;
+ }
+}
+
+void dir_close(DIR* handle)
+{
+ closedir(handle);
+}
+
+
+#else
+
+#include <direct.h>
+#include <io.h>
+
+static void copyDirStruct(struct _finddata_t* findinfo, struct dirent* entry)
+{
+ /* Copy the structure */
+ memset(entry, 0, sizeof(struct dirent));
+ entry->d_fileno = ~0;
+ entry->d_reclen = ~0;
+ strcpy(entry->d_name, findinfo->name);
+ entry->d_namlen = strlen(findinfo->name);
+
+ if(findinfo->attrib & _A_SUBDIR)
+ entry->d_type |= DT_DIR;
+ else
+ entry->d_type |= DT_REG;
+}
+
+DIR* dir_first(const char* folder, const char* wildcard, struct dirent* entry)
+{
+ DIR* handle;
+ char buff[MAX_PATH * 2];
+ struct _finddata_t findinfo;
+
+ if(!wildcard)
+ wildcard = "*.*";
+
+ /* Check against buffer overflow hacks */
+ if(strlen(folder) + strlen(wildcard) + 1 > MAX_PATH * 2)
+ {
+ errno = ENAMETOOLONG;
+ return INVALID_DIR;
+ }
+
+ if(!(handle = malloc(sizeof(DIR))))
+ {
+ errno = ENOMEM;
+ return INVALID_DIR;
+ }
+
+ strcpy(buff, folder);
+ strcat(buff, strlen(folder) ? "\\" : "");
+ strcat(buff, wildcard);
+
+ /* Okay get the first file */
+ *handle = _findfirst(buff, &findinfo);
+
+ if(*handle == -1)
+ {
+ free(handle);
+ return INVALID_DIR;
+ }
+ else
+ {
+ copyDirStruct(&findinfo, entry);
+ return handle;
+ }
+}
+
+int dir_next(DIR* handle, const char* wildcard, struct dirent* entry)
+{
+ struct _finddata_t findinfo;
+ int ret = _findnext(*handle, &findinfo) == 0;
+ if(ret)
+ copyDirStruct(&findinfo, entry);
+
+ return ret;
+}
+
+void dir_close(DIR* handle)
+{
+ if(handle)
+ {
+ _findclose(*handle);
+ free(handle);
+ }
+}
+
+#endif
+
+const char* getFilename(const char* path)
+{
+ const char* filename = strrchr(path, '\\');
+ const char* filename2 = strrchr(path, '/');
+ if(filename2 > filename)
+ filename = filename2;
+ return filename ? filename : path;
+}
+
+const char* getExtension(const char* path)
+{
+ return strrchr(path, '.');
+}
+
+int isDots(const char* path)
+{
+ const char* filename = getFilename(path);
+ return (filename[0] == '.' && (filename[1] == '.' || filename[1] == '\0'));
+}
+
+int isDirectory(const char* path)
+{
+ struct stat st;
+ if(stat(path, &st) == -1)
+ return 0;
+
+ return (st.st_mode & S_IFDIR) ? 1 : 0;
+}
diff --git a/src/file.h b/src/file.h
new file mode 100644
index 0000000..1b46dd2
--- /dev/null
+++ b/src/file.h
@@ -0,0 +1,85 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+/* -------------------------------------------------------------------------
+ * Directory iterating routines and other handy stuff
+ */
+
+#ifndef __FILE_H__
+#define __FILE_H__
+
+#ifndef MAX_PATH
+#if defined(MAXNAMLEN)
+#define MAX_PATH MAXNAMLEN
+#elif defined(_MAX_FNAME)
+#define MAX_PATH _MAX_FNAME
+#else
+#define MAX_PATH 256
+#endif
+#endif
+
+#if HAVE_UNISTD_H && HAVE_DIRENT_H
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+
+#else
+
+
+struct dirent {
+ long d_fileno; /* file number of entry */
+ short d_reclen; /* length of this record */
+ unsigned char d_type; /* file type, see below */
+ unsigned char d_namlen; /* length of string in d_name */
+#ifdef _POSIX_SOURCE
+ char d_name[255 + 1]; /* name must be no longer than this */
+#else
+#define MAXNAMLEN 255
+ char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
+#endif
+};
+
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+typedef int DIR;
+
+#endif
+
+DIR* dir_first(const char* folder, const char* wildcard, struct dirent* entry);
+int dir_next(DIR* handle, const char* wildcard, struct dirent* entry);
+void dir_close(DIR* handle);
+
+#define INVALID_DIR ((DIR*)-1)
+
+const char* getFilename(const char* szPath);
+const char* getExtension(const char* szPath);
+int isDots(const char* szPath);
+int isDirectory(const char* szPath);
+
+#endif \ No newline at end of file
diff --git a/src/rep.1 b/src/rep.1
new file mode 100644
index 0000000..406dcc8
--- /dev/null
+++ b/src/rep.1
@@ -0,0 +1,95 @@
+.Dd September, 2002
+.Dt REP 1
+.Os Rep 2.3
+.Sh NAME
+.Nm rep
+.Nd a regular expression search and replace language
+.Sh SYNOPSIS
+.Nm
+.Op Fl ipq
+.Op Fl z Ar buffsize
+.Ar script
+.Op Ar infile
+.Op Ar outfile
+.Nm
+.Fl f
+.Op Fl bipq
+.Op Fl z Ar buffsize
+.Ar script
+.Ar file
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+scripting language is a regular expression language used for fine grained,
+buffer based search and replace. It is not limited to lines. A full description
+of what
+.Nm
+is capable of is outside the scope of this document.
+.Pp
+.Ar script
+is a text or compiled
+.Nm
+script. For details see the language documentation that came along with the distribution.
+.Pp
+When used with the
+.Fl f
+argument
+.Nm
+replaces files in place. Otherwise it reads from
+.Ar infile
+and writes to
+.Ar outfile
+\&. If either infile or outfile are missing or are equal to a dash
+.Sq Li -
+, then rep processes
+.Em stdin
+or
+.Em stdout
+respectively.
+.Sh OPTIONS
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl b
+Backup files where replacements have occurred. The backup files have an
+.Sq x_r
+extension appended to their filename.
+.It Fl i
+Prompt for confirmation before each replacement.
+.It Fl p
+Only output replaced text. Can be used as a rudimentary parser.
+.It Fl q
+Supress status messages. Only errors will be sent to stderr.
+.It Fl z
+Set the replacement buffer size to
+.Ar buffsize .
+This speeds up execution as regular expressions only have to act on a small
+portion of the whole file at once. However the largest match will be limited to
+roughly
+.Ar buffsize
+, so use this option with care. The script loops over each buffer until no more
+matches are found within it. Care is taken to overlap the buffers as much as
+possible to ensure that any match smaller than
+.Ar buffsize
+can be matched.
+.Sh NOTE
+The
+.Nm
+command uses
+.Xr getopt 3
+to parse it's arguments, which allows it to accept
+the
+.Sq Li --
+option which will stop processing of flag options at that point. This allows
+the processing of files with names that begin with a dash
+.Pq Sq - .
+.Sh BUGS
+When reading from
+.Em stdin
+you must specify a buffer size.
+.Sh SEE ALSO
+.Xr repc 1 ,
+.Xr rlib 3 ,
+.Xr pcre 3
+.Sh AUTHOR
+.An Nate Nielsen Aq nielsen@memberwebs.com \ No newline at end of file
diff --git a/src/rep.c b/src/rep.c
new file mode 100644
index 0000000..b333ef5
--- /dev/null
+++ b/src/rep.c
@@ -0,0 +1,703 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <errno.h>
+#include "common/usuals.h"
+#include "common/compat.h"
+#include "lib/rlib.h"
+#include "lib/rep.h"
+#include "common/repfile.h"
+#include "file.h"
+
+/* Amount of context that will be shown in a prompt surrounding the text */
+#define CONFIRM_CONTEXT 0x20
+
+/* Extension used for backup files */
+const char* kBackupExt = ".x_r";
+
+
+
+/* ------------------------------------------------------------------------
+ * GLOBALS
+ */
+
+/*
+ * Since WIN32 has a hokey (did I say hokey, I meant crappy) shell
+ * we add a bit more file selection functionality if building there.
+ * We allow a set wildcards to be specified. These apply when recursing
+ * folders.
+ */
+#ifdef _WIN32
+ #define MAX_WILDCARDS 0x20
+ const char* kAllFiles = "*.*";
+
+ /* When recursing through folders this is the set of files to replace */
+ char* g_wildcards[MAX_WILDCARDS];
+#endif
+
+/* Quiet mode or not? */
+bool g_showStatus = true;
+
+/* Backups or not? */
+bool g_keepBackups = false;
+
+/*
+ * For status updates the amount of replacements and the amount of
+ * files seen
+ */
+long g_totalReplaces = 0;
+long g_totalFiles = 0;
+
+
+/* ------------------------------------------------------------------------
+ * FORWARD DECLARATIONS
+ */
+
+/* The two match callbacks */
+int matchConfirm(r_stream* stream, r_replace* repl);
+int matchStatus(r_stream* stream, r_replace* repl);
+
+/* The main replace functions */
+int replaceFolder(r_context* ctx, char* szWildCard);
+int replaceFile(r_context* ctx, FILE* fIn, FILE* fOut);
+int replaceFilename(r_context* ctx, const char* szIn, const char* szOut);
+int replaceSingleFile(r_context* ctx, const char* szIn);
+
+/* Error stuff */
+int usage();
+
+
+
+/* ------------------------------------------------------------------------ */
+
+int main(int argc, char* argv[])
+{
+ /* We use one r_stream throughout for speed */
+ r_context context;
+ bool fileMode = false;
+ int ch = 0;
+
+
+ /*
+ * Function return values throughout program are a bit different
+ *
+ * 0 = normal operation
+ * -1 = nothing happened but successful
+ * >0 = error code
+ */
+ int ret = 0;
+ int r = R_OK;
+
+
+ /* Enough params? */
+ if(argc < 2)
+ return usage();
+
+
+ /* Init the stream/context */
+ memset(&context, 0, sizeof(context));
+
+
+ /* A little preparation */
+ context.stream.fMatch = matchStatus;
+
+
+#ifdef _WIN32
+ *g_wildcards = NULL;
+
+ while((ch = getopt(argc, argv, "bcipqw:z:")) != -1)
+#else
+ while((ch = getopt(argc, argv, "bcipqz:")) != -1)
+#endif
+ {
+ switch(ch)
+ {
+ /* Use backups */
+ case 'b':
+ g_keepBackups = true;
+ break;
+
+ case 'i':
+ fileMode = true;
+ break;
+
+ /* Confirmation mode */
+ case 'c':
+ context.stream.fMatch = matchConfirm;
+ break;
+
+ /* Quiet mode */
+ case 'q':
+ g_showStatus = false;
+ break;
+
+ /* Parse mode */
+ case 'p':
+ context.options |= RLIB_MODE_PARSER;
+ break;
+
+#ifdef _WIN32
+ case 'w':
+ {
+ /* Get all the wildcards out */
+ size_t len = 0;
+ char* arg = optarg;
+ char** wildcards = g_wildcards;
+
+ /*
+ * Enumerate the wild cards seperating them
+ * at semi-colons or colons
+ */
+ while((len = strcspn(arg, ";"))
+ && (wildcards < (g_wildcards + MAX_WILDCARDS)))
+ {
+ bool last = (arg[len] == '\0');
+
+ arg[len] = '\0';
+ *wildcards = arg;
+
+ wildcards++;
+ arg += len;
+ arg++;
+
+ if(last) break;
+ }
+
+ /* Null terminate the array */
+ *wildcards = NULL;
+ }
+ break;
+#endif
+
+ case 'z':
+ context.block = atoi(optarg);
+ if(context.block <= 0x20)
+ errx(2, "invalid argument. specify block size greater than 32.");
+ break;
+
+ case '?':
+ default:
+ return usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+
+#ifdef _WIN32
+ if(*g_wildcards == NULL)
+ {
+ g_wildcards[0] = "*.*";
+ g_wildcards[1] = NULL;
+ }
+#endif
+
+
+ /*
+ * The next param should be the script file
+ * so read it...
+ */
+ if(argc > 0)
+ {
+ FILE* file = fopen(argv[0], "rb");
+ if(!file)
+ err(1, "couldn't open rep script file: %s", argv[0]);
+
+ r = repLoad(&context, file);
+ fclose(file);
+
+ if(r < 0)
+ exit(errmsg(r, &(context.script)));
+ }
+ else
+ return usage();
+
+ /*
+ * Now initialize the rlib library structures
+ */
+ r = repInit(&context);
+ if(r < 0)
+ exit(errmsg(r, NULL));
+
+ argc--;
+ argv++;
+
+
+ /*
+ * Okay now we have two options:
+ *
+ * If -f was specified we read each argument and replace the file in place,
+ * possibly with backups, descend into folders etc...
+ *
+ * Or if not specified we read from the in file and output to the outfile
+ * If out or both in and out are not specified then use stdin/stdout
+ */
+ if(!fileMode)
+ {
+ char* in = "-";
+ char* out = "-";
+ int ret;
+
+ if(argc > 2)
+ usage();
+ if(argc > 0)
+ in = argv[0];
+ if(argc > 1)
+ out = argv[1];
+
+ ret = rlibSetVar(&(context.stream), "FILENAME", in);
+ if(ret < 0)
+ ret = errmsg(ret, &(context.script));
+ else
+ ret = replaceFilename(&context, in, out);
+ }
+ else
+ {
+ while(argc > 0)
+ {
+ if(isDirectory(argv[0]))
+ ret = replaceFolder(&context, argv[0]);
+ else
+ ret = replaceSingleFile(&context, argv[0]);
+
+ if(ret > 0)
+ break;
+
+ argc--;
+ argv++;
+ }
+ }
+
+ /* Release the stream */
+ repFree(&context);
+
+ /* Give some stats */
+ if(ret == 0 && g_showStatus)
+ fprintf(stderr, "\n[%d replacements in %d files]\n", g_totalReplaces, g_totalFiles);
+
+ /* Done! */
+ return ret <= 0 ? 0 : ret;
+}
+
+
+
+/* replaceFolder: --------------------------------------------------------------
+ * Enumerate all files in a folder and do a replace on each one using
+ * backups (Note: this function is called recursively)
+ */
+int replaceFolder(r_context* ctx, char* folder)
+{
+ struct dirent ent;
+ char old[260]; /* Save the current folder (as we'll change it) */
+ int ret = 0;
+ DIR* dir;
+
+ /*
+ * We use a null wildcard as the default and replace below
+ * if running under WIN32
+ */
+ char* wildcard = NULL;
+ char** wildcards = &wildcard;
+
+
+ /* Backup the current directory */
+ if(!getcwd(old, 260))
+ err(1, "couldn't get working folder");
+
+
+#ifdef _WIN32
+ /*
+ * Now loop through all the wildcards and search for them
+ * in the folder
+ */
+ wildcards = g_wildcards;
+ while(*wildcards)
+ {
+#endif
+ dir = dir_first(folder, *wildcards, &ent);
+
+ if(dir == INVALID_DIR && errno != ENOENT)
+ err(1, "couldn't list path: %s", folder);
+
+ /* Any files */
+ if(dir != INVALID_DIR)
+ {
+ /* Change dir to the folder we're searching in */
+ chdir(folder);
+
+ /* And for every file */
+ do
+ {
+ if(ent.d_type & DT_DIR)
+ {
+ int r = 0;
+
+ if(g_showStatus)
+ fprintf(stderr, "%s ", ent.d_name);
+
+ r = replaceSingleFile(ctx, ent.d_name);
+
+ if(g_showStatus)
+ fputc('\n', stderr);
+
+ if(r > 0)
+ return r;
+ if(r > ret)
+ ret = r;
+ }
+
+ }
+ while(dir_next(dir, *wildcards, &ent));
+
+ if(errno != 0 && errno != ENOENT)
+ err(1, "couldn't list path: %s", folder);
+
+ dir_close(dir);
+
+ /*
+ * Change directory back to where we saved it
+ * the reason we do this is that in some cases (sub-folders)
+ */
+ _chdir(old);
+ }
+
+#ifdef _WIN32
+ wildcards++;
+ }
+#endif
+
+ /* Now we enumerate all the folders */
+ dir = dir_first(folder, NULL, &ent);
+
+ if(dir == INVALID_DIR && errno != ENOENT)
+ err(1, "couldn't list path: %s", folder);
+
+ /* Any files? */
+ if(dir != INVALID_DIR)
+ {
+ /* Go into folder */
+ chdir(folder);
+
+ do
+ {
+ /* For each folder... */
+ if(ent.d_type & DT_DIR)
+ {
+ int r = 0;
+
+ /* ... that's not dots ... */
+ if(isDots(ent.d_name))
+ continue;
+
+ /* ... recursively call ourselves */
+ ret = replaceFolder(ctx, ent.d_name);
+
+ if(r > 0)
+ return r;
+ if(r > ret)
+ ret = r;
+ }
+ }
+ while(dir_next(dir, NULL, &ent));
+
+ if(errno != 0 && errno != ENOENT)
+ err(1, "couldn't list path: %s", folder);
+
+ dir_close(dir);
+
+ /* Change directory back */
+ chdir(old);
+ }
+
+ /* Did anything change? */
+ return ret;
+}
+
+
+/* replaceSingleFile: -------------------------------------------------------
+ * Replace a file into itself using temp/backups
+ */
+int replaceSingleFile(r_context* ctx, const char* file)
+{
+ int ret = 2;
+ char temp [260 + 4]; /* Temp buffer for filenames */
+
+ ret = rlibSetVar(&(ctx->stream), "FILENAME", file);
+ if(ret < 0)
+ return errmsg(ret, &(ctx->script));
+
+ /* Make a temp/backup name */
+ strcpy(temp, file);
+ strcat(temp, kBackupExt);
+
+ /* Now we do this 2 ways, if we're keeping backups then... */
+ if(g_keepBackups)
+ {
+ /* Rename the original file to the backup */
+ if(rename(file, temp))
+ err(1, "couldn't make backup file: %s", temp);
+
+ /*
+ * Do a replacement operation back to the original
+ * from the backup
+ */
+ ret = replaceFilename(ctx, temp, file);
+
+ /* If there were no replacements */
+ if(ret == -1)
+ {
+ /* Remove the replacement file */
+ unlink(file);
+
+ /* And rename the backup file back */
+ if(rename(temp, file))
+ err(1, "couldn't rename file: %s", file);
+ }
+ }
+
+ /* No backups, much faster! */
+ else
+ {
+ /* Do a replacement operation to a temp file */
+ ret = replaceFilename(ctx, file, temp);
+
+ /* If there were replacements */
+ if(ret == 0)
+ {
+ /* Remove original file */
+ unlink(file);
+
+ /* Rename temp to original */
+ if(rename(temp, file))
+ err(1, "couldn't rename file: %s", file);
+ }
+
+ /* If no replacements */
+ else
+ {
+ /* Remove temp file */
+ unlink(temp);
+ }
+ }
+
+ return ret;
+}
+
+
+/* replaceFilename: -----------------------------------------------------------
+ * Replace one file into another
+ */
+int replaceFilename(r_context* ctx, const char* in, const char* out)
+{
+ FILE* fIn;
+ FILE* fOut;
+ int ret;
+
+ if(!strcmp(in, "-"))
+ {
+ /*
+ * If someone specified stdin as the input make sure we're
+ * not going to put up confirmations as we need input from
+ * stdin ie: YNA or whatever key
+ */
+ if(ctx->stream.fMatch == matchConfirm)
+ errx(2, "can't confirm replacements while using stdin as input");
+
+ /* Input is stdin */
+ fIn = stdin;
+ }
+
+ /* Input is a file */
+ else
+ {
+#ifdef _WIN32
+ if(!(fIn = fopen(in, "rb")))
+#else
+ if(!(fIn = fopen(in, "r")))
+#endif
+ err(1, "couldn't open input file: %s", in);
+ }
+
+ /* Output is stdout */
+ if(!strcmp(out, "-"))
+ fOut = stdout;
+
+ /* Output is a file */
+#ifdef _WIN32
+ else if(!(fOut = fopen(out, "wb")))
+#else
+ else if(!(fOut = fopen(out, "w")))
+#endif
+ err(1, "couldn't open output file: %s", in);
+
+
+ /* Do replacements! */
+ ret = replaceFile(ctx, fIn, fOut);
+
+ /* Close any files */
+ if(fIn != stdin)
+ fclose(fIn);
+ if(fOut != stdout)
+ fclose(fOut);
+
+ return ret;
+}
+
+
+
+/* matchConfirm: -----------------------------------------------------------------
+ * Confirmation callback for rlib. Used when -i flag is given
+ */
+int matchConfirm(r_stream* stream, r_replace* repl)
+{
+ /* Remember if someone pressed A */
+ static bool all = false;
+ char ch = 0;
+ int ret;
+ size_t context_start, context_end;
+
+ if(all)
+ return 1;
+
+ fprintf(stderr, "\n------------- ORIGINAL TEXT between ~{ and }~ markers ---------------\n");
+
+ /* Figure out if we have some context before replacement */
+ /* and how much */
+ context_start = 0;
+ if(repl->from >= CONFIRM_CONTEXT)
+ context_start = repl->from - CONFIRM_CONTEXT;
+
+
+ /* Figure out if we have context after replacement */
+ context_end = stream->availIn;
+
+ if(stream->availIn >= repl->from + repl->flen + CONFIRM_CONTEXT)
+ context_end = repl->from + repl->flen + CONFIRM_CONTEXT;
+
+ /* Write Context Before */
+ fwrite(stream->nextIn + context_start, sizeof(char),
+ repl->from - context_start, stderr);
+ /* Write our tag */
+ fprintf(stderr, "~{");
+ /* Write from text */
+ fwrite(stream->nextIn + repl->from, sizeof(char), repl->flen, stderr);
+
+ /* Write tag */
+ fprintf(stderr, "}~");
+ /* Write Context After */
+ fwrite(stream->nextIn + repl->from + repl->flen, sizeof(char),
+ context_end - (repl->from + repl->flen), stderr);
+ /* Separator */
+ fprintf(stderr, "\n----------------------------- NEW TEXT -------------------------------\n");
+ // Replace with this text
+ fwrite(repl->to, sizeof(byte), repl->tlen, stderr);
+ /* Prompt */
+ fprintf(stderr, "\n----------------------------------------------------------------------\n");
+
+ fprintf(stderr, "(YES\\No\\All)? ");
+
+ setbuf(stdin, NULL);
+ while(ch != 'y' && ch != 'n' && ch != 'a' && ch != '\r')
+ ch = tolower(getchar());
+
+ if(ch == 'a')
+ stream->fMatch = matchStatus;
+
+ fprintf(stderr, "\r \r");
+
+ ret = (ch == 'y' || ch == 'a' || ch == '\r') ? true : false;
+
+ if(ret)
+ g_totalReplaces++;
+
+ return ret;
+}
+
+
+/* matchStatus: ----------------------------------------------------------
+ * Confirmation function for rlib. Used for status display
+ */
+int matchStatus(r_stream* stream, r_replace* repl)
+{
+ if(g_showStatus)
+ fputc('.', stderr);
+
+ g_totalReplaces++;
+
+ return 1;
+}
+
+
+/* outputMsg: --------------------------------------------------------------
+ * Callback for rlib when a message goes to the console.
+ */
+void outputMsg(struct r_stream* stream, const char* data)
+{
+ fprintf(stderr, g_showStatus ? "\n%s " : "%s\n", data);
+}
+
+/* replaceFile: ------------------------------------------------------------
+ * Replace one file into another using file handles. This is where
+ * the main stuff actually happens.
+ */
+int replaceFile(r_context* ctx, FILE* fIn, FILE* fOut)
+{
+ int ret;
+
+ ctx->stream.fMessage = outputMsg;
+ ctx->stream.total = 0;
+
+ ret = repFiles(ctx, fIn, fOut);
+
+ /* fatal errors */
+ if(ret < 0)
+ return errmsg(ret, &(ctx->script));
+
+ ret = (ctx->stream.total > 0) ? 0 : -1;
+
+ g_totalFiles++;
+ rlibClear(&(ctx->stream));
+
+ return ret;
+}
+
+/* usage: -------------------------------------------------------------
+ * Display usage info
+ */
+int usage()
+{
+#ifdef _WIN32
+ fprintf(stderr, "usage: rep [-cpqx] [ -z buffsize ] script infile outfile\n");
+ fprintf(stderr, " rep -i [-bcpqx] [ -z buffsize ] [ -w wildcard ] script file ...\n");
+#else
+ fprintf(stderr, "usage: rep [-cpq] [ -z buffsize ] script infile outfile\n");
+ fprintf(stderr, " rep -i [-bcpq] [ -z buffsize ] script file ...\n");
+#endif
+ return 2;
+}
+
diff --git a/src/rep.dsp b/src/rep.dsp
new file mode 100644
index 0000000..37a8fd0
--- /dev/null
+++ b/src/rep.dsp
@@ -0,0 +1,114 @@
+# Microsoft Developer Studio Project File - Name="rep" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=rep - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rep.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rep.mak" CFG="rep - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rep - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rep - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rep - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libpcre.a kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../win32/release/rep.exe" /libpath:"..\win32\pcre\lib\\"
+
+!ELSEIF "$(CFG)" == "rep - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libpcre.a kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../win32/debug/rep.exe" /pdbtype:sept /libpath:"..\win32\pcre\lib\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "rep - Win32 Release"
+# Name "rep - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\common\compat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rep.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\file.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/src/repc.1 b/src/repc.1
new file mode 100644
index 0000000..49045ae
--- /dev/null
+++ b/src/repc.1
@@ -0,0 +1,73 @@
+.Dd September, 2002
+.Dt REPC 1
+.Os Rep 2.3
+.Sh NAME
+.Nm repc
+.Nd compiler for the
+.Xr rep 1
+scripting language
+.Sh SYNOPSIS
+.Nm
+.Op Fl rp
+.Op Fl z Ar buffsize
+.Ar script
+.Ar outfile
+.Nm
+.Fl d
+.Ar script
+.Sh DESCRIPTION
+The
+.Nm
+command compiles
+.Xr rep 1
+scripts into an byte code format. This speeds up execution as compilation is not
+required at run time. Also useful when using the
+.Xr rlib 3
+library.
+.Pp
+.Ar script
+is compiled into
+.Ar output .
+The
+.Fl z
+and
+.Fl p
+options are stored with the compiled script, and will be used as defaults when the
+script is executed.
+.Sh OPTIONS
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl d
+Dump dissassembled byte code.
+.It Fl p
+Default to parse mode. When the script is executed only replaments
+will be written out, rather than unreplaced text.
+.It Fl r
+Compile into raw byte code format. For use with the
+.Xr rlib 3
+library. Any options are not stored with the code.
+.Xr rep 3
+cannot read this format.
+.It Fl z
+Set the default buffer size to
+.Ar buffsize
+and store it along with the compiled script. See
+.Xr rep 1
+for a description of the buffer size.
+.Sh NOTE
+The
+.Nm
+command uses
+.Xr getopt 3
+to parse it's arguments, which allows it to accept
+the
+.Sq Li --
+option which will stop processing of flag options at that point. This allows
+the processing of files with names that begin with a dash
+.Pq Sq - .
+.Sh SEE ALSO
+.Xr rep 1 ,
+.Xr rlib 3 ,
+.Xr pcre 3
+.Sh AUTHOR
+.An Nate Nielsen Aq nielsen@memberwebs.com \ No newline at end of file
diff --git a/src/repc.c b/src/repc.c
new file mode 100644
index 0000000..8cd5f9b
--- /dev/null
+++ b/src/repc.c
@@ -0,0 +1,192 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include "common/usuals.h"
+#include "common/compat.h"
+#include "lib/rlib.h"
+#include "lib/rep.h"
+#include "common/binfile.h"
+#include "common/repfile.h"
+
+int usage();
+int help();
+
+
+/* --------------------------------------------------------------------------- */
+
+int main(int argc, char* argv[])
+{
+ r_context ctx;
+ int ch = 0;
+ int r = R_OK;
+
+ bool dump = false; /* Do we dump the ops to the display */
+ bool raw = false; /* Output raw script data or rep file */
+
+ memset(&ctx, 0, sizeof(ctx));
+
+ /* Enough params? */
+ if(argc < 2)
+ return usage();
+
+ /* Parse the arguments */
+ while((ch = getopt(argc, argv, "dprz:")) != -1)
+ {
+ switch(ch)
+ {
+ /* Output raw script ops to file instead of rep file*/
+ case 'r':
+ raw = true;
+ break;
+
+ /* Dump rep script ops to stdout */
+ case 'd':
+ dump = true;
+ break;
+
+ /* Set parse mode option in rep file */
+ case 'p':
+ ctx.options |= RLIB_MODE_PARSER;
+ break;
+
+ /* Set the buffer size in rep file */
+ case 'z':
+ ctx.block = atoi(optarg);
+ if(ctx.block <= 0x20)
+ errx(2, "invalid argument. specify block size greater than 32.");
+ break;
+
+ case '?':
+ default:
+ return usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+
+ /* Okay now compile */
+
+ /* Make sure we have a valid amount of file names */
+ if(argc < 1)
+ return usage();
+
+ /*
+ * The next param should be the script file
+ * so read it...
+ */
+ {
+ FILE* file = fopen(argv[0], "rb");
+ if(!file)
+ err(1, "couldn't open rep script file: %s", argv[0]);
+
+ r = repLoad(&ctx, file);
+ fclose(file);
+
+ if(r < 0)
+ exit(errmsg(r, &(ctx.script)));
+ }
+
+ argc--;
+ argv++;
+
+ /* Now if we were asked to dump then output the file */
+ if(dump)
+ {
+ if(argc != 0)
+ return usage();
+
+ rlibDump(&(ctx.script), stdout);
+ }
+
+ /* Otherwise we write it out to a file */
+ else
+ {
+ FILE* file;
+ char* output = argv[0];
+
+ if(argc < 1)
+ return usage();
+
+ /* Opet the output file */
+ if(!(file = fopen(output, "wb")))
+ err(1, "couldn't open output file for compiled script: %s\n", output);
+
+
+ /* Write a full rep file if not in raw mode */
+ if(!raw)
+ {
+ bfval val;
+ BFILE h;
+
+ if(!(h = bfStartFile(file)))
+ errx(1, "couldn't open output file for compiled script: %s\n", output);
+
+ repfWriteHeader(h);
+
+ bfWriteInt(h, REPVAL_PARSEMODE,
+ ctx.options & RLIB_MODE_PARSER ? 1 : 0);
+
+ if(ctx.block != 0)
+ bfWriteInt(h, REPVAL_BUFSIZE, ctx.block);
+
+ val.id = REPVAL_SCRIPT;
+ val.len = ctx.script.len;
+ val.type = BINTYPE_DATA;
+
+ bfWriteValue(h, &val, ctx.script.ops);
+
+ bfWriteEnd(h);
+ bfClose(h);
+ }
+ else
+ {
+ /* Just write out the raw script */
+ fwrite(ctx.script.ops, 1, ctx.script.len, file);
+ }
+
+ if(ferror(file))
+ err(1, "couldn't write to file: %s", output);
+
+ fclose(file);
+ }
+
+ repFree(&ctx);
+
+ return 0;
+}
+
+/* usage: ----------------------------------------------------------------
+ */
+int usage()
+{
+ fprintf(stderr, "usage: repc [-rp] [ -z buffsize ] script output\n");
+ fprintf(stderr, " repc -d script\n");
+ return 2;
+}
diff --git a/src/repc.dsp b/src/repc.dsp
new file mode 100644
index 0000000..47c66d9
--- /dev/null
+++ b/src/repc.dsp
@@ -0,0 +1,110 @@
+# Microsoft Developer Studio Project File - Name="repc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=repc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "repc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "repc.mak" CFG="repc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "repc - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "repc - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "repc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libpcre.a kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../win32/release/repc.exe" /libpath:"..\win32\pcre\lib\\"
+
+!ELSEIF "$(CFG)" == "repc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libpcre.a kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../win32/debug/repc.exe" /pdbtype:sept /libpath:"..\win32\pcre\lib\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "repc - Win32 Release"
+# Name "repc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\common\compat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\repc.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\common\compat.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project