Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
CMake
CMake
Commits
50db2773
Commit
50db2773
authored
May 01, 2004
by
Ken Martin
Browse files
better if expression support
parent
7965cfb3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Source/cmIfCommand.cxx
View file @
50db2773
...
...
@@ -16,7 +16,7 @@
=========================================================================*/
#include "cmIfCommand.h"
#include <stdlib.h> // required for atof
#include <deque>
#include <cmsys/RegularExpression.hxx>
bool
cmIfFunctionBlocker
::
...
...
@@ -131,167 +131,307 @@ bool cmIfCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args)
return
true
;
}
// order of operations,
// EXISTS COMMAND DEFINED
// MATCHES LESS GREATER EQUAL STRLESS STRGREATER
// AND OR
//
// There is an issue on whether the arguments should be values of references,
// for example IF (FOO AND BAR) should that compare the strings FOO and BAR
// or should it really do IF (${FOO} AND ${BAR}) Currently EXISTS COMMAND and
// DEFINED all take values. EQUAL, LESS and GREATER can take numeric values or
// variable names. STRLESS and STRGREATER take variable names but if the
// variable name is not found it will use the name directly. AND OR take
// variables or the values 0 or 1.
bool
cmIfCommand
::
IsTrue
(
const
std
::
vector
<
std
::
string
>
&
args
,
bool
&
isValid
,
const
cmMakefile
*
makefile
)
{
// check for the different signatures
bool
isTrue
=
true
;
isValid
=
false
;
const
char
*
def
;
const
char
*
def2
;
// store the reduced args in this vector
std
::
deque
<
std
::
string
>
newArgs
;
int
reducible
=
1
;
unsigned
int
i
;
if
(
args
.
size
()
<
1
)
{
isValid
=
true
;
return
false
;
// copy to the list structure
for
(
i
=
0
;
i
<
args
.
size
();
++
i
)
{
newArgs
.
push_back
(
args
[
i
])
;
}
if
(
args
.
size
()
==
1
)
// now loop through the arguments and see if we can reduce any of them
// we do this multiple times. Once for each level of precedence
do
{
def
=
makefile
->
GetDefinition
(
args
[
0
].
c_str
());
if
(
cmSystemTools
::
IsOff
(
def
))
reducible
=
0
;
std
::
deque
<
std
::
string
>::
iterator
arg
=
newArgs
.
begin
();
while
(
arg
!=
newArgs
.
end
())
{
isTrue
=
false
;
// does a file exist
if
(
*
arg
==
"EXISTS"
&&
arg
+
1
!=
newArgs
.
end
())
{
if
(
cmSystemTools
::
FileExists
((
arg
+
1
)
->
c_str
()))
{
*
arg
=
"1"
;
}
else
{
*
arg
=
"0"
;
}
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
// does a command exist
if
(
*
arg
==
"COMMAND"
&&
arg
+
1
!=
newArgs
.
end
())
{
if
(
makefile
->
CommandExists
((
arg
+
1
)
->
c_str
()))
{
*
arg
=
"1"
;
}
else
{
*
arg
=
"0"
;
}
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
// is a variable defined
if
(
*
arg
==
"DEFINED"
&&
arg
+
1
!=
newArgs
.
end
())
{
def
=
makefile
->
GetDefinition
((
arg
+
1
)
->
c_str
());
if
(
def
)
{
*
arg
=
"1"
;
}
else
{
*
arg
=
"0"
;
}
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
++
arg
;
}
isValid
=
true
;
}
if
(
args
.
size
()
==
2
&&
(
args
[
0
]
==
"NOT"
))
while
(
reducible
);
// now loop through the arguments and see if we can reduce any of them
// we do this multiple times. Once for each level of precedence
do
{
def
=
makefile
->
GetDefinition
(
args
[
1
].
c_str
());
if
(
!
cmSystemTools
::
IsOff
(
def
))
reducible
=
0
;
std
::
deque
<
std
::
string
>::
iterator
arg
=
newArgs
.
begin
();
while
(
arg
!=
newArgs
.
end
())
{
isTrue
=
false
;
}
isValid
=
true
;
if
(
arg
+
1
!=
newArgs
.
end
()
&&
arg
+
2
!=
newArgs
.
end
()
&&
*
(
arg
+
1
)
==
"MATCHES"
)
{
def
=
cmIfCommand
::
GetVariableOrString
(
arg
->
c_str
(),
makefile
);
cmsys
::
RegularExpression
regEntry
((
arg
+
2
)
->
c_str
());
if
(
regEntry
.
find
(
def
))
{
*
arg
=
"1"
;
}
else
{
*
arg
=
"0"
;
}
newArgs
.
erase
(
arg
+
2
);
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
}
if
(
arg
+
1
!=
newArgs
.
end
()
&&
*
arg
==
"MATCHES"
)
{
*
arg
=
"0"
;
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
if
(
args
.
size
()
==
2
&&
(
args
[
0
]
==
"COMMAND"
))
{
if
(
!
makefile
->
CommandExists
(
args
[
1
].
c_str
()))
{
isTrue
=
false
;
}
isValid
=
true
;
}
if
(
arg
+
1
!=
newArgs
.
end
()
&&
arg
+
2
!=
newArgs
.
end
()
&&
(
*
(
arg
+
1
)
==
"LESS"
||
*
(
arg
+
1
)
==
"GREATER"
||
*
(
arg
+
1
)
==
"EQUAL"
))
{
def
=
cmIfCommand
::
GetVariableOrString
(
arg
->
c_str
(),
makefile
);
def2
=
cmIfCommand
::
GetVariableOrString
((
arg
+
2
)
->
c_str
(),
makefile
);
if
(
*
(
arg
+
1
)
==
"LESS"
)
{
if
(
atof
(
def
)
<
atof
(
def2
))
{
*
arg
=
"1"
;
}
else
{
*
arg
=
"0"
;
}
}
else
if
(
*
(
arg
+
1
)
==
"GREATER"
)
{
if
(
atof
(
def
)
>
atof
(
def2
))
{
*
arg
=
"1"
;
}
else
{
*
arg
=
"0"
;
}
}
else
{
if
(
atof
(
def
)
==
atof
(
def2
))
{
*
arg
=
"1"
;
}
else
{
*
arg
=
"0"
;
}
}
newArgs
.
erase
(
arg
+
2
);
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
if
(
args
.
size
()
==
2
&&
(
args
[
0
]
==
"EXISTS"
))
{
if
(
!
cmSystemTools
::
FileExists
(
args
[
1
].
c_str
()))
{
isTrue
=
false
;
}
isValid
=
true
;
}
if
(
arg
+
1
!=
newArgs
.
end
()
&&
arg
+
2
!=
newArgs
.
end
()
&&
(
*
(
arg
+
1
)
==
"STRLESS"
||
*
(
arg
+
1
)
==
"STRGREATER"
))
{
def
=
cmIfCommand
::
GetVariableOrString
(
arg
->
c_str
(),
makefile
);
def2
=
cmIfCommand
::
GetVariableOrString
((
arg
+
2
)
->
c_str
(),
makefile
);
if
(
*
(
arg
+
1
)
==
"STRLESS"
)
{
if
(
strcmp
(
def
,
def2
)
<
0
)
{
*
arg
=
"1"
;
}
else
{
*
arg
=
"0"
;
}
}
else
{
if
(
strcmp
(
def
,
def2
)
>
0
)
{
*
arg
=
"1"
;
}
else
{
*
arg
=
"0"
;
}
}
newArgs
.
erase
(
arg
+
2
);
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
if
(
args
.
size
()
==
2
&&
(
args
[
0
]
==
"MATCHES"
))
{
if
(
!
cmSystemTools
::
FileExists
(
args
[
1
].
c_str
()))
{
isTrue
=
false
;
++
arg
;
}
isValid
=
true
;
}
while
(
reducible
);
if
(
args
.
size
()
==
3
&&
(
args
[
1
]
==
"AND"
))
// now loop through the arguments and see if we can reduce any of them
// we do this multiple times. Once for each level of precedence
do
{
def
=
makefile
->
GetDefinition
(
args
[
0
].
c_str
())
;
def2
=
makefile
->
GetDefinition
(
args
[
2
].
c_str
()
);
if
(
cmSystemTools
::
IsOff
(
def
)
||
cmSystemTools
::
IsOff
(
def2
))
reducible
=
0
;
std
::
deque
<
std
::
string
>::
iterator
arg
=
newArgs
.
begin
(
);
while
(
arg
!=
newArgs
.
end
(
))
{
isTrue
=
false
;
if
(
arg
+
1
!=
newArgs
.
end
()
&&
*
arg
==
"NOT"
)
{
def
=
cmIfCommand
::
GetVariableOrNumber
((
arg
+
1
)
->
c_str
(),
makefile
);
if
(
!
cmSystemTools
::
IsOff
(
def
))
{
*
arg
=
"0"
;
}
else
{
*
arg
=
"1"
;
}
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
++
arg
;
}
isValid
=
true
;
}
while
(
reducible
);
if
(
args
.
size
()
==
3
&&
(
args
[
1
]
==
"OR"
))
// now loop through the arguments and see if we can reduce any of them
// we do this multiple times. Once for each level of precedence
do
{
def
=
makefile
->
GetDefinition
(
args
[
0
].
c_str
())
;
def2
=
makefile
->
GetDefinition
(
args
[
2
].
c_str
()
);
if
(
cmSystemTools
::
IsOff
(
def
)
&&
cmSystemTools
::
IsOff
(
def2
))
reducible
=
0
;
std
::
deque
<
std
::
string
>::
iterator
arg
=
newArgs
.
begin
(
);
while
(
arg
!=
newArgs
.
end
(
))
{
isTrue
=
false
;
}
isValid
=
true
;
}
if
(
arg
+
1
!=
newArgs
.
end
()
&&
*
(
arg
+
1
)
==
"AND"
&&
arg
+
2
!=
newArgs
.
end
())
{
def
=
cmIfCommand
::
GetVariableOrNumber
(
arg
->
c_str
(),
makefile
);
def2
=
cmIfCommand
::
GetVariableOrNumber
((
arg
+
2
)
->
c_str
(),
makefile
);
if
(
cmSystemTools
::
IsOff
(
def
)
||
cmSystemTools
::
IsOff
(
def2
))
{
*
arg
=
"0"
;
}
else
{
*
arg
=
"1"
;
}
newArgs
.
erase
(
arg
+
2
);
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
if
(
args
.
size
()
==
3
&&
(
args
[
1
]
==
"MATCHES"
))
{
def
=
cmIfCommand
::
GetVariableOrString
(
args
[
0
].
c_str
(),
makefile
);
cmsys
::
RegularExpression
regEntry
(
args
[
2
].
c_str
());
// check for black line or comment
if
(
!
regEntry
.
find
(
def
))
{
isTrue
=
false
;
}
isValid
=
true
;
}
if
(
arg
+
1
!=
newArgs
.
end
()
&&
*
(
arg
+
1
)
==
"OR"
&&
arg
+
2
!=
newArgs
.
end
())
{
def
=
cmIfCommand
::
GetVariableOrNumber
(
arg
->
c_str
(),
makefile
);
def2
=
cmIfCommand
::
GetVariableOrNumber
((
arg
+
2
)
->
c_str
(),
makefile
);
if
(
cmSystemTools
::
IsOff
(
def
)
&&
cmSystemTools
::
IsOff
(
def2
))
{
*
arg
=
"0"
;
}
else
{
*
arg
=
"1"
;
}
newArgs
.
erase
(
arg
+
2
);
newArgs
.
erase
(
arg
+
1
);
reducible
=
1
;
}
if
(
args
.
size
()
==
3
&&
(
args
[
1
]
==
"LESS"
))
{
def
=
cmIfCommand
::
GetVariableOrString
(
args
[
0
].
c_str
(),
makefile
);
def2
=
cmIfCommand
::
GetVariableOrString
(
args
[
2
].
c_str
(),
makefile
);
if
(
!
def
)
{
def
=
args
[
0
].
c_str
();
}
if
(
!
def2
)
{
def2
=
args
[
2
].
c_str
();
}
if
(
atof
(
def
)
>=
atof
(
def2
))
{
isTrue
=
false
;
++
arg
;
}
isValid
=
true
;
}
while
(
reducible
);
if
(
args
.
size
()
==
3
&&
(
args
[
1
]
==
"GREATER"
))
// now at the end there should only be one argument left
if
(
newArgs
.
size
()
==
1
)
{
def
=
cmIfCommand
::
GetVariableOrString
(
args
[
0
].
c_str
(),
makefile
);
def2
=
cmIfCommand
::
GetVariableOrString
(
args
[
2
].
c_str
(),
makefile
);
if
(
atof
(
def
)
<=
atof
(
def2
))
{
isTrue
=
false
;
}
isValid
=
true
;
}
if
(
args
.
size
()
==
3
&&
(
args
[
1
]
==
"EQUAL"
))
{
def
=
cmIfCommand
::
GetVariableOrString
(
args
[
0
].
c_str
(),
makefile
);
def2
=
cmIfCommand
::
GetVariableOrString
(
args
[
2
].
c_str
(),
makefile
);
if
(
atof
(
def
)
!=
atof
(
def2
))
if
(
newArgs
[
0
]
==
"0"
)
{
isTrue
=
false
;
return
false
;
}
isValid
=
true
;
}
if
(
args
.
size
()
==
3
&&
(
args
[
1
]
==
"STRLESS"
))
{
def
=
cmIfCommand
::
GetVariableOrString
(
args
[
0
].
c_str
(),
makefile
);
def2
=
cmIfCommand
::
GetVariableOrString
(
args
[
2
].
c_str
(),
makefile
);
if
(
strcmp
(
def
,
def2
)
>=
0
)
if
(
newArgs
[
0
]
==
"1"
)
{
isTrue
=
fals
e
;
return
tru
e
;
}
isValid
=
true
;
}
if
(
args
.
size
()
==
3
&&
(
args
[
1
]
==
"STRGREATER"
))
{
def
=
cmIfCommand
::
GetVariableOrString
(
args
[
0
].
c_str
(),
makefile
);
def2
=
cmIfCommand
::
GetVariableOrString
(
args
[
2
].
c_str
(),
makefile
);
if
(
strcmp
(
def
,
def2
)
<=
0
)
def
=
makefile
->
GetDefinition
(
args
[
0
].
c_str
());
if
(
cmSystemTools
::
IsOff
(
def
))
{
isTrue
=
false
;
return
false
;
}
isValid
=
true
;
}
return
isTrue
;
return
true
;
}
const
char
*
cmIfCommand
::
GetVariableOrString
(
const
char
*
str
,
...
...
@@ -304,3 +444,17 @@ const char* cmIfCommand::GetVariableOrString(const char* str,
}
return
def
;
}
const
char
*
cmIfCommand
::
GetVariableOrNumber
(
const
char
*
str
,
const
cmMakefile
*
mf
)
{
const
char
*
def
=
mf
->
GetDefinition
(
str
);
if
(
!
def
)
{
if
(
atoi
(
str
))
{
def
=
str
;
}
}
return
def
;
}
Source/cmIfCommand.h
View file @
50db2773
...
...
@@ -112,8 +112,12 @@ public:
"Evaluates the given expression. If the result is true, the commands "
"in the THEN section are invoked. Otherwise, the commands in the "
"ELSE section are invoked. The ELSE section is optional. Note that "
"the same expression must be given to IF, ELSE, and ENDIF. Possible "
"expressions are:
\n
"
"the same expression must be given to IF, ELSE, and ENDIF. Long "
"exressions can be used and the order or precidence is that the "
"EXISTS, COMMAND, and DEFINED operators will be evaluated first. "
"Then any EQUAL, LESS, GREATER, STRLESS, STRGREATER, MATCHES will be "
"evaluated. Then NOT operators and finally AND, OR operators will be "
"evaluated. Possible expressions are:
\n
"
" IF(variable)
\n
"
"True if the variable's value is not empty, 0, FALSE, OFF, or NOTFOUND.
\n
"
" IF(NOT variable)
\n
"
...
...
@@ -146,7 +150,10 @@ public:
" IF(variable STRGREATER string)
\n
"
" IF(string STRGREATER string)
\n
"
"True if the given string or variable's value is lexicographically "
"less (or greater) than the string on the right."
;
"less (or greater) than the string on the right.
\n
"
" IF(DEFINED variable)
\n
"
"True if the given variable is defined. It does not matter if the "
"variable is true or false just if it has been set."
;
}
// this is a shared function for both If and Else to determine if
...
...
@@ -158,6 +165,9 @@ public:
// return the original string.
static
const
char
*
GetVariableOrString
(
const
char
*
str
,
const
cmMakefile
*
mf
);
static
const
char
*
GetVariableOrNumber
(
const
char
*
str
,
const
cmMakefile
*
mf
);
cmTypeMacro
(
cmIfCommand
,
cmCommand
);
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment