CppCond¶
Provides a state stack of booleans to facilitate conditional compilation as: ISO/IEC 9899:1999(E) section 6.10.1 (‘C’) and ISO/IEC 14882:1998(E) section 16.1 (‘C++’) [cpp.cond]
This does not interpret any semantics of either standard but instead provides a state class that callers that do interpret the language semantics can use.
In particular this provides state change operations that might be triggered by the following six pre-processing directives:
#if constant-expression new-line group opt
#ifdef identifier new-line group opt
#ifndef identifier new-line group opt
#elif constant-expression new-line group opt
#else new-line group opt
#endif new-line
In this module a single CppCond
object has a stack of ConditionalState objects.
The latter has both a boolean state and an ‘explanation’ of that state at any
point in the translation.
The latter is represented by a list of string representations of either
constant-expression or identifier tokens.
The stack i.e. CppCond
can also be queried for its net boolean state and its
net ‘explanation’.
Basic boolean stack operations:
Directive Argument Stack, s, boolean operation
--------- -------- -----------------------
#if constant-expression s.push(bool)
#ifdef identifier s.push(bool)
#ifndef identifier s.push(!bool)
#elif constant-expression s.pop(), s.push(bool)
#else N/A Either s.push(!s.pop()) or s.flip()
#endif N/A s.pop()
Basic boolean ‘explanation’ string operations:
The '!'
prefix is parameterised as TOKEN_NEGATION
so that any
subsequent processing can recognise '!!'
as ''
and '!!!'
as '!'
:
Directive Argument Matrix, m, strings
--------- -------- ------------------
#if constant-expression m.push(['%s' % tokens,])
#ifdef identifier m.push(['(defined %s)' % identifier)])
#ifndef identifier m.push(['!(defined %s)' % identifier)])
#elif constant-expression m[-1].push('!%s' % m[-1].pop()),
m[-1].push(['%s' % tokens,])
Note: Here we flip the existing state via
a push(!pop())) then push the additional
condition so that we have multiple
contitions that are and'd together.
#else N/A m[-1].push('!%s' % m[-1].pop())
Note: This is the negation of the sum of
the previous #if, #elif statements.
#endif N/A m.pop()
Note
The above does not include error checking such as pop() from an empty stack.
Stringifying the matrix m:
flatList = []
for aList in m:
assert(len(aList) > 0)
if len(aList) > 1:
# Add parenthesis so that when flatList is flattened then booleans are
# correctly protected.
flatList.append('(%s)' % ' && '.join(aList))
else:
flatList.append(aList[0])
return ' && '.join(flatList)
This returns for something like m is: [['a < 0',], ['!b', 'c > 45'], ['d < 27',],]
Then this gives: "a < 0 && (!b && c > 45) && d < 27"
-
class
cpip.core.CppCond.
ConditionalState
(theState, theIdOrCondExpr)¶ Holds a single conditional state.
-
constExprStr
(invert=False)¶ Returns self as a string which is the concatenation of constant-expressions.
-
flip
()¶ Inverts the boolean such as for #else directive.
-
flipAndAdd
(theBool, theConstExpr)¶ This handles an #elif command on this item in the stack. This flips the state (if theBool is True) and negates the last expression on the condition list then appends theConstExpr onto the condition list.
-
hasBeenTrue
¶ Return True if the state has been True at any time in the lifetime of this object.
-
negateLastState
()¶ Inverts the state of the last item on the stack.
-
state
¶ Returns boolean state of self.
-
-
class
cpip.core.CppCond.
CppCond
¶ Provides a state stack to handle conditional compilation. This could be used by an implementation of conditional inclusion e.g. ISO/IEC 14882:1998(E) section 16.1 Conditional inclusion [cpp.cond]
Essentially this class provides a state machine that can be created altered and queried. The APIs available to the caller correspond to the if-section part of the the applicable standard (i.e.
#if
#elif
etc). Most APIs take two arguments;- theBool
- Is a boolean that is the result of the callers evaluation of a constant-expression.
- theIce
- A string that represents the identifier or constant-expression
in a way that the caller sees fit (i.e. this is not evaluated
locally in any way).
Combinations of such strings _are_ merged by use of boolean
logic (
'!'
) andLPAREN
andRPAREN
.
-
close
()¶ Finalisation, may raise
ExceptionCppCond
is stack non-empty.
-
hasBeenTrueAtCurrentDepth
()¶ Return True if the
ConditionalState
at the current depth has ever beenTrue
. This is used to decide whether to evaluate#elif
expressions. They don’t need to be if theConditionalState
has already been True, and in fact, the C Rationale (6.10) says that bogus#elif
expressions should not be evaluated in this case - i.e. ignore syntax errors.
-
isTrue
()¶ Returns True if all of the states in the stack are True, False otherwise.
-
oElif
(theBool, theConstExpr)¶ Deal with the result of a
#elif
.- theBool
- Is a boolean that is the result of the callers evaluation of a constant-expression.
- theConstExpr
- A string that represents the identifier or
constant-expression in a way that the caller sees fit (i.e. this is not
evaluated locally in any way).
Combinations of such strings _are_ merged by use of boolean
logic (‘!’) and
LPAREN
andRPAREN
.
-
oElse
()¶ Deal with the result of a
#else
.
-
oEndif
()¶ Deal with the result of a
#endif
.
-
oIf
(theBool, theConstExpr)¶ Deal with the result of a
#if
.- theBool
- Is a boolean that is the result of the callers evaluation of a constant-expression.
- theConstExpr
- A string that represents the identifier or
constant-expression in a way that the caller sees fit (i.e. this is not
evaluated locally in any way).
Combinations of such strings _are_ merged by use of boolean
logic (‘!’) and
LPAREN
andRPAREN
.
-
oIfdef
(theBool, theConstExpr)¶ Deal with the result of a
#ifdef
.- theBool
- Is a boolean that is the result of the callers evaluation of a constant-expression.
- theConstExpr
- A string that represents the identifier or
constant-expression in a way that the caller sees fit (i.e. this is not
evaluated locally in any way).
Combinations of such strings _are_ merged by use of boolean
logic (‘!’) and
LPAREN
andRPAREN
.
-
oIfndef
(theBool, theConstExpr)¶ Deal with the result of a
#ifndef
.- theBool
- Is a boolean that is the result of the callers evaluation of a constant-expression.
- theConstExpr
- A string that represents the identifier or
constant-expression in a way that the caller sees fit (i.e. this is not
evaluated locally in any way).
Combinations of such strings _are_ merged by use of boolean
logic (‘!’) and
LPAREN
andRPAREN
.
-
stackDepth
¶ Returns the depth of the conditional stack as an integer.
-
class
cpip.core.CppCond.
CppCondGraph
¶ Represents a graph of conditional preprocessing directives.
-
isComplete
¶ True if the last if-section, if present is completed with an
#endif
.
-
oElif
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#elif
.- theFlc
- A
cpip.core.FileLocation.FileLineColumn
object that identifies the position in the file. - theTuIndex
- An integer that represents the position in the translation unit.
- theBool
- The current state of the conditional stack.
- theCe
- The constant expression as a string (not evaluated).
-
oElse
(theFlc, theTuIdx, theBool)¶ Deal with the result of a
#else
.- theFlc
- A
cpip.core.FileLocation.FileLineColumn
object that identifies the position in the file. - theTuIndex
- An integer that represents the position in the translation unit.
- theBool
- The current state of the conditional stack.
-
oEndif
(theFlc, theTuIdx, theBool)¶ Deal with the result of a
#endif
.- theFlc
- A
cpip.core.FileLocation.FileLineColumn
object that identifies the position in the file. - theTuIndex
- An integer that represents the position in the translation unit.
- theBool
- The current state of the conditional stack.
-
oIf
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#if
.- theFlc
- A
cpip.core.FileLocation.FileLineColumn
object that identifies the position in the file. - theTuIndex
- An integer that represents the position in the translation unit.
- theBool
- The current state of the conditional stack.
- theCe
- The constant expression as a string (not evaluated).
-
oIfdef
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#ifdef
.- theFlc
- A
cpip.core.FileLocation.FileLineColumn
object that identifies the position in the file. - theTuIndex
- An integer that represents the position in the translation unit.
- theBool
- The current state of the conditional stack.
- theCe
- The constant expression as a string (not evaluated).
-
oIfndef
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#ifndef
.- theFlc
- A
cpip.core.FileLocation.FileLineColumn
object that identifies the position in the file. - theTuIndex
- An integer that represents the position in the translation unit.
- theBool
- The current state of the conditional stack.
- theCe
- The constant expression as a string (not evaluated).
-
visit
(theVisitor)¶ Take a visitor object and pass it around giving it each
CppCondGraphNode
object.
-
-
class
cpip.core.CppCond.
CppCondGraphIfSection
(theIfCppD, theFlc, theTuIdx, theBool, theCe)¶ Class that represents a conditionally compiled section starting with #if... and ending with
#endif
.- theIfCppD
- A string, one of ‘#if’, ‘#ifdef’, ‘#ifndef’.
- theFlc
- A
cpip.core.FileLocation.FileLineColumn
object that identifies the position in the file. - theTuIndex
- An integer that represents the position in the translation unit.
- theBool
- The current state of the conditional stack.
- theCe
- The constant expression as a string (not evaluated).
-
oElif
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#elif
.
-
oElse
(theFlc, theTuIdx, theBool)¶ Deal with the result of a
#else
.
-
oEndif
(theFlc, theTuIdx, theBool)¶ Deal with the result of a
#endif
.
-
oIf
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#if
.
-
oIfdef
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#ifdef
.
-
oIfndef
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#ifndef
.
-
visit
(theVisitor, theDepth)¶ Take a visitor object make the pre/post calls.
-
class
cpip.core.CppCond.
CppCondGraphNode
(theCppDirective, theFileLineCol, theTuIdx, theBool, theConstExpr=None)¶ Base class for all nodes in the
CppCondGraph
.-
canAccept
(theCppD)¶ True if I can accept a Preprocessing Directive; theCppD.
-
oElif
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#elif
.
-
oElse
(theFlc, theTuIdx, theBool)¶ Deal with the result of a
#else
.
-
oEndif
(theFlc, theTuIdx, theBool)¶ Deal with the result of a
#endif
.
-
oIf
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#if
.
-
oIfdef
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#ifdef
.
-
oIfndef
(theFlc, theTuIdx, theBool, theCe)¶ Deal with the result of a
#ifndef
.
-
retStrList
(theDepth)¶ Returns a list of string representation.
-
visit
(theVisitor, theDepth)¶ Take a visitor object make the pre/post calls.
-
-
class
cpip.core.CppCond.
CppCondGraphVisitorBase
¶ Base class for a CppCondGraph visitor object.
-
visitPost
(theCcgNode, theDepth)¶ Post-traversal call with a
CppCondGraphNode
and the integer depth in the tree.
-
visitPre
(theCcgNode, theDepth)¶ Pre-traversal call with a
CppCondGraphNode
and the integer depth in the tree.
-
-
class
cpip.core.CppCond.
CppCondGraphVisitorConditionalLines
¶ Allows you to find out if any particular line in a file is compiled or not. This is useful to be handed to the ITU to HTML generator that can colourize the HTML depending if any line is compiled or not.
This is a visitor class that walks the graph creating a dict of:
{file_id : [(line_num, boolean), ...], ...}
It then decomposes those into a map of{file_id : LineConditionalInterpretation(), ...}
which can perfom the actual conditional state determination.API is really
isCompiled()
and this returns -1 or 0 or 1. 0 means NO. 1 means YES and -1 means sometimes - for re-included files in a different macro environment perhaps.-
fileIdS
¶ An unordered list of file IDs.
-
isCompiled
(fileId, lineNum)¶ Returns 1 if this line is compiled, 0 if not or -1 if it is ambiguous i.e. sometimes it is and somtimes not when multiple inclusions.
-
visitPre
(theCcgNode, theDepth)¶ Capture the fileID, line number and state.
-
-
exception
cpip.core.CppCond.
ExceptionCppCond
¶ Simple specialisation of an exception class for the CppCond.
-
exception
cpip.core.CppCond.
ExceptionCppCondGraph
¶ Simple specialisation of an exception class for the CppCondGraph.
-
exception
cpip.core.CppCond.
ExceptionCppCondGraphElif
¶ When the CppCondGraph sees an #elif preprocessing directive in the wrong sequence.
-
exception
cpip.core.CppCond.
ExceptionCppCondGraphElse
¶ When the CppCondGraph sees an #endif preprocessing directive in the wrong sequence.
-
exception
cpip.core.CppCond.
ExceptionCppCondGraphIfSection
¶ Exception for a
CppCondGraphIfSection
.
-
exception
cpip.core.CppCond.
ExceptionCppCondGraphNode
¶ When the
CppCondGraphNode
sees an preprocessing directive in the wrong sequence.
-
class
cpip.core.CppCond.
LineConditionalInterpretation
(theList)¶ Class that represents the conditional compilation state of every line in a file. This takes a list of
[(line_num, boolean), ...]
and interprets individual line numbers as to whether they are compiled or not.If the same file is included twice with a different macro environment then it is entirely possible that line_num is not monotonic. In any case not every line number is present, the state of any unmentioned line is the state of the last mentioned line. Thus a simple dict is not useful.
We have to sort theList by line_num and if there are duplicate line_num with different boolean values then the conditional compilation state at that point is ambiguous.
-
isCompiled
(lineNum)¶ Returns 1 if this line is compiled, 0 if not or -1 if it is ambiguous i.e. sometimes it is and sometimes not when multiply included.
This requires a search for the previously mentioned line state.
Will raise a ValueError if no prior state can be found, for example if there are no conditional compilation directives in the file. In this case it is up to the caller to handle this.
CppCondGraphVisitorConditionalLines
does this duringvisitPre()
by artificially inserting line 1. SeeCppCondGraphVisitorConditionalLines.isCompiled()
-
-
cpip.core.CppCond.
StateConstExprFileLine
¶ alias of
StateConstExprLoc