diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html
index f6a62d55d..ffc373f24 100644
--- a/Doc/Manual/SWIG.html
+++ b/Doc/Manual/SWIG.html
@@ -163,6 +163,32 @@ can be obtained by typing swig -help or swig
+
+Arguments may also be passed in a command-line options file (also known as a
+response file) which is useful if they exceed the system command line length
+limit. To do this, put the arguments in a file, then provide the file name
+prefixed with @ like so:
+
+
+
+
+
+The options read from the file are inserted in place of the file option. If the
+file does not exist, or cannot be read, then the option will be treated
+literally and not removed.
+
+
+
+Options in the file are separated by whitespace. A whitespace character may be
+included in an option by surrounding the entire option in either single or
+double quotes. Any character (including a backslash) may be included by
+prefixing the character to be included with a backslash. The file may itself
+contain additional @file options; any such options will be processed
+recursively.
+
+
diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx
index 9822b6af7..c7ae02625 100644
--- a/Source/Modules/main.cxx
+++ b/Source/Modules/main.cxx
@@ -159,6 +159,10 @@ is equivalent to: \n\
\n\
$ swig -Wall -python interface.i \n\
\n\
+Arguments may also be passed in a file, separated by whitespace. For example:\n\
+\n\
+ $ echo \"-Wall -python interface.i\" > args.txt\n\
+ $ swig @args.txt\n\
\n";
// Local variables
diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx
index 397677fc5..f72525b6f 100644
--- a/Source/Modules/swigmain.cxx
+++ b/Source/Modules/swigmain.cxx
@@ -119,13 +119,14 @@ static swig_module modules[] = {
void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, char ***nargv) {
if (!env) {
*nargc = oargc;
- *nargv = oargv;
+ *nargv = (char **)malloc(sizeof(char *) * (oargc + 1));
+ memcpy(*nargv, oargv, sizeof(char *) * (oargc + 1));
return;
}
int argc = 1;
int arge = oargc + 1024;
- char **argv = (char **) malloc(sizeof(char *) * (arge));
+ char **argv = (char **) malloc(sizeof(char *) * (arge + 1));
char *buffer = (char *) malloc(2048);
char *b = buffer;
char *be = b + 1023;
@@ -147,11 +148,90 @@ void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, ch
for (int i = 1; (i < oargc) && (argc < arge); ++i, ++argc) {
argv[argc] = oargv[i];
}
+ argv[argc] = NULL;
*nargc = argc;
*nargv = argv;
}
+static void insert_option(int *argc, char ***argv, int index, char const *start, char const *end) {
+ int new_argc = *argc;
+ char **new_argv = *argv;
+ size_t option_len = end - start;
+
+ // Preserve the NULL pointer at argv[argc]
+ new_argv = (char **)realloc(new_argv, (new_argc + 2) * sizeof(char *));
+ memmove(&new_argv[index + 1], &new_argv[index], sizeof(char *) * (new_argc + 1 - index));
+ new_argc++;
+
+ new_argv[index] = (char *)malloc(option_len + 1);
+ memcpy(new_argv[index], start, option_len);
+ new_argv[index][option_len] = '\0';
+
+ *argc = new_argc;
+ *argv = new_argv;
+}
+
+static void merge_options_files(int *argc, char ***argv) {
+ static const int BUFFER_SIZE = 4096;
+ char buffer[BUFFER_SIZE];
+ int i;
+ int insert;
+ char **new_argv = *argv;
+ int new_argc = *argc;
+ FILE *f;
+
+ i = 1;
+ while (i < new_argc) {
+ if (new_argv[i] && new_argv[i][0] == '@' && (f = fopen(&new_argv[i][1], "r"))) {
+ char c;
+ char *b;
+ char *be = &buffer[BUFFER_SIZE];
+ int quote = 0;
+ bool escape = false;
+
+ new_argc--;
+ memmove(&new_argv[i], &new_argv[i + 1], sizeof(char *) * (new_argc - i));
+ insert = i;
+ b = buffer;
+
+ while ((c = fgetc(f)) != EOF) {
+ if (escape) {
+ if (b != be) {
+ *b = c;
+ ++b;
+ }
+ escape = false;
+ } else if (c == '\\') {
+ escape = true;
+ } else if (!quote && (c == '\'' || c == '"')) {
+ quote = c;
+ } else if (quote && c == quote) {
+ quote = 0;
+ } else if (isspace(c) && !quote) {
+ if (b != buffer) {
+ insert_option(&new_argc, &new_argv, insert, buffer, b);
+ insert++;
+
+ b = buffer;
+ }
+ } else if (b != be) {
+ *b = c;
+ ++b;
+ }
+ }
+ if (b != buffer)
+ insert_option(&new_argc, &new_argv, insert, buffer, b);
+ fclose(f);
+ } else {
+ ++i;
+ }
+ }
+
+ *argv = new_argv;
+ *argc = new_argc;
+}
+
int main(int margc, char **margv) {
int i;
Language *dl = 0;
@@ -161,6 +241,7 @@ int main(int margc, char **margv) {
char **argv;
SWIG_merge_envopt(getenv("SWIG_FEATURES"), margc, margv, &argc, &argv);
+ merge_options_files(&argc, &argv);
#ifdef MACSWIG
SIOUXSettings.asktosaveonclose = false;