applied patch #1412982 - "!if" - enhanced compile time flow control

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@4526 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
kichik 2006-02-24 15:06:30 +00:00
parent 0bcee34186
commit b1dc917843
5 changed files with 138 additions and 34 deletions

View file

@ -51,6 +51,40 @@ d\
i\
f
# tests for !if statement
!if 'test' == 'test'
!if 1 <= 2
!if ! 100 < 99.99
!if 2.2 > 1.12
!if ! 23 >= 37
!if 1 && 1
!if ! 0 || 0
# this should be compiled
!else
!error "!if ! 0 || 0 is true!"
!endif
!else
!error "!if 1 && 1 is true!"
!endif
!else
!error "!if ! 23 >= 37 is true!"
!endif
!else
!error "!if 2.2 > 1.12 is true!"
!endif
!else
!error "!if ! 100 < 99.99 is true!"
!endif
!else
!error "!if 1 <= 2 is true!"
!endif
!else
!error "!if 'test' == 'test' is true!"
!endif
# this should just give a warning, not an error
!include /NONFATAL file_that_doesnt_exist.nsh

View file

@ -353,9 +353,15 @@ parse_again:
if (cur_ifblock && cur_ifblock->inherited_ignore)
return PS_OK;
if (!num_ifblock() || cur_ifblock->elseused)
if (!num_ifblock())
{
ERROR_MSG("!else: stray !else\n");
ERROR_MSG("!else: no if block open (!if[macro][n][def])\n");
return PS_ERROR;
}
if (cur_ifblock->elseused)
{
ERROR_MSG("!else: else already used in current if block\n");
return PS_ERROR;
}
@ -376,16 +382,17 @@ parse_again:
line.eattoken();
int v=line.gettoken_enum(0,"ifdef\0ifndef\0ifmacrodef\0ifmacrondef\0");
int v=line.gettoken_enum(0,"if\0ifdef\0ifndef\0ifmacrodef\0ifmacrondef\0");
if (v < 0) PRINTHELP()
if (line.getnumtokens() == 1) PRINTHELP()
int cmds[] = {TOK_P_IFDEF, TOK_P_IFNDEF, TOK_P_IFMACRODEF, TOK_P_IFMACRONDEF};
int cmds[] = {TOK_P_IF, TOK_P_IFDEF, TOK_P_IFNDEF, TOK_P_IFMACRODEF, TOK_P_IFMACRONDEF};
tkid = cmds[v];
if_from_else++;
}
if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF ||
tkid == TOK_P_IFMACRODEF || tkid == TOK_P_IFMACRONDEF)
tkid == TOK_P_IFMACRODEF || tkid == TOK_P_IFMACRONDEF ||
tkid == TOK_P_IF)
{
if (!if_from_else)
start_ifblock();
@ -398,29 +405,74 @@ parse_again:
int istrue=0;
int mod=0;
int p;
// pure left to right precedence. Not too powerful, but useful.
for (p = 1; p < line.getnumtokens(); p ++)
{
if (p & 1)
{
int new_s;
if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF)
new_s=!!definedlist.find(line.gettoken_str(p));
else
new_s=MacroExists(line.gettoken_str(p));
if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFMACRONDEF)
new_s=!new_s;
if (mod == 0) istrue = istrue || new_s;
else istrue = istrue && new_s;
int p=0;
if (tkid == TOK_P_IF) {
if(!strcmp(line.gettoken_str(1),"!")) {
p = 1;
line.eattoken();
}
else
if(line.getnumtokens() == 2)
istrue = line.gettoken_int(1);
else if (line.getnumtokens() == 4) {
mod = line.gettoken_enum(2,"=\0==\0!=\0<=\0<\0>\0>=\0&\0&&\0|\0||\0");
switch(mod) {
case 0:
case 1:
istrue = strcmp(line.gettoken_str(1),line.gettoken_str(3)) == 0; break;
case 2:
istrue = strcmp(line.gettoken_str(1),line.gettoken_str(3)) != 0; break;
case 3:
istrue = line.gettoken_float(1) <= line.gettoken_float(3); break;
case 4:
istrue = line.gettoken_float(1) < line.gettoken_float(3); break;
case 5:
istrue = line.gettoken_float(1) > line.gettoken_float(3); break;
case 6:
istrue = line.gettoken_float(1) >= line.gettoken_float(3); break;
case 7:
case 8:
istrue = line.gettoken_int(1) && line.gettoken_int(3); break;
case 9:
case 10:
istrue = line.gettoken_int(1) || line.gettoken_int(3); break;
default:
PRINTHELP()
}
}
else PRINTHELP()
if(p) istrue = !istrue;
}
else {
// pure left to right precedence. Not too powerful, but useful.
for (p = 1; p < line.getnumtokens(); p ++)
{
mod=line.gettoken_enum(p,"|\0&\0||\0&&\0");
if (mod == -1) PRINTHELP()
mod &= 1;
if (p & 1)
{
int new_s;
if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF)
new_s=!!definedlist.find(line.gettoken_str(p));
else
new_s=MacroExists(line.gettoken_str(p));
if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFMACRONDEF)
new_s=!new_s;
if (mod == 0) istrue = istrue || new_s;
else istrue = istrue && new_s;
}
else
{
mod=line.gettoken_enum(p,"|\0&\0||\0&&\0");
if (mod == -1) PRINTHELP()
mod &= 1;
}
}
}
@ -437,7 +489,7 @@ parse_again:
if (tkid == TOK_P_ENDIF) {
if (!num_ifblock())
{
ERROR_MSG("!endif: no !ifdef open\n");
ERROR_MSG("!endif: no if block open (!if[macro][n][def])\n");
return PS_ERROR;
}
end_ifblock();

View file

@ -225,12 +225,13 @@ static tokenType tokenlist[TOK__LAST] =
{TOK_P_ADDINCLUDEDIR,"!AddIncludeDir",1,0,"dir",TP_ALL},
{TOK_P_INCLUDE,"!include",1,1,"[/NONFATAL] filename.nsh",TP_ALL},
{TOK_P_CD,"!cd",1,0,"absolute_or_relative_new_directory",TP_ALL},
{TOK_P_IF,"!if",1,3,"[!] value [(==,!=,<=,<,>,>=,&&,||) value2] [...]",TP_ALL},
{TOK_P_IFDEF,"!ifdef",1,-1,"symbol [| symbol2 [& symbol3 [...]]]",TP_ALL},
{TOK_P_IFNDEF,"!ifndef",1,-1,"symbol [| symbol2 [& symbol3 [...]]]",TP_ALL},
{TOK_P_ENDIF,"!endif",0,0,"",TP_ALL},
{TOK_P_DEFINE,"!define",1,2,"[/date] symbol [value]",TP_ALL},
{TOK_P_UNDEF,"!undef",1,1,"symbol [value]",TP_ALL},
{TOK_P_ELSE,"!else",0,-1,"[ifdef|ifndef symbol [|symbol2 [& symbol3 [...]]]]",TP_ALL},
{TOK_P_ELSE,"!else",0,-1,"[if[macro][n][def] ...]",TP_ALL},
{TOK_P_ECHO,"!echo",1,0,"message",TP_ALL},
{TOK_P_WARNING,"!warning",0,1,"[warning_message]",TP_ALL},
{TOK_P_ERROR,"!error",0,1,"[error_message]",TP_ALL},

View file

@ -71,6 +71,7 @@ enum
TOK_FILEBUFSIZE,
// system "preprocessor"ish tokens
TOK_P_IF,
TOK_P_IFDEF,
TOK_P_IFNDEF,
TOK_P_ELSE,