From c3529a6b9b91735ef2012f4679cfb608ed4ae2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 10 Mar 2021 10:22:06 +0200 Subject: [PATCH] windres-wrapper: Implement support for the --preprocessor option --- wrappers/windres-wrapper.c | 69 +++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/wrappers/windres-wrapper.c b/wrappers/windres-wrapper.c index eed2aa6..da41987 100644 --- a/wrappers/windres-wrapper.c +++ b/wrappers/windres-wrapper.c @@ -31,6 +31,7 @@ #include #include +#include #define _P_WAIT 0 static int _spawnvp(int mode, const char *filename, const char * const *argv) { @@ -69,6 +70,57 @@ static const TCHAR *unescape_cpp(const TCHAR *str) { return out; } +static int split_args(const TCHAR *str, const TCHAR **args, int *num_args, int max_args) { + int len = _tcslen(str); + TCHAR *out = _tcsdup(str); + int i, outpos = 0; + int arg = num_args ? *num_args : 0; + int inquote = 0; + if (!args) + max_args = INT_MAX; + for (i = 0; i < len; i++) { + if (str[i] == '\\') { + if (i + 1 < len) + out[outpos++] = str[++i]; + else + fprintf(stderr, "Unterminated escape\n"); + continue; + } + if (str[i] == '"') { + inquote = !inquote; + continue; + } + if (str[i] == ' ' && !inquote) { + out[outpos++] = '\0'; + if (arg < max_args) { + if (args) + args[arg] = _tcsdup(out); + arg++; + } else + fprintf(stderr, "Too many options split\n"); + outpos = 0; + continue; + } + out[outpos++] = str[i]; + } + if (inquote) + fprintf(stderr, "Unterminated quote\n"); + if (outpos > 0) { + out[outpos++] = '\0'; + if (arg < max_args) { + if (args) + args[arg] = _tcsdup(out); + arg++; + } else + fprintf(stderr, "Too many options split\n"); + } + if (num_args) { + *num_args = arg; + arg -= *num_args; + } + return arg; +} + static void print_version(void) { printf( "version: LLVM windres (GNU windres compatible) 0.1\n" @@ -156,6 +208,7 @@ int _tmain(int argc, TCHAR* argv[]) { int nb_includes = 0; const TCHAR *codepage = _T("1252"); const TCHAR *language = NULL; + const TCHAR *preprocessor = NULL; const TCHAR **cpp_options = malloc(argc * sizeof(*cpp_options)); int nb_cpp_options = 0; int verbose = 0; @@ -207,7 +260,7 @@ int _tmain(int argc, TCHAR* argv[]) { } else OPTION("-c", "--codepage", codepage) else OPTION("-l", "--language", language) else if (!_tcscmp(argv[i], _T("--preprocessor"))) { - error(basename, _T("ENOSYS")); + SEPARATE_ARG(preprocessor); } else if (_tcsstart(argv[i], _T("--preprocessor-arg="))) { cpp_options[nb_cpp_options++] = _tcschr(argv[i], '=') + 1; } else if (!_tcscmp(argv[i], _T("--preprocessor-arg"))) { @@ -292,16 +345,22 @@ int _tmain(int argc, TCHAR* argv[]) { int max_arg = 2 * argc + 20; + if (preprocessor) + max_arg += split_args(preprocessor, NULL, NULL, 0); const TCHAR **exec_argv = malloc((max_arg + 1) * sizeof(*exec_argv)); int arg = 0; if (!_tcsicmp(input_format, _T("rc"))) { - exec_argv[arg++] = concat(dir, CC); - exec_argv[arg++] = _T("-E"); + if (preprocessor) { + split_args(preprocessor, exec_argv, &arg, max_arg); + } else { + exec_argv[arg++] = concat(dir, CC); + exec_argv[arg++] = _T("-E"); + exec_argv[arg++] = _T("-xc"); + exec_argv[arg++] = _T("-DRC_INVOKED=1"); + } for (int i = 0; i < nb_cpp_options; i++) exec_argv[arg++] = cpp_options[i]; - exec_argv[arg++] = _T("-xc"); - exec_argv[arg++] = _T("-DRC_INVOKED=1"); exec_argv[arg++] = input; exec_argv[arg++] = _T("-o"); exec_argv[arg++] = preproc_rc;