diff --git a/Docs/src/history.but b/Docs/src/history.but index 522feccb..c9aa8bd5 100644 --- a/Docs/src/history.but +++ b/Docs/src/history.but @@ -20,9 +20,9 @@ Released on ??? ??rd, 20?? \S2{} Minor Changes -\b Added \R{intptrcmp}{IntPtrCmp}, IntPtrCmpU, Int64Cmp and Int64CmpU +\b Added \R{intptrcmp}{IntPtrCmp}, IntPtrCmpU, and \R{intptrop}{IntPtrOp} -\b Added \R{intptrop}{IntPtrOp} +\b Added Int64Cmp, Int64CmpU and Int64Fmt (64-bit only) \b Added IntOp and System::Int64Op >>> operator diff --git a/Docs/src/int.but b/Docs/src/int.but index 57ac9964..b0f247e0 100644 --- a/Docs/src/int.but +++ b/Docs/src/int.but @@ -9,6 +9,16 @@ Formats the number in "numberstring" using the format "format", and sets the out \c IntFmt $0 "0x%08X" 195948557 \c IntFmt $0 "%c" 0x41 +\S2{int64fmt} Int64Fmt + +\c user_var(output) format numberstring + +\NsisFuncReq64 + +\c Int64Fmt $0 "%I64x" 244837743786702 + +\# InternalNote: There is no IntPtrFmt instruction because "%p" is 2000+ and "%Ix" is XP+. Consequently, all code needs to check ${NSIS_PTR_SIZE}. + \S2{intop} IntOp \c user_var(output) value1 OP [value2] diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 1e0c27bb..c78708ef 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -683,7 +683,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) #ifdef NSIS_SUPPORT_INTOPTS case EW_INTCMP: { - UINT supp64=sizeof(void*) > 4, opu=supp64 ? (BYTE) parm5 : parm5, op64=supp64 ? (INT16) parm5 < 0 : FALSE; + UINT supp64=sizeof(void*) > 4, opu=supp64 ? (BYTE) parm5 : parm5, op64=supp64 ? (SHORT) 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) { @@ -735,9 +735,8 @@ static int NSISCALL ExecuteEntry(entry *entry_) break; case EW_INTFMT: { TCHAR *buf0=GetStringFromParm(0x01); - wsprintf(var0, - buf0, - GetIntPtrFromParm(2)); // TODO: BUGBUG64: This sign-extends from INT32 to INT64, do we want that? + INT_PTR val=GetIntPtrFromParm(2), op64=sizeof(void*) > 4 && parm3; + wsprintf(var0,buf0,op64 ? val : (UINT)val); } break; #endif//NSIS_SUPPORT_INTOPTS diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index 22f09888..82de7923 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -98,7 +98,7 @@ enum #ifdef NSIS_SUPPORT_INTOPTS 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] + EW_INTFMT, // IntFmt: 4 [output, format, input, 64-bit] #endif #ifdef NSIS_SUPPORT_STACK EW_PUSHPOP, // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch] diff --git a/Source/exehead/util.c b/Source/exehead/util.c index 1aa46f79..30ebaee0 100644 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -507,7 +507,7 @@ HRESULT NSISCALL UTF16LEBOM(HANDLE h, INT_PTR ForWrite) if (0 == orgpos) { BYTE bom[2]; - if (myReadFile(h, bom, 2) && (0xfeff == *(UINT16*) &bom[0])) + if (myReadFile(h, bom, 2) && (0xfeff == *(USHORT*) &bom[0])) { return S_OK; } diff --git a/Source/script.cpp b/Source/script.cpp index 183e79ab..8ecb747a 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -300,7 +300,7 @@ parse_again: ERROR_MSG(_T("Plugin%") NPRIs _T(" not found, cannot call %") NPRIs _T("\n"),m_pPlugins && m_pPlugins->IsKnownPlugin(tokstr0) ? _T(" function") : _T(""),tokstr0); else #endif - ERROR_MSG(_T("Invalid command: %") NPRIs _T("\n"),tokstr0); + ERROR_MSG(_T("Invalid command: \"%") NPRIs _T("\"\n"),tokstr0); return PS_ERROR; } } @@ -4170,18 +4170,20 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) SCRIPT_MSG(_T("%") NPRIs _T(": %") NPRIs _T("=%") NPRIs _T("%") NPRIs _T("%") NPRIs _T("\n"),cmdname,line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); } return add_entry(&ent); - case TOK_INTFMT: + case TOK_INTFMT: case TOK_INT64FMT: ent.which=EW_INTFMT; ent.offsets[0]=GetUserVarIndex(line, 1); if (ent.offsets[0]<0) PRINTHELP() ent.offsets[1]=add_string(line.gettoken_str(2)); ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=which_token == TOK_INT64FMT; + if (ent.offsets[3] && !is_target_64bit()) return (ERROR_MSG(_T("%") NPRIns _T("\n"), "Instruction only supported by 64-bit targets!"), PS_ERROR); 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: 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); + if (!t64 && o64) return (ERROR_MSG(_T("%") NPRIns _T("\n"), "Instruction only supported by 64-bit targets!"), PS_ERROR); ent.which=EW_INTCMP; ent.offsets[0]=add_string(line.gettoken_str(1)); ent.offsets[1]=add_string(line.gettoken_str(2)); @@ -4194,8 +4196,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) } #else case TOK_INTOP: case TOK_INTPTROP: + case TOK_INTFMT: case TOK_INT64FMT: case TOK_INTCMP: case TOK_INTCMPU: case TOK_INT64CMP: case TOK_INT64CMPU: case TOK_INTPTRCMP: case TOK_INTPTRCMPU: - case TOK_INTFMT: ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_SUPPORT_INTOPTS not defined.\n"), line.gettoken_str(0)); return PS_ERROR; #endif //~ NSIS_SUPPORT_INTOPTS @@ -5113,7 +5115,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) default: break; } - ERROR_MSG(_T("Error: doCommand: Invalid token \"%") NPRIs _T("\".\n"),line.gettoken_str(0)); + ERROR_MSG(_T("Invalid command \"%") NPRIs _T("\"\n"),line.gettoken_str(0)); return PS_ERROR; } diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 1e89779c..a9735c76 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -131,6 +131,7 @@ static tokenType tokenlist[TOK__LAST] = {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_INT64FMT,_T("Int64Fmt"),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}, {TOK_LANGSTRING,_T("LangString"),3,0,_T("[un.]name lang_id|0 string"),TP_GLOBAL}, @@ -319,15 +320,15 @@ static tokenType tokenlist[TOK__LAST] = const TCHAR* CEXEBuild::get_commandtoken_name(int tok) { - for (int x = 0; x < TOK__LAST; ++x) + for (UINT x = 0; x < TOK__LAST; ++x) if (tokenlist[x].id==tok) return tokenlist[x].name; return 0; } void CEXEBuild::print_help(const TCHAR *commandname) { - int x; - for (x = 0; x < TOK__LAST; x ++) + UINT x; + for (x = 0; x < TOK__LAST; ++x) { if (!commandname || !_tcsicmp(tokenlist[x].name,commandname)) { @@ -376,7 +377,7 @@ bool CEXEBuild::is_unsafe_pp_token(int tkid) int CEXEBuild::get_commandtoken(const TCHAR *s, int *np, int *op, int *pos) { - for (int x = 0; x < TOK__LAST; x ++) + for (UINT x = 0; x < TOK__LAST; ++x) if (!_tcsicmp(tokenlist[x].name,s)) { *np=tokenlist[x].num_parms; diff --git a/Source/tokens.h b/Source/tokens.h index 370cd81a..865c86e4 100644 --- a/Source/tokens.h +++ b/Source/tokens.h @@ -246,6 +246,7 @@ enum TOK_INTPTRCMP, TOK_INTPTRCMPU, TOK_INTFMT, + TOK_INT64FMT, TOK_ENUMREGKEY, TOK_ENUMREGVAL, TOK_PUSH,