From a5587976252f75d06be7a2246ccba1d1b09f3649 Mon Sep 17 00:00:00 2001 From: ramon18 Date: Mon, 16 Jun 2003 19:58:29 +0000 Subject: [PATCH] Language strings inside any other strings, $$ defines fix, both currently disabled by defines, support for /LANG in command VIAddVersionKey git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2652 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/ResourceVersionInfo.cpp | 7 +-- Source/ResourceVersionInfo.h | 2 +- Source/build.cpp | 90 ++++++++++++++++++++++++++++++++-- Source/build.h | 8 +++ Source/exehead/config.h | 5 ++ Source/exehead/exec.c | 4 ++ Source/exehead/fileform.h | 4 ++ Source/exehead/util.c | 31 ++++++++++-- Source/exehead/util.h | 4 ++ Source/script.cpp | 62 ++++++++++++++++++++--- Source/tokens.cpp | 4 +- 11 files changed, 200 insertions(+), 21 deletions(-) diff --git a/Source/ResourceVersionInfo.cpp b/Source/ResourceVersionInfo.cpp index ad66a08b..cd6695e1 100644 --- a/Source/ResourceVersionInfo.cpp +++ b/Source/ResourceVersionInfo.cpp @@ -7,14 +7,14 @@ #include "ResourceVersionInfo.h" #ifdef NSIS_SUPPORT_VERSION_INFO - +/* int ValidCodePages[] = { 437, 708, 709, 710, 720, 737, 775, 850, 852, 855, 85, 86, 86, 86, 86, 864, 865, 866, 869, 874, 932, 936, 949, 950, 1200, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 20000, 20001, 20002, 20003, 20004, 20005, 20127, 20261, 20269, 20866, 21027, 21866, 28591, 28592, 28593, 28594, 28595, 28596, 28597, 28598, 28599, 29001, 1361, 0 }; - +*/ ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// @@ -253,7 +253,7 @@ char *CResourceVersionInfo::FindKey(LANGID LangID, int codepage, char *pKeyName) DefineList *pStrings = m_ChildStringLists.get_strings(pos); return pStrings->find(pKeyName); } - +/* bool CResourceVersionInfo::IsValidCodePage(WORD codePage ) { int *pCP = ValidCodePages; @@ -266,4 +266,5 @@ bool CResourceVersionInfo::IsValidCodePage(WORD codePage ) } return false; } +*/ #endif \ No newline at end of file diff --git a/Source/ResourceVersionInfo.h b/Source/ResourceVersionInfo.h index 6cdaca71..351bdd13 100644 --- a/Source/ResourceVersionInfo.h +++ b/Source/ResourceVersionInfo.h @@ -91,7 +91,7 @@ public: LANGID GetLangID(int Index); int GetCodePage(int Index); char *FindKey(LANGID LangID, int codepage, char *pKeyName); - bool IsValidCodePage(WORD codePage ); + //bool IsValidCodePage(WORD codePage ); }; #endif diff --git a/Source/build.cpp b/Source/build.cpp index bd705833..c3b5e0d1 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -415,7 +415,11 @@ int CEXEBuild::add_intstring(const int i) // returns offset in stringblock } // based on Dave Laundon's code +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS +int CEXEBuild::preprocess_string(char *out, const char *in, bool bUninstall) +#else int CEXEBuild::preprocess_string(char *out, const char *in) +#endif { #ifndef NSIS_SUPPORT_NAMED_USERVARS static const char VarNames[] = @@ -494,8 +498,12 @@ int CEXEBuild::preprocess_string(char *out, const char *in) *out++ = (char)255; } #else - // Test for characters that equals to control char of variable codes - if (i == VAR_CODES_START || i == 255 ) { + // Test for characters that equals to control char of variable codes or lang strings + if (i == VAR_CODES_START || +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + i == LANG_CODES_START || +#endif + i == 255 ) { *out++ = (char)255; } #endif @@ -549,6 +557,57 @@ int CEXEBuild::preprocess_string(char *out, const char *in) pUserVarName--; } } +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + if ( !bProceced && *p == '(' ) + { + int idx = -1; + char *cp = strdup(p+1); + char *pos = strchr(cp, ')'); + if (pos) + { + *pos = 0; + if ( !bUninstall ) + { + if (!strnicmp(cp,"un.",3)) { + warning("Installer language strings can't start with un. (%s)! (%s:%d)", p, curfilename, linecnt); + } + else + { + idx = GetUserString(cp); + if ( idx >= 0 ) + { + idx = -((int)(idx+1+(sizeof(common_strings)+sizeof(installer_strings))/sizeof(int))); + *out++=(unsigned int)LANG_CODES_START; // Next word is lang-string Identifier + *(WORD*)out=(WORD)idx; + out += sizeof(WORD); + p += strlen(cp)+2; + bProceced = true; + } + } + } + else + { + if (strnicmp(cp,"un.",3)) { + warning("Uninstaller language strings must start with un. (%s)! (%s:%d)", p, curfilename, linecnt); + } + else + { + idx = GetUserString(cp); + if ( idx >= 0 ) + { + idx = -((int)(idx+1+(sizeof(common_strings)+sizeof(uninstall_strings))/sizeof(int))); + *out++=(unsigned int)LANG_CODES_START; // Next word is lang-string Identifier + *(WORD*)out=(WORD)idx; + out += sizeof(WORD); + p += strlen(cp)+2; + bProceced = true; + } + } + } + } + free(cp); + } +#endif if ( bProceced ) continue; else @@ -556,6 +615,8 @@ int CEXEBuild::preprocess_string(char *out, const char *in) { char tbuf[64]; char cBracket = '\0'; + bool bDoWarning = true; + if ( *p == '[' ) cBracket = ']'; else if ( *p == '(' ) @@ -569,12 +630,19 @@ int CEXEBuild::preprocess_string(char *out, const char *in) if ( cBracket != 0 ) { if (strchr(tbuf,cBracket)) (strchr(tbuf,cBracket)+1)[0]=0; + if ( tbuf[0] == '{' && tbuf[strlen(tbuf)-1] == '}' ) + { + char *tstIfDefine = strdup(tbuf+1); + tstIfDefine[strlen(tstIfDefine)-1] = '\0'; + bDoWarning = definedlist.find(tstIfDefine) == NULL; + } } else { if (strstr(tbuf," ")) strstr(tbuf," ")[0]=0; } - warning("unknown variable \"%s\" detected, ignoring (%s:%d)",tbuf,curfilename,linecnt); + if ( bDoWarning ) + warning("unknown variable \"%s\" detected, ignoring (%s:%d)",tbuf,curfilename,linecnt); i = '$'; } } @@ -594,7 +662,11 @@ int CEXEBuild::add_string_main(const char *string, int process) // returns offse int idx = -1; char *cp = strdup(string+2); char *p = strchr(cp, ')'); +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + if (p && p[1] == '\0' ) { // if string is only a language str identifier +#else if (p) { +#endif *p = 0; if (!strnicmp(cp,"un.",3)) { warning("Installer language strings can't start with un. (%s)! (%s:%d)", string, curfilename, linecnt); @@ -610,7 +682,11 @@ int CEXEBuild::add_string_main(const char *string, int process) // returns offse if (!process) return build_strlist.add(string,2); char buf[4096]; +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + preprocess_string(buf,string, false); +#else preprocess_string(buf,string); +#endif return build_strlist.add(buf,2); } @@ -622,7 +698,11 @@ int CEXEBuild::add_string_uninst(const char *string, int process) // returns off int idx = -1; char *cp = strdup(string+2); char *p = strchr(cp, ')'); +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + if (p && p[1] == '\0' ) { // if string is only a language str identifier +#else if (p) { +#endif *p = 0; if (strnicmp(cp,"un.",3)) { warning("Uninstaller language strings must start with un. (%s)! (%s:%d)", string, curfilename, linecnt); @@ -638,7 +718,11 @@ int CEXEBuild::add_string_uninst(const char *string, int process) // returns off if (!process) return ubuild_strlist.add(string,2); char buf[4096]; +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + preprocess_string(buf,string, true); +#else preprocess_string(buf,string); +#endif return ubuild_strlist.add(buf,2); } diff --git a/Source/build.h b/Source/build.h index d4f05a48..91f22166 100644 --- a/Source/build.h +++ b/Source/build.h @@ -113,7 +113,11 @@ class CEXEBuild { void restore_line_predefine(char *); #endif int parseScript(); +#ifdef NSIS_FIX_DEFINES_IN_STRINGS + void ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist, bool bIgnoreDefines = false); +#else void ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist); +#endif int doParse(const char *str); int doCommand(int which_token, LineParser &line); int do_add_file(const char *lgss, int attrib, int recurse, int linecnt, int *total_files, const char *name_override=0, int generatecode=1, int *data_handle=0, int rec_depth=0); @@ -144,7 +148,11 @@ class CEXEBuild { int add_intstring(const int i); // returns offset in stringblock int add_string_main(const char *string, int process=1); // returns offset (in string table) int add_string_uninst(const char *string, int process=1); // returns offset (in string table) +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + int preprocess_string(char *out, const char *in, bool bUninstall); +#else int preprocess_string(char *out, const char *in); +#endif int make_sure_not_in_secorfunc(const char *str); diff --git a/Source/exehead/config.h b/Source/exehead/config.h index 25f3e8b7..b77d13c4 100644 --- a/Source/exehead/config.h +++ b/Source/exehead/config.h @@ -210,6 +210,11 @@ // NSIS_SUPPORT_VERSION_INFO enables support for version information on final exe #define NSIS_SUPPORT_VERSION_INFO +// NSIS_SUPPORT_LANG_IN_STRINGS enables support for language strings inside other strings +//#define NSIS_SUPPORT_LANG_IN_STRINGS + +// NSIS_FIX_DEFINES_IN_STRINGS fix defines inside defines and handles chars $ perfectly +//#define NSIS_FIX_DEFINES_IN_STRINGS // Added by Ximon Eighteen 5th August 2002 // If this is uncommented the following changes/new features are diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 0a483f61..86190e17 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -106,7 +106,11 @@ static int *parms; static int NSISCALL process_string_fromparm_toint(int id_) { +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + return myatoi(process_string(GetStringFromStringTab(parms[id_]), 0)); +#else return myatoi(process_string(GetStringFromStringTab(parms[id_]))); +#endif } // NB - USE CAUTION when rearranging code to make use of the new return value of diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index 9af588cc..1fedfd74 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -524,6 +524,10 @@ DWORD NSISCALL SetSelfFilePointer(LONG lDistanceToMove, DWORD dwMoveMethod); #endif #endif +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + #define LANG_CODES_START 251 +#endif + union installer_flags { struct { int autoclose; diff --git a/Source/exehead/util.c b/Source/exehead/util.c index 8372cc4c..0d30d5b9 100644 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -333,7 +333,11 @@ char ps_tmpbuf[NSIS_MAX_STRLEN*2]; char * NSISCALL process_string_fromtab(char *out, int offs) { +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + char *p=process_string(GetStringFromStringTab(offs), 0); +#else char *p=process_string(GetStringFromStringTab(offs)); +#endif if (!out) return p; return lstrcpyn(out,p,NSIS_MAX_STRLEN); } @@ -394,9 +398,17 @@ int NSISCALL mystrlen(const char *in) } // Dave Laundon's simplified process_string +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS +char * NSISCALL process_string(const char *in, int iStartIdx ) +#else char * NSISCALL process_string(const char *in) +#endif { +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + char *out = ps_tmpbuf+iStartIdx; +#else char *out = ps_tmpbuf; +#endif while (*in && out - ps_tmpbuf < NSIS_MAX_STRLEN) { int nVarIdx = (unsigned char)*in++; @@ -525,11 +537,7 @@ char * NSISCALL process_string(const char *in) { *out++ = *in++; } - else if (nVarIdx != VAR_CODES_START) - { - *out++ = nVarIdx; - } - else + else if (nVarIdx == VAR_CODES_START) { DWORD f; static char smwcvesf[]="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; @@ -613,6 +621,19 @@ char * NSISCALL process_string(const char *in) } out+=mystrlen(out); } // == VAR_CODES_START +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS + else if ( nVarIdx == LANG_CODES_START ) + { + char *p; + nVarIdx = *(short*)in; in+=sizeof(WORD); + p = process_string(GetStringFromStringTab(nVarIdx), out-ps_tmpbuf); + out+=mystrlen(out); + } +#endif + else // Normal char + { + *out++ = nVarIdx; + } #endif } // while *out = 0; diff --git a/Source/exehead/util.h b/Source/exehead/util.h index 3ea67cbc..ced2271e 100644 --- a/Source/exehead/util.h +++ b/Source/exehead/util.h @@ -1,7 +1,11 @@ #include "config.h" extern char ps_tmpbuf[NSIS_MAX_STRLEN*2]; +#ifdef NSIS_SUPPORT_LANG_IN_STRINGS +char * NSISCALL process_string(const char *in, int iStartIdx); +#else char * NSISCALL process_string(const char *in); +#endif char * NSISCALL process_string_fromtab(char *out, int offs); void NSISCALL myRegGetStr(HKEY root, const char *sub, const char *name, char *out); int NSISCALL myatoi(char *s); diff --git a/Source/script.cpp b/Source/script.cpp index 81b0c616..e13bb64c 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -344,7 +344,11 @@ parse_again: return PS_OK; } +#ifdef NSIS_FIX_DEFINES_IN_STRINGS +void CEXEBuild::ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist, bool bIgnoreDefines /*= false*/) +#else void CEXEBuild::ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist) +#endif { // convert $\r, $\n to their literals // preprocessor replace ${VAR} with whatever value @@ -396,7 +400,11 @@ void CEXEBuild::ps_addtoline(const char *str, GrowBuf &linedata, StringList &his if (*t == '}' && bn-- == 0) break; t=CharNext(t); } - if (*t && t!=s) + if (*t && t!=s +#ifdef NSIS_FIX_DEFINES_IN_STRINGS + && !bIgnoreDefines +#endif + ) { *t=0; // check for defines inside the define name - ${bla${blo}} @@ -409,12 +417,47 @@ void CEXEBuild::ps_addtoline(const char *str, GrowBuf &linedata, StringList &his in+=strlen(s)+2; add=0; hist.add((char*)defname.get(),0); +#ifdef NSIS_FIX_DEFINES_IN_STRINGS + ps_addtoline(t,linedata,hist, true); +#else ps_addtoline(t,linedata,hist); +#endif hist.delbypos(hist.find((char*)defname.get(),0)); } } free(s); } +#ifdef NSIS_FIX_DEFINES_IN_STRINGS + else if (in[0] == '$' ) + { + if ( in[1] == '{' ) // Found $$ before - Don't replace this define + { + char *s=strdup(in+2); + char *t=s; + unsigned int bn = 0; + while (*t) + { + if (*t == '{') bn++; + if (*t == '}' && bn-- == 0) break; + t=CharNext(t); + } + if (*t && t!=s ) + { + *t=0; + // add text unchanged + GrowBuf defname; + ps_addtoline(s,defname,hist); + in++; + } + free(s); + } + else + { + linedata.add((void*)&c,1); + in++; + } + } +#endif } if (add) linedata.add((void*)&c,1); } @@ -4570,9 +4613,13 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) #ifdef NSIS_SUPPORT_VERSION_INFO case TOK_VI_ADDKEY: { - LANGID LangID = line.gettoken_int(1); - char *pKey = line.gettoken_str(2); - char *pValue = line.gettoken_str(3); + LANGID LangID=0; + int a = 1; + if (!strnicmp(line.gettoken_str(a),"/LANG=",6)) + LangID=atoi(line.gettoken_str(a++)+6); + if (line.getnumtokens()!=a+2) PRINTHELP(); + char *pKey = line.gettoken_str(a); + char *pValue = line.gettoken_str(a+1); if ( !(*pKey) ) { ERROR_MSG("Error: empty name for version info key!\n"); @@ -4580,10 +4627,11 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) } else { - SCRIPT_MSG("%s: \"%s\" \"%s\" \"%s\"\n", line.gettoken_str(0), line.gettoken_str(1), line.gettoken_str(2), line.gettoken_str(3)); + SCRIPT_MSG("%s: \"%s\" \"%s\"\n", line.gettoken_str(0), line.gettoken_str(a), line.gettoken_str(a+1)); + LANGID lReaded = LangID; StringTable *strTable = GetTable(LangID); - if ( line.gettoken_int(1) == 0 && !strTable->nlf ) - warning("%s: \"%s\" language not loaded, using default \"1033-English\". (%s:%d)", line.gettoken_str(0), line.gettoken_str(1), curfilename,linecnt); + if ( a > 1 && lReaded == 0 ) + warning("%s: %s language not loaded, using default \"1033-English\". (%s:%d)", line.gettoken_str(0), line.gettoken_str(1), curfilename,linecnt); if ( rVersionInfo.SetKeyValue(LangID, strTable->nlf ? strTable->nlf->m_uCodePage : 1252 /*English US*/, pKey, pValue) ) { ERROR_MSG("%s: \"%s\" \"%04d-%s\" already defined!\n",line.gettoken_str(0), line.gettoken_str(2), LangID, strTable->nlf ? strTable->nlf->m_szName : LangID == 1033 ? "English" : "???"); diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 77f0b3f8..5eecc84b 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -230,8 +230,8 @@ static tokenType tokenlist[TOK__LAST] = // Added by ramon 3 jun 2003 {TOK_DEFVAR,"dim",1,0,"VarName"}, // Added by ramon 6 jun 2003 -{TOK_VI_ADDKEY,"VIAddVersionKey", 3, 0, "lang_id keyname value"}, -{TOK_VI_SETPRODUCTVERSION,"VIProductVersion", 1, 0, "[version string X.X.X.X]"}, +{TOK_VI_ADDKEY,"VIAddVersionKey", 2, 1, "[/LANG=lang_id] keyname value"}, +{TOK_VI_SETPRODUCTVERSION,"VIProductVersion", 1, 0, "[version_string_X.X.X.X]"}, }; void CEXEBuild::print_help(char *commandname)