From 67d0b165b1dfea00ae4b669fc55a447a4614763e Mon Sep 17 00:00:00 2001 From: anders_k Date: Tue, 6 Dec 2011 19:14:45 +0000 Subject: [PATCH] Added !if S==, S!=, = and <> compare ops and hex/int/float parsing support git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6198 212acab6-be3b-0410-9dea-997c60f758d6 --- Docs/src/defines.but | 4 ++-- Source/lineparse.cpp | 15 +++++++++++++-- Source/lineparse.h | 1 + Source/script.cpp | 40 +++++++++++++++++++++++++++------------- Source/tokens.cpp | 2 +- 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/Docs/src/defines.but b/Docs/src/defines.but index be01f5cc..c442816f 100644 --- a/Docs/src/defines.but +++ b/Docs/src/defines.but @@ -64,10 +64,10 @@ The opposite of !ifdef. The lines will be compiled when the gflag has not been d \c [!] /FileExists "c:\path\file.exe" This command, when paired with an !endif command, will tell the compiler whether or not to compile the lines in between the two lines. If value is non-zero, or the comparison of value and value2 depending on the operator results in true, the contained lines will be compiled. Otherwise, they will be skipped. -op can be either == or != (string comparison), <=, < > or >= (float comparison), & (bitwise AND comparison), && or || (boolean comparison). +op can be either == or != (case-insensitive string comparison), S== or S!= (case-sensitive string comparison), =, <>, <=, <, > or >= (int/hex/float comparison), & (bitwise AND comparison), && or || (boolean comparison). If [!] is set, return value will be switched from true to false and vice versa. -\c !if 1 < 2 +\c !if 1 < 0x2 \c !echo "1 is smaller than 2!!" \c !else if ! 3.1 > 1.99 \c !error "this line should never appear" diff --git a/Source/lineparse.cpp b/Source/lineparse.cpp index 8a824c5e..624a0156 100644 --- a/Source/lineparse.cpp +++ b/Source/lineparse.cpp @@ -88,6 +88,7 @@ double LineParser::gettoken_float(int token, int *success/*=0*/) if (success) { TCHAR *t=m_tokens[token]; + if (_T('-') == *t || _T('+') == *t) ++t; *success=*t?1:0; while (*t) { @@ -108,12 +109,22 @@ int LineParser::gettoken_int(int token, int *success/*=0*/) } TCHAR *tmp; int l; - if (m_tokens[token][0] == _T('-')) l=_tcstol(m_tokens[token],&tmp,0); - else l=(int)_tcstoul(m_tokens[token],&tmp,0); + if (_T('-') == m_tokens[token][0]) + l=_tcstol(m_tokens[token],&tmp,0); + else + l=(int)_tcstoul(m_tokens[token],&tmp,0); if (success) *success=! (int)(*tmp); return l; } +double LineParser::gettoken_number(int token, int *success/*=0*/) +{ + const TCHAR*str=gettoken_str(token); + if (_T('-') == *str || _T('+') == *str) ++str; + if (_T('0') == str[0] && _T('x') == (str[1]|32)) return gettoken_int(token,success); + return gettoken_float(token,success); +} + TCHAR* LineParser::gettoken_str(int token) { token+=m_eat; diff --git a/Source/lineparse.h b/Source/lineparse.h index 76954021..6b3f6d81 100644 --- a/Source/lineparse.h +++ b/Source/lineparse.h @@ -34,6 +34,7 @@ class LineParser { void eattoken(); double gettoken_float(int token, int *success=0); int gettoken_int(int token, int *success=0); + double gettoken_number(int token, int *success=0); TCHAR *gettoken_str(int token); int gettoken_enum(int token, const TCHAR *strlist); // null seperated list diff --git a/Source/script.cpp b/Source/script.cpp index c02d0c30..15b193fd 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -489,8 +489,7 @@ parse_again: istrue = line.gettoken_int(1); else if (line.getnumtokens() == 3) { - if (!_tcsicmp(line.gettoken_str(1),_T("/fileexists"))) - { + if (!_tcsicmp(line.gettoken_str(1),_T("/fileexists"))) { TCHAR *fc = my_convert(line.gettoken_str(2)); tstring dir = get_dir_name(fc), spec = get_file_name(fc); my_convert_free(fc); @@ -515,32 +514,47 @@ parse_again: } else if (line.getnumtokens() == 4) { - mod = line.gettoken_enum(2,_T("=\0==\0!=\0<=\0<\0>\0>=\0&\0&&\0|\0||\0")); - + mod = line.gettoken_enum(2, + _T("==\0!=\0S==\0S!=\0") + _T("=\0<>\0<=\0<\0>\0>=\0") + _T("&\0&&\0|\0||\0") + ); + + int cnv1 = 1, cnv2 = 1; switch(mod) { case 0: - case 1: istrue = _tcsicmp(line.gettoken_str(1),line.gettoken_str(3)) == 0; break; - case 2: + case 1: istrue = _tcsicmp(line.gettoken_str(1),line.gettoken_str(3)) != 0; break; + case 2: + istrue = _tcscmp(line.gettoken_str(1),line.gettoken_str(3)) == 0; break; case 3: - istrue = line.gettoken_float(1) <= line.gettoken_float(3); break; + istrue = _tcscmp(line.gettoken_str(1),line.gettoken_str(3)) != 0; break; case 4: - istrue = line.gettoken_float(1) < line.gettoken_float(3); break; + istrue = line.gettoken_number(1,&cnv1) == line.gettoken_number(3,&cnv2); break; case 5: - istrue = line.gettoken_float(1) > line.gettoken_float(3); break; + istrue = line.gettoken_number(1,&cnv1) != line.gettoken_number(3,&cnv2); break; case 6: - istrue = line.gettoken_float(1) >= line.gettoken_float(3); break; + istrue = line.gettoken_number(1,&cnv1) <= line.gettoken_number(3,&cnv2); break; case 7: - istrue = (line.gettoken_int(1) & line.gettoken_int(3)) != 0; break; + istrue = line.gettoken_number(1,&cnv1) < line.gettoken_number(3,&cnv2); break; case 8: - istrue = line.gettoken_int(1) && line.gettoken_int(3); break; + istrue = line.gettoken_number(1,&cnv1) > line.gettoken_number(3,&cnv2); break; case 9: + istrue = line.gettoken_number(1,&cnv1) >= line.gettoken_number(3,&cnv2); break; case 10: - istrue = line.gettoken_int(1) || line.gettoken_int(3); break; + istrue = (line.gettoken_int(1,&cnv1) & line.gettoken_int(3,&cnv2)) != 0; break; + case 11: + istrue = line.gettoken_int(1,&cnv1) && line.gettoken_int(3,&cnv2); break; + case 12: + case 13: + istrue = line.gettoken_int(1,&cnv1) || line.gettoken_int(3,&cnv2); break; default: PRINTHELP() } + if (!cnv1 || !cnv2) { + warning_fl("Invalid number: \"%s\"", line.gettoken_str(!cnv1 ? 1 : 3)); + } } else PRINTHELP() diff --git a/Source/tokens.cpp b/Source/tokens.cpp index a9101dd4..7bba53e9 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -247,7 +247,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_P_ADDINCLUDEDIR,_T("!AddIncludeDir"),1,0,_T("dir"),TP_ALL}, {TOK_P_INCLUDE,_T("!include"),1,1,_T("[/NONFATAL] filename.nsh"),TP_ALL}, {TOK_P_CD,_T("!cd"),1,0,_T("absolute_or_relative_new_directory"),TP_ALL}, -{TOK_P_IF,_T("!if"),1,3,_T("[!] (value [(==,!=,<=,<,>,>=,&,&&,||) value2] | /FILEEXISTS path)"),TP_ALL}, +{TOK_P_IF,_T("!if"),1,3,_T("[!] (value [(==,!=,S==,S!=,=,<>,<=,<,>,>=,&,&&,||) value2] | /FILEEXISTS path)"),TP_ALL}, {TOK_P_IFDEF,_T("!ifdef"),1,-1,_T("symbol [| symbol2 [& symbol3 [...]]]"),TP_ALL}, {TOK_P_IFNDEF,_T("!ifndef"),1,-1,_T("symbol [| symbol2 [& symbol3 [...]]]"),TP_ALL}, {TOK_P_ENDIF,_T("!endif"),0,0,_T(""),TP_ALL},