aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Watt <JPEWhacker@gmail.com>2017-11-28 21:43:24 -0600
committerJoshua Watt <Joshua.Watt@garmin.com>2018-01-12 15:01:45 -0600
commite9b4d3378b314e903db2dec6d6832245b8d61948 (patch)
treeed14c25b36232d51f2a49d964510337336baf54e
parent7eff4e7c1d40b4f6666aa8b635f30d8f6771e88f (diff)
downloadswig-e9b4d3378b314e903db2dec6d6832245b8d61948.tar.gz
Add option file support
Arguments may be passed using an option file prefixed with the '@' character. Processing of option files is the same as for the same feature in gcc.
-rw-r--r--Source/Modules/main.cxx4
-rw-r--r--Source/Modules/swigmain.cxx82
2 files changed, 85 insertions, 1 deletions
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 b49fe909a..f72525b6f 100644
--- a/Source/Modules/swigmain.cxx
+++ b/Source/Modules/swigmain.cxx
@@ -119,7 +119,8 @@ 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;
}
@@ -153,6 +154,84 @@ void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, ch
*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;
@@ -162,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;