From 5a5cf3b8711d10f5c46d4a19e3bf25033ab34ad1 Mon Sep 17 00:00:00 2001 From: Rejean Loyer Date: Wed, 12 Jun 2013 15:59:31 -0400 Subject: [PATCH] ecere, ide; Instance_COM_Initialize, Tokenize, _DualPipeOpen; multiple fixes. finally closes #778, #777 and #863. - affects all command line tools. - fixed windows arguments parsing to respect spaces and double quotes that are escaped. - adjusted toolchaing debugging tools to not alter the way args are passed to the debugging ide now that win args parsing is fixed. - fixed preprocessor definitions when defining MY_STR_DEF="string" on windows by escaping quotes. --- Makefile | 2 +- compiler/Makefile | 4 +- compiler/ecc/ecc.ec | 70 +++++++++------------ compiler/ecp/ecp.ec | 55 ++++++----------- compiler/libec/src/ecdefs.ec | 39 ++++++++++++ crossplatform.mk | 38 +++++++----- default.cf | 8 +-- ear/extract/Makefile | 4 +- ecere/Makefile | 2 +- ecere/Makefile.ecereCOM | 2 +- ecere/Makefile.vanilla | 2 +- ecere/src/com/String.ec | 67 ++++++++++---------- ecere/src/com/instance.c | 5 +- ecere/src/sys/DualPipe.c | 3 +- ide/src/debugger/Debugger.ec | 8 +++ ide/src/ide.ec | 73 ++++++---------------- ide/src/project/Project.ec | 135 ++++++++++++++++++++++++++--------------- ide/src/project/ProjectNode.ec | 62 +++++++++---------- 18 files changed, 298 insertions(+), 281 deletions(-) diff --git a/Makefile b/Makefile index 8c6c755..596ed56 100644 --- a/Makefile +++ b/Makefile @@ -126,7 +126,7 @@ else endif export CPPFLAGS -CPPFLAGS += -DDEB_HOST_MULTIARCH=\"$(PREFIXLIBDIR)\" +CPPFLAGS += -DDEB_HOST_MULTIARCH=\"$(call escspace,$(PREFIXLIBDIR))\" DESTLIBDIR := $(DESTDIR)$(PREFIXLIBDIR) ifdef SLIBDIR diff --git a/compiler/Makefile b/compiler/Makefile index c5418b2..fb9e957 100644 --- a/compiler/Makefile +++ b/compiler/Makefile @@ -54,7 +54,7 @@ clean: realclean: cd bootstrap && $(MAKE) realclean cd libec && $(MAKE) realclean - cd libec && $(MAKE) fixprecompile + cd libec && $(MAKE) silentfixprecompile cd ecp && $(MAKE) realclean cd ecc && $(MAKE) realclean cd ecs && $(MAKE) realclean @@ -62,7 +62,7 @@ realclean: distclean: cd bootstrap && $(MAKE) distclean cd libec && $(MAKE) distclean - cd libec && $(MAKE) fixprecompile + cd libec && $(MAKE) silentfixprecompile cd ecp && $(MAKE) distclean cd ecc && $(MAKE) distclean cd ecs && $(MAKE) distclean diff --git a/compiler/ecc/ecc.ec b/compiler/ecc/ecc.ec index 4969d56..7b680d7 100644 --- a/compiler/ecc/ecc.ec +++ b/compiler/ecc/ecc.ec @@ -296,42 +296,31 @@ class CompilerApp : Application { if(!strcmp(arg + 1, "m32") || !strcmp(arg + 1, "m64")) { - int argLen = strlen(arg); - int newLen = cppOptionsLen + 1 + argLen; + int newLen = cppOptionsLen + 1 + strlen(arg); cppOptions = renew cppOptions char[newLen + 1]; cppOptions[cppOptionsLen] = ' '; strcpy(cppOptions + cppOptionsLen + 1, arg); cppOptionsLen = newLen; targetBits = !strcmp(arg + 1, "m32") ? 32 : 64; } - else if(arg[1] == 'D') + else if(arg[1] == 'D' || arg[1] == 'I') { - int argLen = strlen(arg); - int newLen = cppOptionsLen + 1 + argLen; - cppOptions = renew cppOptions char[newLen + 1]; - cppOptions[cppOptionsLen] = ' '; - strcpy(cppOptions + cppOptionsLen + 1, arg); - cppOptionsLen = newLen; - if(!strcmp(arg, "-DBUILDING_ECERE_COM")) - SetBuildingEcereCom(true); - else if(!strcmp(arg, "-DECERE_COM_MODULE")) - SetBuildingEcereComModule(true); - else if(!strcmp(arg, "-DECERE_BOOTSTRAP")) - buildingBootStrap = true; - } - else if(arg[1] == 'I') - { - int argLen = strlen(arg); - int newLen = cppOptionsLen + argLen + 3; - cppOptions = renew cppOptions char[newLen + 1]; - cppOptions[cppOptionsLen] = ' '; - cppOptions[cppOptionsLen+1] = '-'; - cppOptions[cppOptionsLen+2] = 'I'; - cppOptions[cppOptionsLen+3] = '"'; - strcpy(cppOptions + cppOptionsLen + 4, arg+2); - cppOptions[newLen-1] = '\"'; - cppOptions[newLen] = '\0'; - cppOptionsLen = newLen; + char * buf; + int size = cppOptionsLen + 1 + strlen(arg) * 2 + 1; + cppOptions = renew cppOptions char[size]; + buf = cppOptions + cppOptionsLen; + *buf++ = ' '; + PassArg(buf, arg); + cppOptionsLen = cppOptionsLen + 1 + strlen(buf); + if(arg[1] == 'D') + { + if(!strcmp(arg, "-DBUILDING_ECERE_COM")) + SetBuildingEcereCom(true); + else if(!strcmp(arg, "-DECERE_COM_MODULE")) + SetBuildingEcereComModule(true); + else if(!strcmp(arg, "-DECERE_BOOTSTRAP")) + buildingBootStrap = true; + } } else if(!strcmp(arg+1, "t")) { @@ -371,19 +360,16 @@ class CompilerApp : Application { if(c + 1 < argc) { - int argLen = strlen(arg); - int arg1Len = strlen(argv[c+1]); - int newLen = cppOptionsLen + argLen + arg1Len + 4; - cppOptions = renew cppOptions char[newLen + 1]; - cppOptions[cppOptionsLen] = ' '; - strcpy(cppOptions + cppOptionsLen + 1, arg); - cppOptions[cppOptionsLen+argLen+1] = ' '; - cppOptions[cppOptionsLen+argLen+2] = '"'; - arg = argv[++c]; - strcpy(cppOptions + cppOptionsLen + argLen + 3, arg); - cppOptions[newLen-1] = '\"'; - cppOptions[newLen] = '\0'; - cppOptionsLen = newLen; + char * buf; + char * arg1 = argv[++c]; + int size = cppOptionsLen + 1 + strlen(arg) * 2 + strlen(arg1) * 2 + 1; + cppOptions = renew cppOptions char[size]; + buf = cppOptions + cppOptionsLen; + *buf++ = ' '; + buf = PassArg(buf, arg); + *buf++ = ' '; + buf = PassArg(buf, arg1); + cppOptionsLen = buf - cppOptions; } else valid = false; diff --git a/compiler/ecp/ecp.ec b/compiler/ecp/ecp.ec index 6d60e3c..38e399b 100644 --- a/compiler/ecp/ecp.ec +++ b/compiler/ecp/ecp.ec @@ -1337,36 +1337,22 @@ class PrecompApp : Application { if(!strcmp(arg + 1, "m32") || !strcmp(arg + 1, "m64")) { - int argLen = strlen(arg); - int newLen = cppOptionsLen + 1 + argLen; + int newLen = cppOptionsLen + 1 + strlen(arg); cppOptions = renew cppOptions char[newLen + 1]; cppOptions[cppOptionsLen] = ' '; strcpy(cppOptions + cppOptionsLen + 1, arg); cppOptionsLen = newLen; targetBits = !strcmp(arg + 1, "m32") ? 32 : 64; } - else if(arg[1] == 'D') + else if(arg[1] == 'D' || arg[1] == 'I') { - int argLen = strlen(arg); - int newLen = cppOptionsLen + 1 + argLen; - cppOptions = renew cppOptions char[newLen + 1]; - cppOptions[cppOptionsLen] = ' '; - strcpy(cppOptions + cppOptionsLen + 1, arg); - cppOptionsLen = newLen; - } - else if(arg[1] == 'I') - { - int argLen = strlen(arg); - int newLen = cppOptionsLen + argLen + 3; - cppOptions = renew cppOptions char[newLen + 1]; - cppOptions[cppOptionsLen] = ' '; - cppOptions[cppOptionsLen+1] = '-'; - cppOptions[cppOptionsLen+2] = 'I'; - cppOptions[cppOptionsLen+3] = '"'; - strcpy(cppOptions + cppOptionsLen + 4, arg+2); - cppOptions[newLen-1] = '\"'; - cppOptions[newLen] = '\0'; - cppOptionsLen = newLen; + char * buf; + int size = cppOptionsLen + 1 + strlen(arg) * 2 + 1; + cppOptions = renew cppOptions char[size]; + buf = cppOptions + cppOptionsLen; + *buf++ = ' '; + PassArg(buf, arg); + cppOptionsLen = cppOptionsLen + 1 + strlen(buf); } else if(!strcmp(arg+1, "t")) { @@ -1406,19 +1392,16 @@ class PrecompApp : Application { if(c + 1 < argc) { - int argLen = strlen(arg); - int arg1Len = strlen(argv[c+1]); - int newLen = cppOptionsLen + argLen + arg1Len + 4; - cppOptions = renew cppOptions char[newLen + 1]; - cppOptions[cppOptionsLen] = ' '; - strcpy(cppOptions + cppOptionsLen + 1, arg); - cppOptions[cppOptionsLen+argLen+1] = ' '; - cppOptions[cppOptionsLen+argLen+2] = '"'; - arg = argv[++c]; - strcpy(cppOptions + cppOptionsLen + argLen + 3, arg); - cppOptions[newLen-1] = '\"'; - cppOptions[newLen] = '\0'; - cppOptionsLen = newLen; + char * buf; + char * arg1 = argv[++c]; + int size = cppOptionsLen + 1 + strlen(arg) * 2 + strlen(arg1) * 2 + 1; + cppOptions = renew cppOptions char[size]; + buf = cppOptions + cppOptionsLen; + *buf++ = ' '; + buf = PassArg(buf, arg); + *buf++ = ' '; + buf = PassArg(buf, arg1); + cppOptionsLen = buf - cppOptions; } else valid = false; diff --git a/compiler/libec/src/ecdefs.ec b/compiler/libec/src/ecdefs.ec index e316105..e2fea0e 100644 --- a/compiler/libec/src/ecdefs.ec +++ b/compiler/libec/src/ecdefs.ec @@ -101,6 +101,45 @@ public void FixModuleName(char *moduleName) ChangeCh(moduleName, '&', '_'); } +// todo support %var% variables for windows and $var for linux? +public char * PassArg(char * output, const char * input) +{ +#ifdef __WIN32__ +//define windowsFileNameCharsNeedEscaping = " !%&'()+,;=[]^`{}~"; // "#$-.@_" are ok + const char * escChars = " !\"%&'()+,;=[]^`{}~"; // windowsFileNameCharsNeedEscaping; + const char * escCharsQuoted = "\""; +#else +//define linuxFileNameCharsNeedEscaping = " !\"$&'()*:;<=>?[\\`{|"; // "#%+,-.@]^_}~" are ok + const char * escChars = " !\"$&'()*:;<=>?[\\`{|"; // linuxFileNameCharsNeedEscaping; + const char * escCharsQuoted = "\"()$"; +#endif + bool quoting = false; + char *o = output, *i = input, *l = input; +#ifdef __WIN32__ + while(*l && !strchr(escChars, *l)) l++; + if(*l) quoting = true; +#else + if(*i == '-') + { + l++; + while(*l && !strchr(escChars, *l)) l++; + if(*l) quoting = true; + *o++ = *i++; + } +#endif + if(quoting) + *o++ = '\"'; + while(*i) + { + if(strchr(quoting ? escCharsQuoted : escChars, *i)) + *o++ = '\\'; + *o++ = *i++; + } + if(quoting) + *o++ = '\"'; + *o = '\0'; + return o; +} /*public Module GetPrivateModule() { return privateModule; diff --git a/crossplatform.mk b/crossplatform.mk index c19098b..b3b90c0 100644 --- a/crossplatform.mk +++ b/crossplatform.mk @@ -150,11 +150,15 @@ endif # MISC STRING TOOLS empty := +esc := $(empty)$(empty) space := $(empty) $(empty) comma := , -escspace = $(subst $(space),\$(space),$(subst \$(space),$(space),$1)) -hidspace = $(subst $(space),,$(subst \$(space),,$1)) -shwspace = $(subst ,\$(space),$1) +slash := $(empty)/$(empty) +backslash := $(empty)\$(empty) +escspace = $(subst $(space),$(backslash)$(space),$(subst $(backslash)$(space),$(space),$(1))) +hidspace = $(subst $(space),$(esc),$(subst $(backslash)$(space),$(esc),$(1))) +shwspace = $(subst $(esc),$(backslash)$(space),$(1)) +unescp_all = $(subst $(esc),$(backslash),$(subst $(backslash),,$(subst $(backslash)$(backslash),$(esc),$(1)))) # PATH SEPARATOR STRING TOOLS ifdef WINDOWS_HOST @@ -163,13 +167,15 @@ ifndef MSYSCON endif endif ifdef WIN_PS_TOOLS - fixps = $(subst \,/,$(1)) - psep = $(subst \\,/,$(subst /,\,$(1))) - PS := $(strip \) + psep := $(backslash) + slash_path = $(subst $(backslash),$(slash),$(1)) + sys_path = $(subst $(backslash)$(backslash),$(slash),$(subst $(slash),$(backslash),$(1))) + quote_path = "$(call sys_path,$(call unescp_all,$(1)))" else - fixps = $(1) - PS := $(strip /) - psep = $(1) + psep := $(slash) + slash_path = $(1) + sys_path = $(1) + quote_path = $(1) endif # PREFIXES AND EXTENSIONS @@ -215,12 +221,12 @@ endif endif ifdef WIN_SHELL_COMMANDS echo = $(if $(1),echo $(1)) - touch = $(if $(1),@cmd /c "for %%a in ($(call psep,$(1))) do @(cd %%~pa && type nul >> %%~nxa && copy /by %%~nxa+,, >nul 2>&1 && cd %%cd%%)") - cpq = $(if $(1),@cmd /c "for %%a in ($(call psep,$(1))) do copy /by %%a $(call psep,$(2))" >nul 2>&1) - rmq = $(if $(1),-del /f /q $(call psep,$(1)) > nul 2>&1) - rmrq = $(if $(1),-rmdir /q /s $(call psep,$(1)) > nul 2>&1) - mkdirq = $(if $(1),-mkdir $(call psep,$(1)) > nul 2>&1) - rmdirq = $(if $(1),-rmdir /q $(call psep,$(1)) > nul 2>&1) + touch = $(if $(1),@cmd /c "for %%I in ($(call sys_path,$(1))) do @(cd %%~pI && type nul >> %%~nxI && copy /by %%~nxI+,, > nul 2>&1 && cd %%cd%%)") + cpq = $(if $(1),@cmd /c "for %%I in ($(call sys_path,$(1))) do copy /by %%I $(call sys_path,$(2))" > nul 2>&1) + rmq = $(if $(1),-del /f /q $(call sys_path,$(1)) > nul 2>&1) + rmrq = $(if $(1),-rmdir /q /s $(call sys_path,$(1)) > nul 2>&1) + mkdirq = $(if $(1),-mkdir $(call sys_path,$(1)) > nul 2>&1) + rmdirq = $(if $(1),-rmdir /q $(call sys_path,$(1)) > nul 2>&1) else echo = $(if $(1),echo "$(1)") touch = $(if $(1),touch $(1)) @@ -260,7 +266,7 @@ endif # COMMON LIBRARIES DETECTION ifdef WINDOWS_TARGET ifdef OPENSSL_CONF - _OPENSSL_CONF = $(call hidspace,$(call fixps,$(OPENSSL_CONF))) + _OPENSSL_CONF = $(call hidspace,$(call slash_path,$(OPENSSL_CONF))) OPENSSL_INCLUDE_DIR = $(call shwspace,$(subst /bin/openssl.cfg,/include,$(_OPENSSL_CONF))) OPENSSL_LIB_DIR = $(call shwspace,$(subst /bin/openssl.cfg,/lib,$(_OPENSSL_CONF))) OPENSSL_BIN_DIR = $(call shwspace,$(subst /bin/openssl.cfg,/bin,$(_OPENSSL_CONF))) diff --git a/default.cf b/default.cf index 513a1cb..a4a2058 100644 --- a/default.cf +++ b/default.cf @@ -14,10 +14,10 @@ export AS = $(GCC_PREFIX)as export LD = $(GCC_PREFIX)ld export AR = $(GCC_PREFIX)ar export STRIP = $(GCC_PREFIX)strip -export ECP := $(call psep,$(EC_BINS)ecp$(HOST_E)) -export ECC := $(call psep,$(EC_BINS)ecc$(HOST_E))$(if $(CROSS_TARGET), -t $(TARGET_PLATFORM),) -export ECS := $(call psep,$(EC_BINS)ecs$(HOST_E))$(if $(CROSS_TARGET), -t $(TARGET_PLATFORM),)$(if $(OUTPUT_POT), -outputpot,) -export EAR := $(call psep,$(_CF_DIR)obj/$(HOST_PLATFORM)$(COMPILER_SUFFIX)$(DEBUG_SUFFIX)/bin/ear$(HOST_E)) +export ECP := $(call sys_path,$(EC_BINS)ecp$(HOST_E)) +export ECC := $(call sys_path,$(EC_BINS)ecc$(HOST_E))$(if $(CROSS_TARGET), -t $(TARGET_PLATFORM),) +export ECS := $(call sys_path,$(EC_BINS)ecs$(HOST_E))$(if $(CROSS_TARGET), -t $(TARGET_PLATFORM),)$(if $(OUTPUT_POT), -outputpot,) +export EAR := $(call sys_path,$(_CF_DIR)obj/$(HOST_PLATFORM)$(COMPILER_SUFFIX)$(DEBUG_SUFFIX)/bin/ear$(HOST_E)) ifdef WINDOWS_TARGET WINDRES := $(GCC_PREFIX)windres ifdef ARCH diff --git a/ear/extract/Makefile b/ear/extract/Makefile index 4300cc0..aeb287a 100644 --- a/ear/extract/Makefile +++ b/ear/extract/Makefile @@ -198,10 +198,10 @@ ifndef NOSTRIP endif ifndef WINDOWS_TARGET ifdef EXECUTABLE_TARGET - @-$(call psep,$(UPX) $(UPXFLAGS) $(TARGET)) || $(call echo,upx not installed; not compressing.) + @-$(call sys_path,$(UPX) $(UPXFLAGS) $(TARGET)) || $(call echo,upx not installed; not compressing.) endif else - @-$(call psep,$(UPX) $(UPXFLAGS) $(TARGET)) || $(call echo,upx not installed; not compressing.) + @-$(call sys_path,$(UPX) $(UPXFLAGS) $(TARGET)) || $(call echo,upx not installed; not compressing.) endif $(EAR) aw$(EARFLAGS) $(TARGET) ../../ecere/res/vanilla/ecere/actions/folderNew.png ../../ecere/res/vanilla/ecere/actions/goUp.png "ecere/actions" $(EAR) aw$(EARFLAGS) $(TARGET) ../../ecere/res/vanilla/ecere/devices/computer.png ../../ecere/res/vanilla/ecere/devices/driveHardDisk.png ../../ecere/res/vanilla/ecere/devices/driveRemovableMedia.png ../../ecere/res/vanilla/ecere/devices/mediaFloppy.png ../../ecere/res/vanilla/ecere/devices/mediaOptical.png "ecere/devices" diff --git a/ecere/Makefile b/ecere/Makefile index f7880ef..dfdd089 100644 --- a/ecere/Makefile +++ b/ecere/Makefile @@ -38,7 +38,7 @@ include $(_CF_DIR)crossplatform.mk include $(_CF_DIR)default.cf ifdef PREFIXLIBDIR -CFLAGS += -DDEB_HOST_MULTIARCH=\"$(PREFIXLIBDIR)\" +CFLAGS += -DDEB_HOST_MULTIARCH=\"$(call escspace,$(PREFIXLIBDIR))\" endif # POST-INCLUDES VARIABLES diff --git a/ecere/Makefile.ecereCOM b/ecere/Makefile.ecereCOM index 5335a33..14ce21c 100644 --- a/ecere/Makefile.ecereCOM +++ b/ecere/Makefile.ecereCOM @@ -38,7 +38,7 @@ include $(_CF_DIR)crossplatform.mk include $(_CF_DIR)default.cf ifdef PREFIXLIBDIR -CFLAGS += -DDEB_HOST_MULTIARCH=\"$(PREFIXLIBDIR)\" +CFLAGS += -DDEB_HOST_MULTIARCH=\"$(call escspace,$(PREFIXLIBDIR))\" endif # POST-INCLUDES VARIABLES diff --git a/ecere/Makefile.vanilla b/ecere/Makefile.vanilla index 1fcc1b9..1d8b776 100644 --- a/ecere/Makefile.vanilla +++ b/ecere/Makefile.vanilla @@ -38,7 +38,7 @@ include $(_CF_DIR)crossplatform.mk include $(_CF_DIR)default.cf ifdef PREFIXLIBDIR -CFLAGS += -DDEB_HOST_MULTIARCH=\"$(PREFIXLIBDIR)\" +CFLAGS += -DDEB_HOST_MULTIARCH=\"$(call escspace,$(PREFIXLIBDIR))\" endif # POST-INCLUDES VARIABLES diff --git a/ecere/src/com/String.ec b/ecere/src/com/String.ec index addfbab..fcd0c01 100644 --- a/ecere/src/com/String.ec +++ b/ecere/src/com/String.ec @@ -818,65 +818,66 @@ public char * RSearchString(char * buffer, char * subStr, int maxLen, bool match return null; } -public int Tokenize(char * string, int maxTokens, char* tokens[], bool escapeBackSlashes) +//public define gnuMakeCharsNeedEscaping = "$%"; +//public define windowsFileNameCharsNotAllowed = "*/:<>?\\\"|"; +//public define linuxFileNameCharsNotAllowed = "/"; +//public define windowsFileNameCharsNeedEscaping = " !%&'()+,;=[]^`{}~"; // "#$-.@_" are ok +//public define linuxFileNameCharsNeedEscaping = " !\"$&'()*:;<=>?[\\`{|"; // "#%+,-.@]^_}~" are ok + +// fix #139 to remove " = 2" and warnings for backward compatible calls to Tokenize using 'true' for the 'esc' argument; +public enum BackSlashEscaping : bool { forArgsPassing = 2 }; +public int Tokenize(char * string, int maxTokens, char* tokens[], BackSlashEscaping esc) { +#ifdef __WIN32__ +//define windowsFileNameCharsNeedEscaping = " !%&'()+,;=[]^`{}~"; // "#$-.@_" are ok + const char * escChars = " !\"%&'()+,;=[]^`{}~"; // windowsFileNameCharsNeedEscaping; + const char * escCharsQuoted = "\""; +#else +//define linuxFileNameCharsNeedEscaping = " !\"$&'()*:;<=>?[\\`{|"; // "#%+,-.@]^_}~" are ok + const char * escChars = " !\"$&'()*:;<=>?[\\`{|"; // linuxFileNameCharsNeedEscaping; + const char * escCharsQuoted = "\"()$"; +#endif int count = 0; - bool quoted = false; - byte * start = null; - bool escaped = false; - char * output = string; - - for(; *string && count < maxTokens; string++, output++) + bool quoted = false, escaped = false; + char * start = null, * output = string; + char ch; + for(; (ch = *string) && count 0) passArgs.concat(" "); - passArgs.concat(app.argv[c]); + PassArg(buf, arg); + passArgs.concat(buf); + delete buf; } else if(debugWorkDir) { @@ -2845,6 +2839,16 @@ class IDEWorkSpace : Window StripQuotes(passDebugWorkDir, passDebugWorkDir); debugWorkDir = false; } + else if(!strcmp(app.argv[c], "-t")) + openAsText = true; + else if(!strcmp(app.argv[c], "-no-parsing")) + ide.noParsing = true; + else if(!strcmp(app.argv[c], "-debug-start")) + debugStart = true; + else if(!strcmp(app.argv[c], "-debug-work-dir")) + debugWorkDir = true; + else if(!strcmp(app.argv[c], "-@")) + passThrough = true; else { char fullPath[MAX_LOCATION]; @@ -2905,49 +2909,8 @@ class IDEWorkSpace : Window } } if(passThrough && projectView && projectView.project && workspace) - { - char * fixSpacing = new char[Max(passArgs.size * 1.5, 32)]; - { - int c, d = 0; - char j = 0; - char k = ' '; - char l = 0; - bool inQuote = false; - for(c=0; c?[\\`{|"; // "#%+,-.@]^_}~" are ok + +// NOTES: - this function should get only unescaped unix style paths +// - paths with literal $(somestring) in them are not supported +// my_$(messed_up)_path would likely become my__path +void EscapeForMake(char * output, char * input, bool hideSpace, bool allowVars, bool allowDblQuote) { - char ch; - char * s = source, * d = output; + char ch, *i = input, *o = output; bool inVar = false; - while((ch = *s++)) +#ifdef _DEBUG + int len = strlen(input); + if(len && ((input[0] == '"' && input[len-1] == '"') || strchr(input, '\\') || strchr(input, 127) || (!allowDblQuote && strchr(input, '"')))) + PrintLn("Invalid input for EscapeForMake! -- ", input); +#endif + while((ch = *i++)) { if(ch == '(') { - if(s != source && *(s-1) == '$') + if(i-1 != input && *(i-2) == '$' && allowVars) inVar = true; else - *d++ = '\\'; + *o++ = '\\'; } else if(ch == ')') { - if(inVar == true) + if(inVar == true && allowVars) inVar = false; else - *d++ = '\\'; + *o++ = '\\'; } - else if(ch == '$' && *(s+1) != '(') - *d++ = '$'; + else if(ch == '$' && *i != '(') + *o++ = '$'; + else if(ch == '&') + *o++ = '\\'; + else if(ch == '"') + *o++ = '\\'; if(ch == ' ') - *d++ = 127; + { + if(hideSpace) + *o++ = 127; + else + { + *o++ = '\\'; + *o++ = ch; + } + } else - *d++ = ch; + *o++ = ch; } - *d = '\0'; + *o = '\0'; } -static void OutputNoSpace(File f, char * source) +void EscapeForMakeToFile(File output, char * input, bool hideSpace, bool allowVars, bool allowDblQuote) { - char * output = new char[strlen(source)+1024]; - ReplaceSpaces(output, source); - f.Puts(output); - delete output; + char * buf = new char[strlen(input)*2+1]; + EscapeForMake(buf, input, hideSpace, allowVars, allowDblQuote); + output.Print(buf); + delete buf; } -enum ListOutputMethod { inPlace, newLine, lineEach }; +void EscapeForMakeToDynString(DynamicString output, char * input, bool hideSpace, bool allowVars, bool allowDblQuote) +{ + char * buf = new char[strlen(input)*2+1]; + EscapeForMake(buf, input, hideSpace, allowVars, allowDblQuote); + output.concat(buf); + delete buf; +} int OutputFileList(File f, char * name, Array list, Map varStringLenDiffs, char * prefix) { @@ -593,33 +628,35 @@ void OutputCleanActions(File f, char * name, int parts) f.Printf("\t$(call rmq,$(%s))\n", name); } -void OutputListOption(File f, char * option, Array list, ListOutputMethod method, bool noSpace, bool noDash) +enum LineOutputMethod { inPlace, newLine, lineEach }; +enum StringOutputMethod { asIs, escape, escapePath}; + +enum ToolchainFlag { any, _D, _I, _isystem, _Wl, _L/*, _Wl-rpath*/ }; +String flagNames[ToolchainFlag] = { "", "-D", "-I", "-isystem ", "-Wl,", "-Wl,--library-path="/*, "-Wl,-rpath "*/ }; +void OutputFlags(File f, ToolchainFlag flag, Array list, LineOutputMethod lineMethod) { if(list.count) { - if(method == newLine) + if(lineMethod == newLine) f.Puts(" \\\n\t"); for(item : list) { - if(method == lineEach) + if(lineMethod == lineEach) f.Puts(" \\\n\t"); - f.Printf(" %s%s", noDash ? "" : "-", option); - if(noSpace) - OutputNoSpace(f, item); + f.Printf(" %s", flagNames[flag]); + if(flag != _D && flag != _Wl && flag != any) + { + char * tmp = new char[strlen(item)*2+1]; + EscapeForMake(tmp, item, false, true, false); + f.Printf("$(call quote_path,%s)", tmp); + delete tmp; + } else - f.Printf("%s", item); + EscapeForMakeToFile(f, item, false, true, true); } } } -void StringNoSpaceToDynamicString(DynamicString s, char * path) -{ - char * output = new char[strlen(path)+1024]; - ReplaceSpaces(output, path); - s.concat(output); - delete output; -} - static void OutputLibraries(File f, Array libraries) { for(item : libraries) @@ -645,7 +682,7 @@ static void OutputLibraries(File f, Array libraries) f.Puts(" \\\n\t$(call _L,"); usedFunction = true; } - OutputNoSpace(f, s); + EscapeForMakeToFile(f, s, false, false, false); if(usedFunction) f.Puts(")"); } @@ -1630,7 +1667,7 @@ private: precompiling = true; } // Changed escapeBackSlashes here to handle paths with spaces - Tokenize(module, 1, tokens, true); // false); + Tokenize(module, 1, tokens, (BackSlashEscaping)true); // fix #139 GetLastDirectory(module, moduleName); ide.outputView.buildBox.Logf("%s\n", moduleName); } @@ -1660,7 +1697,7 @@ private: if(module) { byte * tokens[1]; - Tokenize(module, 1, tokens, true); + Tokenize(module, 1, tokens, (BackSlashEscaping)true); // fix #139 GetLastDirectory(module, moduleName); ide.outputView.buildBox.Logf("%s\n", moduleName); } @@ -2297,8 +2334,6 @@ private: fileName[0] = '\0'; if(targetType == staticLibrary || targetType == sharedLibrary) strcat(fileName, "$(LP)"); - // !!! ReplaceSpaces must be done after all PathCat calls !!! - // ReplaceSpaces(s, GetTargetFileName(config)); strcat(fileName, GetTargetFileName(config)); switch(targetType) { @@ -2483,21 +2518,21 @@ private: if(compiler.includeDirs && compiler.includeDirs.count) { f.Puts("\nCFLAGS +="); - OutputListOption(f, gccCompiler ? "isystem " : "I", compiler.includeDirs, lineEach, true, false); + OutputFlags(f, gccCompiler ? _isystem : _I, compiler.includeDirs, lineEach); f.Puts("\n"); } if(compiler.prepDirectives && compiler.prepDirectives.count) { f.Puts("\nCFLAGS +="); - OutputListOption(f, "D", compiler.prepDirectives, inPlace, true, false); + OutputFlags(f, _D, compiler.prepDirectives, inPlace); f.Puts("\n"); } if(compiler.libraryDirs && compiler.libraryDirs.count) { f.Puts("\nLDFLAGS +="); - OutputListOption(f, "L", compiler.libraryDirs, lineEach, true, false); + OutputFlags(f, _L, compiler.libraryDirs, lineEach); // We would need a bool option to know whether we want to add to rpath as well... - // OutputListOption(f, "Wl,-rpath ", compiler.libraryDirs, lineEach, true, false); + // OutputFlags(f, _Wl-rpath, compiler.libraryDirs, lineEach); f.Puts("\n"); } if(compiler.excludeLibs && compiler.excludeLibs.count) @@ -2512,13 +2547,13 @@ private: if(compiler.compilerFlags && compiler.compilerFlags.count) { f.Puts("\nCFLAGS +="); - OutputListOption(f, "", compiler.compilerFlags, inPlace, true, true); + OutputFlags(f, any, compiler.compilerFlags, inPlace); f.Puts("\n"); } if(compiler.linkerFlags && compiler.linkerFlags.count) { f.Puts("\nLDFLAGS +="); - OutputListOption(f, "Wl,", compiler.linkerFlags, inPlace, true, false); + OutputFlags(f, _Wl, compiler.linkerFlags, inPlace); f.Puts("\n"); } f.Puts("\n"); @@ -2979,9 +3014,9 @@ private: { f.Puts("OFLAGS +="); if(configPlatformOptions && configPlatformOptions.options.libraryDirs) - OutputListOption(f, "L", configPlatformOptions.options.libraryDirs, lineEach, true, false); + OutputFlags(f, _L, configPlatformOptions.options.libraryDirs, lineEach); if(projectPlatformOptions && projectPlatformOptions.options.libraryDirs) - OutputListOption(f, "L", projectPlatformOptions.options.libraryDirs, lineEach, true, false); + OutputFlags(f, _L, projectPlatformOptions.options.libraryDirs, lineEach); f.Puts("\n"); } @@ -3094,9 +3129,9 @@ private: f.Puts("ifndef STATIC_LIBRARY_TARGET\n"); f.Puts("OFLAGS +="); if(config && config.options && config.options.libraryDirs) - OutputListOption(f, "L", config.options.libraryDirs, lineEach, true, false); + OutputFlags(f, _L, config.options.libraryDirs, lineEach); if(options && options.libraryDirs) - OutputListOption(f, "L", options.libraryDirs, lineEach, true, false); + OutputFlags(f, _L, options.libraryDirs, lineEach); f.Puts("\n"); f.Puts("endif\n"); f.Puts("\n"); diff --git a/ide/src/project/ProjectNode.ec b/ide/src/project/ProjectNode.ec index 7d86f8f..7009792 100644 --- a/ide/src/project/ProjectNode.ec +++ b/ide/src/project/ProjectNode.ec @@ -1452,7 +1452,7 @@ private: strcpy(tempPath, path); PathCatSlash(tempPath, name); } - ReplaceUnwantedMakeChars(modulePath, tempPath); + EscapeForMake(modulePath, tempPath, true, true, false); sprintf(s, "%s%s%s%s", ts.a, useRes ? "$(RES)" : "", modulePath, ts.b); items.Add(CopyString(s)); } @@ -1463,8 +1463,8 @@ private: !strcmpi(extension, "m") || !strcmpi(extension, "mm")) { char modulePath[MAX_LOCATION]; - ReplaceUnwantedMakeChars(modulePath, path); - ReplaceUnwantedMakeChars(moduleName, name); + EscapeForMake(modulePath, path, true, true, false); + EscapeForMake(moduleName, name, true, true, false); sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b); items.Add(CopyString(s)); } @@ -1474,8 +1474,8 @@ private: if(!strcmpi(extension, "ec")) { char modulePath[MAX_LOCATION]; - ReplaceUnwantedMakeChars(modulePath, path); - ReplaceUnwantedMakeChars(moduleName, name); + EscapeForMake(modulePath, path, true, true, false); + EscapeForMake(moduleName, name, true, true, false); sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b); items.Add(CopyString(s)); count++; @@ -1486,8 +1486,8 @@ private: if(!strcmpi(extension, "rc")) { char modulePath[MAX_LOCATION]; - ReplaceUnwantedMakeChars(modulePath, path); - ReplaceUnwantedMakeChars(moduleName, name); + EscapeForMake(modulePath, path, true, true, false); + EscapeForMake(moduleName, name, true, true, false); sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b); items.Add(CopyString(s)); count++; @@ -1502,7 +1502,7 @@ private: bool collision; NameCollisionInfo info; count++; - ReplaceUnwantedMakeChars(moduleName, name); + EscapeForMake(moduleName, name, true, true, false); StripExtension(moduleName); info = namesInfo[moduleName]; collision = info ? info.IsExtensionColliding(extension) : false; @@ -2129,7 +2129,7 @@ private: strcpy(tempPath, child.path); PathCatSlash(tempPath, child.name); } - ReplaceUnwantedMakeChars(resPath, tempPath); + EscapeForMake(resPath, tempPath, true, true, false); if(strchr(tempPath, ' ')) quotes = "\""; else @@ -3093,9 +3093,9 @@ static void GenCFlagsFromProjectOptions(ProjectOptions options, bool prjWithEcFi } if(options && options.preprocessorDefinitions) - ListOptionToDynamicString("D", options.preprocessorDefinitions, false, lineEach, "\t\t\t", false, s); + ListOptionToDynamicString(s, _D, options.preprocessorDefinitions, false, lineEach, "\t\t\t"); if(options && options.includeDirs) - ListOptionToDynamicString("I", options.includeDirs, true, lineEach, "\t\t\t", true, s); + ListOptionToDynamicString(s, _I, options.includeDirs, true, lineEach, "\t\t\t"); } static void GenECFlagsFromProjectOptions(ProjectOptions options, bool prjWithEcFiles, DynamicString s) @@ -3110,15 +3110,15 @@ static void GenECFlagsFromProjectOptions(ProjectOptions options, bool prjWithEcF s.concatf(" -defaultns %s", options.defaultNameSpace); } -static void ListOptionToDynamicString(char * option, Array list, bool prioritize, - ListOutputMethod method, String newLineStart, bool noSpace, DynamicString s) +static void ListOptionToDynamicString(DynamicString output, ToolchainFlag flag, Array list, bool prioritize, + LineOutputMethod lineMethod, String newLineStart) { if(list.count) { - if(method == newLine) + if(lineMethod == newLine) { - s.concat(" \\\n"); - s.concat(newLineStart); + output.concat(" \\\n"); + output.concat(newLineStart); } if(prioritize) { @@ -3129,17 +3129,14 @@ static void ListOptionToDynamicString(char * option, Array list, bool pr for(mn = sortedList.root.minimum; mn; mn = mn.next) { char * start = strstr(mn.key, "\n"); - if(method == lineEach) + if(lineMethod == lineEach) { - s.concat(" \\\n"); - s.concat(newLineStart); + output.concat(" \\\n"); + output.concat(newLineStart); } - s.concat(" -"); - s.concat(option); - if(noSpace) - StringNoSpaceToDynamicString(s, start ? start+1 : mn.key); - else - s.concat(start ? start+1 : mn.key); + output.concat(" "); + output.concat(flagNames[flag]); + EscapeForMakeToDynString(output, start ? start+1 : mn.key, false, true, flag == _D); } delete sortedList; } @@ -3147,17 +3144,14 @@ static void ListOptionToDynamicString(char * option, Array list, bool pr { for(item : list) { - if(method == lineEach) + if(lineMethod == lineEach) { - s.concat(" \\\n"); - s.concat(newLineStart); + output.concat(" \\\n"); + output.concat(newLineStart); } - s.concat(" -"); - s.concat(option); - if(noSpace) - StringNoSpaceToDynamicString(s, item); - else - s.concat(item); + output.concat(" "); + output.concat(flagNames[flag]); + EscapeForMakeToDynString(output, item, false, true, flag == _D); } } } -- 1.8.3.1