diff --git a/Docs/src/config.but b/Docs/src/config.but index 35bdfd93..e00c03c5 100644 --- a/Docs/src/config.but +++ b/Docs/src/config.but @@ -12,6 +12,8 @@ \define{NsisFuncReqU} This function is only available when building a \R{intro-unicode}{Unicode installer}. +\define{NsisFuncReq64} This function is only available when building a 64-bit installer. + \define{NsisACPcp} system default ANSI codepage (ACP) \define{NsisInputCharset} ACP|OEM|CP#|UTF8|UTF16 diff --git a/Docs/src/flowcontrol.but b/Docs/src/flowcontrol.but index 5c48a144..07a6b039 100644 --- a/Docs/src/flowcontrol.but +++ b/Docs/src/flowcontrol.but @@ -185,6 +185,34 @@ Compares two integers val1 and val2. If val1 and val2 are equal, Gotos jump_if_e Same as \R{intcmp}{IntCmp}, but treats the values as unsigned integers. +\S2{int64cmp} Int64Cmp + +\c val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more] + +Same as \R{intcmp}{IntCmp}, but treats the values as 64-bit integers. + +\NsisFuncReq64 + +\S2{int64cmpu} Int64CmpU + +\c val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more] + +Same as \R{intcmp}{IntCmp}, but treats the values as 64-bit unsigned integers. + +\NsisFuncReq64 + +\S2{intptrcmp} IntPtrCmp + +\c val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more] + +Same as \R{intcmp}{IntCmp}, but treats the values as pointer sized integers. + +\S2{intptrcmpu} IntPtrCmpU + +\c val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more] + +Same as \R{intcmp}{IntCmp}, but treats the values as pointer sized unsigned integers. + \S2{messagebox} MessageBox \c mb_option_list messagebox_text [/SD return] [return_check jumpto [return_check_2 jumpto_2]] diff --git a/Docs/src/history.but b/Docs/src/history.but index bd453a80..522feccb 100644 --- a/Docs/src/history.but +++ b/Docs/src/history.but @@ -20,6 +20,8 @@ Released on ??? ??rd, 20?? \S2{} Minor Changes +\b Added \R{intptrcmp}{IntPtrCmp}, IntPtrCmpU, Int64Cmp and Int64CmpU + \b Added \R{intptrop}{IntPtrOp} \b Added IntOp and System::Int64Op >>> operator diff --git a/Include/Util.nsh b/Include/Util.nsh index 620a4410..4e905c0c 100644 --- a/Include/Util.nsh +++ b/Include/Util.nsh @@ -46,11 +46,7 @@ !define Int64Op '!insertmacro Int64Op ' !define IntPtrOp '!insertmacro IntPtrOp ' !macro Int32Op r a o b -!if ${NSIS_PTR_SIZE} <= 4 - IntOp `${r}` `${a}` `${o}` ${b} -!else - !error "Int32Op not implemented" -!endif +IntOp `${r}` `${a}` `${o}` ${b} !macroend !macro Int64Op r a o b !echo "Int64Op ${r}=${a}${o}${b}" @@ -67,13 +63,10 @@ IntPtrOp `${r}` `${a}` `${o}` `${b}` !define Int64Cmp '!insertmacro Int64Cmp ' !define IntPtrCmp '!insertmacro IntPtrCmp ' !macro Int32Cmp a b jeek jles jgtr -!if ${NSIS_PTR_SIZE} <= 4 - IntCmp `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` -!else - !error "Int32Cmp not implemented" -!endif +IntCmp `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` !macroend !macro Int64Cmp a b jeek jles jgtr +!if ${NSIS_PTR_SIZE} <= 4 !ifmacrondef _LOGICLIB_TEMP !include LogicLib.nsh !endif @@ -82,24 +75,19 @@ IntPtrOp `${r}` `${a}` `${o}` `${b}` ${IfThen} ${a} L= ${b} ${|} Goto ${jeek} ${|} !insertmacro _L< ${a} ${b} `${jles}` `${jgtr}` !verbose pop +!else +Int64Cmp `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` +!endif !macroend !macro IntPtrCmp a b jeek jles jgtr -!if ${NSIS_PTR_SIZE} <= 4 - ${Int32Cmp} `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` -!else - ${Int64Cmp} `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` -!endif +IntPtrCmp `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` !macroend !define Int32CmpU '!insertmacro Int32CmpU ' !define Int64CmpU '!insertmacro Int64CmpU ' !define IntPtrCmpU '!insertmacro IntPtrCmpU ' !macro Int32CmpU a b jeek jles jgtr -!if ${NSIS_PTR_SIZE} <= 4 - IntCmpU `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` -!else - !error "Int32CmpU not implemented" -!endif +IntCmpU `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` !macroend !macro Int64CmpUHelper ; This macro performs "$_LOGICLIB_TEMP = a < b ? -1 : a > b ? 1 : 0" but System::Int64Op does not support unsigned operations so we have to perform multiple steps @@ -148,6 +136,7 @@ Pop $1 Pop $2 !macroend !macro Int64CmpU a b jeek jles jgtr +!if ${NSIS_PTR_SIZE} <= 4 !echo "Int64CmpU ${a}:${b} =${jeek}, <${jles}, >${jgtr}" !verbose push 2 Push `${a}` @@ -155,13 +144,12 @@ Push `${b}` !insertmacro CallArtificialFunction Int64CmpUHelper IntCmp $_LOGICLIB_TEMP 0 `${jeek}` `${jles}` `${jgtr}` !verbose pop +!else +Int64CmpU `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` +!endif !macroend !macro IntPtrCmpU a b jeek jles jgtr -!if ${NSIS_PTR_SIZE} <= 4 - ${Int32CmpU} `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` -!else - ${Int64CmpU} `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` -!endif +IntPtrCmpU `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}` !macroend diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 183dadc2..1e0c27bb 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -683,18 +683,27 @@ static int NSISCALL ExecuteEntry(entry *entry_) #ifdef NSIS_SUPPORT_INTOPTS case EW_INTCMP: { - int v,v2; - v=GetIntFromParm(0); - v2=GetIntFromParm(1); - if (!parm5) { - // signed - if (vv2) return parm4; + UINT supp64=sizeof(void*) > 4, opu=supp64 ? (BYTE) parm5 : parm5, op64=supp64 ? (INT16) parm5 < 0 : FALSE; + INT_PTR v=GetIntPtrFromParm(0), v2=GetIntPtrFromParm(1); // Note: This needs to be INT64 if supp64 is ever set to true for 32-bit builds! + if (!opu) { // signed: + if (op64) { + if ((INT64)v < (INT64)v2) return parm3; + if ((INT64)v > (INT64)v2) return parm4; + } + else { + if ((signed int)v < (signed int)v2) return parm3; + if ((signed int)v > (signed int)v2) return parm4; + } } - else { - // unsigned - if ((unsigned int)v<(unsigned int)v2) return parm3; - if ((unsigned int)v>(unsigned int)v2) return parm4; + else { // unsigned: + if (op64) { + if ((UINT64)v < (UINT64)v2) return parm3; + if ((UINT64)v > (UINT64)v2) return parm4; + } + else { + if ((unsigned int)v < (unsigned int)v2) return parm3; + if ((unsigned int)v > (unsigned int)v2) return parm4; + } } } return parm2; diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index 7e748845..22f09888 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -96,7 +96,7 @@ enum EW_READENVSTR, // ReadEnvStr/ExpandEnvStrings: 3 [output, string_with_env_variables, IsRead] #endif #ifdef NSIS_SUPPORT_INTOPTS - EW_INTCMP, // IntCmp: 6 [val1, val2, equal, val1val2, unsigned?] + EW_INTCMP, // IntCmp: 6 [val1, val2, equal, val1val2, flags] where flags: bit 0x01 is set for unsigned operations and bit 0x8000 is set for 64-bit operations EW_INTOP, // IntOp: 4 [output, input1, input2, op] where op: 0=add, 1=sub, 2=mul, 3=div, 4=bor, 5=band, 6=bxor, 7=bnot input1, 8=lor, 9=land 10=mod, 11=shl, 12=sar, 13=shr (bneg is implemented with bxor in compiler) EW_INTFMT, // IntFmt: [output, format, input] #endif diff --git a/Source/script.cpp b/Source/script.cpp index 87ce291d..183e79ab 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -87,6 +87,15 @@ static LANGID ParseLangId(const TCHAR*Str) return _T('0') == p[0] && _T('x') == (p[1]|32) ? LineParser::parse_int(Str) : _ttoi(Str); } +LANGID CEXEBuild::ParseLangIdParameter(const LineParser&line, int token) +{ + int succ, lid = line.gettoken_int(token, &succ); + if (!lid) lid = last_used_lang; + if (!succ) + warning_fl(DW_BAD_LANGID, _T("\"%") NPRIs _T("\" is not a valid language id, using language id %u!"), line.gettoken_str(token), lid); + return lid; +} + int CEXEBuild::process_script(NIStream&Strm, const TCHAR *filename) { NStreamLineReader linereader(Strm); @@ -4169,23 +4178,24 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) ent.offsets[2]=add_string(line.gettoken_str(3)); SCRIPT_MSG(_T("IntFmt: %") NPRIs _T("->%") NPRIs _T(" (fmt:%") NPRIs _T(")\n"),line.gettoken_str(3),line.gettoken_str(1),line.gettoken_str(2)); return add_entry(&ent); - case TOK_INTCMP: - case TOK_INTCMPU: - ent.which=EW_INTCMP; - ent.offsets[0]=add_string(line.gettoken_str(1)); - ent.offsets[1]=add_string(line.gettoken_str(2)); - ent.offsets[5]=which_token == TOK_INTCMPU; - if (process_jump(line,3,&ent.offsets[2]) || - process_jump(line,4,&ent.offsets[3]) || - process_jump(line,5,&ent.offsets[4])) PRINTHELP() - SCRIPT_MSG(_T("%") NPRIs _T(" %") NPRIs _T(":%") NPRIs _T(" equal=%") NPRIs _T(", < %") NPRIs _T(", > %") NPRIs _T("\n"),line.gettoken_str(0), - line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5)); - return add_entry(&ent); + case TOK_INTCMP: case TOK_INTCMPU: case TOK_INT64CMP: case TOK_INT64CMPU: case TOK_INTPTRCMP: case TOK_INTPTRCMPU: + { + int t64 = is_target_64bit(), o32 = TOK_INTCMP == which_token || TOK_INTCMPU == which_token, o64 = TOK_INT64CMP == which_token || TOK_INT64CMPU == which_token; + if (!t64 && o64) return (ERROR_MSG(_T("Instruction only supported by 64-bit targets!\n")), PS_ERROR); + ent.which=EW_INTCMP; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[5]=(which_token == TOK_INTCMPU || which_token == TOK_INT64CMPU || which_token == TOK_INTPTRCMPU) | (t64 && !o32 ? 0x8000 : 0); + if (process_jump(line,3,&ent.offsets[2]) | process_jump(line,4,&ent.offsets[3]) | process_jump(line,5,&ent.offsets[4])) + PRINTHELP() + SCRIPT_MSG(_T("%") NPRIs _T(" %") NPRIs _T(":%") NPRIs _T(" equal=%") NPRIs _T(", < %") NPRIs _T(", > %") NPRIs _T("\n"),line.gettoken_str(0), + line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5)); + return add_entry(&ent); + } #else - case TOK_INTOP: - case TOK_INTCMP: + case TOK_INTOP: case TOK_INTPTROP: + case TOK_INTCMP: case TOK_INTCMPU: case TOK_INT64CMP: case TOK_INT64CMPU: case TOK_INTPTRCMP: case TOK_INTPTRCMPU: case TOK_INTFMT: - case TOK_INTCMPU: ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_SUPPORT_INTOPTS not defined.\n"), line.gettoken_str(0)); return PS_ERROR; #endif //~ NSIS_SUPPORT_INTOPTS @@ -5427,12 +5437,3 @@ int CEXEBuild::do_add_file_create_dir(const tstring& local_dir, const tstring& d return PS_OK; } #endif - -LANGID CEXEBuild::ParseLangIdParameter(const LineParser&line, int token) -{ - int succ, lid = line.gettoken_int(token, &succ); - if (!lid) lid = last_used_lang; - if (!succ) - warning_fl(DW_BAD_LANGID, _T("\"%") NPRIs _T("\" is not a valid language id, using language id %u!"), line.gettoken_str(token), lid); - return lid; -} diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 3cf89a37..1e89779c 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -126,6 +126,10 @@ static tokenType tokenlist[TOK__LAST] = {TOK_INTPTROP,_T("IntPtrOp"),3,1,_T("$(user_var: result) val1 OP [val2]"),TP_CODE}, {TOK_INTCMP,_T("IntCmp"),3,2,_T("val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]"),TP_CODE}, {TOK_INTCMPU,_T("IntCmpU"),3,2,_T("val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]"),TP_CODE}, +{TOK_INT64CMP,_T("Int64Cmp"),3,2,_T("val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]"),TP_CODE}, +{TOK_INT64CMPU,_T("Int64CmpU"),3,2,_T("val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]"),TP_CODE}, +{TOK_INTPTRCMP,_T("IntPtrCmp"),3,2,_T("val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]"),TP_CODE}, +{TOK_INTPTRCMPU,_T("IntPtrCmpU"),3,2,_T("val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]"),TP_CODE}, {TOK_INTFMT,_T("IntFmt"),3,0,_T("$(user_var: output) format_string input"),TP_CODE}, {TOK_ISWINDOW,_T("IsWindow"),2,1,_T("hwnd jump_if_window [jump_if_not_window]"),TP_CODE}, {TOK_GOTO,_T("Goto"),1,0,_T("label"),TP_CODE}, diff --git a/Source/tokens.h b/Source/tokens.h index 7549374c..370cd81a 100644 --- a/Source/tokens.h +++ b/Source/tokens.h @@ -241,6 +241,10 @@ enum TOK_INTPTROP, TOK_INTCMP, TOK_INTCMPU, + TOK_INT64CMP, + TOK_INT64CMPU, + TOK_INTPTRCMP, + TOK_INTPTRCMPU, TOK_INTFMT, TOK_ENUMREGKEY, TOK_ENUMREGVAL,