📄 language.values.html
字号:
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
><TT
CLASS="LITERAL"
>get_data(option)</TT
></DT
><DD
><P
>This function can be used to obtain just the data part of a loaded
configuration option, ignoring other factors such as whether or not
the option is active and enabled. It takes a single argument which
should be the name of a configuration option. If the specified option
is not loaded in the current configuration then the function returns
0, otherwise it returns the data part. Typically this function will
only be used in conjunction with <CODE
CLASS="FUNCTION"
>is_active</CODE
> and
<CODE
CLASS="FUNCTION"
>is_enabled</CODE
> for fine-grained control over the
various factors that make up an option's value.</P
></DD
><DT
><TT
CLASS="LITERAL"
>is_active(option)</TT
></DT
><DD
><P
>This function can be used to determine whether or not a particular
configuration option is active. It takes a single argument which
should be the name of an option, and returns a boolean. If the
specified option is not loaded then the function will return false.
Otherwise it will consider the state of the option's parents and
evaluate any <SPAN
CLASS="PROPERTY"
>active_if</SPAN
> properties, and return the option's current
active state. A typical use might be:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> requires { is_active(CYGNUM_LIBC_MAIN_DEFAULT_STACK_SIZE) implies
(CYGNUM_LIBC_MAIN_DEFAULT_STACK_SIZE >= (16 * 1024)) }</PRE
></TD
></TR
></TABLE
><P
>In other words either the specified configuration option must be
inactive, for example because the current application does not use
any related C library or POSIX functionality, or the stack size must
be at least 16K.</P
><P
>The configuration system's inference engine can attempt to satisfy
constraints involving <CODE
CLASS="FUNCTION"
>is_active</CODE
> in various
different ways, for example by enabling or disabling parent
components, or by examining <SPAN
CLASS="PROPERTY"
>active_if</SPAN
> properties and manipulating
terms in the associated expressions.</P
></DD
><DT
><TT
CLASS="LITERAL"
>is_enabled(option)</TT
></DT
><DD
><P
>This function can be used to determine whether or not a particular
configuration option is enabled. It takes a single argument which
should be the name of an option, and returns a boolean. If the
specified option is not loaded then the function will return false.
Otherwise it will return the current boolean part of the option's
value. The option's active or inactive state is ignored. Typically
this function will be used in conjunction with
<CODE
CLASS="FUNCTION"
>is_active</CODE
> and possibly
<CODE
CLASS="FUNCTION"
>get_data</CODE
> to provide fine-grained control over the
various factors that make up an option's value.</P
></DD
><DT
><TT
CLASS="LITERAL"
>is_loaded(option)</TT
></DT
><DD
><P
>This function can be used to determine whether or not a particular
configuration option is loaded. It takes a single argument which
should be the name of an option, and returns a boolean. If the
argument is a package then the <CODE
CLASS="FUNCTION"
>is_loaded</CODE
> function
provides little or no extra information, for example the following two
constraints are usually equivalent:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> requires { CYGPKG_KERNEL }
requires { is_loaded(CYGPKG_KERNEL) }</PRE
></TD
></TR
></TABLE
><P
>However if the specified package is loaded but re-parented below a
disabled component, or inactive as a result of an <SPAN
CLASS="PROPERTY"
>active_if</SPAN
>
property, then the first constraint would not be satisfied but the
second constraint would. In other words the
<CODE
CLASS="FUNCTION"
>is_loaded</CODE
> makes it possible to consider in
isolation one of the factors that are considered when CDL expressions
are evaluated.</P
><P
>The configuration system's inference engine will not automatically
load or unload packages to satisfy <CODE
CLASS="FUNCTION"
>is_loaded</CODE
>
constraints. </P
></DD
><DT
><TT
CLASS="LITERAL"
>is_substr(haystack, needle)</TT
></DT
><DD
><P
>This can be used to check whether or not a particular string is
present in another string. It is used mainly for manipulating compiler
flags. The function takes two arguments, both of which can be
arbitrary expressions, and returns a boolean.</P
><P
><CODE
CLASS="FUNCTION"
>is_substr</CODE
> has some understanding of word
boundaries. If the second argument starts with a space character then
that will match either a real space or the start of the string.
Similarly if the second argument ends with a space character then that
will match a real space or the end of the string. For example, all of
the following conditions are satisfied:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> is_substr("abracadabra", "abra")
is_substr("abracadabra", " abra")
is_substr("hocus pocus", " pocus")
is_substr("abracadabra", "abra ")</PRE
></TD
></TR
></TABLE
><P
>The first is an exact match. The second is a match because the leading
space matches the start of the string. The third is an exact match,
with the leading space matching an actual space. The fourth is a match
because the trailing space matches the end of the string. However, the
following condition is not satisfied.</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> is_substr("abracadabra", " abra ")</PRE
></TD
></TR
></TABLE
><P
>This fails to match at the start of the string because the trailing
space is not matched by either a real space or the end of the string.
Similarly it fails to match at the end of the string.</P
><P
>If a constraint involving <CODE
CLASS="FUNCTION"
>is_substr</CODE
> is not
satisfied and the first argument is a reference to a configuration
option, the inference engine will attempt to modify that option's
value. This can be achieved either by appending the second argument to
the current value, or by removing all occurrences of that argument
from the current value.</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> requires { !is_substr(CYGBLD_GLOBAL_CFLAGS, " -fno-rtti ") }
requires { is_substr(CYGBLD_GLOBAL_CFLAGS, " -frtti ") }</PRE
></TD
></TR
></TABLE
><P
>When data is removed the leading and trailing spaces will be left. For
example, given an initial value of
<<CODE
CLASS="VARNAME"
>CYGBLD_GLOBAL_CFLAGS</CODE
> of
<TT
CLASS="LITERAL"
>-g -fno-rtti -O2</TT
> the result will be
<TT
CLASS="LITERAL"
>-g -O2</TT
> rather than <TT
CLASS="LITERAL"
>-g-O2</TT
>.</P
><P
>If exact matches are needed, the function
<CODE
CLASS="FUNCTION"
>is_xsubstr</CODE
> can be used instead.</P
></DD
><DT
><TT
CLASS="LITERAL"
>is_xsubstr(haystack, needle)</TT
></DT
><DD
><P
>This function checks whether or not the pattern string is an exact
substring of the string being searched. It is similar to
<CODE
CLASS="FUNCTION"
>is_substr</CODE
> but uses exact matching only. In other
words, leading or trailing spaces have to match exactly and will not
match the beginning or end of the string being searched. The function
takes two arguments, both of which can be arbitrary expressions, and
returns a boolean. The difference between
<CODE
CLASS="FUNCTION"
>is_substr</CODE
> and <CODE
CLASS="FUNCTION"
>is_xsubstr</CODE
> is
illustrated by the following examples:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> cdl_option MAGIC {
flavor data
default_value { "abracadabra" }
}
…
requires { is_substr(MAGIC, " abra") }
requires { is_xsubstr(MAGIC, " abra") }</PRE
></TD
></TR
></TABLE
><P
>The first goal will be satisfied because the leading space in the
pattern matches the beginning of the string. The second goal will not
be satisfied initialy because there is no exact match, so the
inference engine is likely to update the value of
<CODE
CLASS="VARNAME"
>MAGIC</CODE
> to <TT
CLASS="LITERAL"
>abracadabra abra</TT
> which
does give an exact match.</P
></DD
><DT
><TT
CLASS="LITERAL"
>version_cmp(A, B)</TT
></DT
><DD
><P
>This function is used primarily to check that a sufficiently recent
<A
HREF="package.versions.html"
>version</A
> of some other package
is being used. It takes two arguments, both of which can be arbitrary
expressions. In practice usually one of the arguments will be a
reference to a package and the other will be a constant version
string. The return value is -1 if the first argument is a more recent
version then the second, 0 if the two arguments correspond to
identical versions, and 1 if the first argument is an older version.
For example the following constraint can be used to indicate that the
current package depends on kernel functionality that only became
available in version 1.3:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> requires { version_cmp(CYGPKG_KERNEL, "v1.3") <= 0 }</PRE
></TD
></TR
></TABLE
></DD
></DL
></DIV
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
>At this time it is not possible to define new functions inside a CDL
script. Instead functions can only be added at the C++ level, usually
by extending libcdl itself. This is partly because there is more to
CDL functions than simple evaluation: associated with most functions
is support for the inference engine, so that if a constraint involving
a function is not currently satisfied the system may be able to find a
solution automatically.</P
></BLOCKQUOTE
></DIV
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="LANGUAGE.GOAL-EXPRESSION"
>Goal Expressions</A
></H2
><P
>The arguments to certain properties, notably <SPAN
CLASS="PROPERTY"
>requires</SPAN
> and
<SPAN
CLASS="PROPERTY"
>active_if</SPAN
>, constitute a goal expression. As with an ordinary
expression, all of the arguments get combined and then the expression
parser takes over. The same care has to be taken with constant strings
and anything else that may get processed by the Tcl interpreter, so
often a goal expression is enclosed entirely in braces and the
expression parsing code sees just a single argument.</P
><P
>A goal expression is basically just a sequence of ordinary
expressions, for example:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> requires { CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
!CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
!CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT }</PRE
></TD
></TR
></TABLE
><P
>This consists of three separate expressions, all of which should
evaluate to a non-zero result. The same expression could be written
as: </P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> requires { CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS &&
!CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT &&
!CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT }</PRE
></TD
></TR
></TABLE
><P
>Alternatively the following would have much the same effect:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
requires !CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
requires !CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT</PRE
></TD
></TR
></TABLE
><P
>Selecting between these alternatives is largely a stylistic choice.
The first is slightly more concise than the others. The second is more
likely to appeal to mathematical purists. The third is more amenable
to cutting and pasting.</P
><P
>The result of evaluating a goal expression is a boolean. If any part
of the goal expression evaluates to the integer <TT
CLASS="LITERAL"
>0</TT
>
or an equivalent string then the result is false, otherwise it is
true. </P
><P
>The term “goal expression” relates to the component
framework's inference engine: it is a description of a goal that
should be satisfied for a conflict-free configuration. If a <SPAN
CLASS="PROPERTY"
>requires</SPAN
>
constraint is not satisfied then the inference engine will examine the
goal expression: if there is some way of changing the configuration
that does not introduce new conflicts and that will cause the goal
expression to evaluate to true, the conflict can be resolved.</P
><P
>The inference engine works with one conflict and hence one goal
expression at a time. This means that there can be slightly different
behavior if a constraint is specified using a single <SPAN
CLASS="PROPERTY"
>requires</SPAN
>
property or several different ones. Given the above example, suppose
that none of the three conditions are satisfied. If a single goal
expression is used then the inference engine might be able to satisfy
only two of the three parts, but since the conflict as a whole cannot
be resolved no part of the solution will be applied. Instead the user
will have to resolve the entire conflict. If three separate goal
expressions are used then the inference engine might well find
solutions to two of them, leaving less work for the user. On the other
hand, if a single goal expression is used then the inference engine
has a bit more information to work with, and it might well find a
solution to the entire conflict where it would be unable to find
separate solutions for the three parts. Things can get very
complicated, and in general component writers should not worry about
the subtleties of the inference engine and how to manipulate its
behavior. </P
><P
>It is possible to write ambiguous goal expressions, for example:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> requires CYGNUM_LIBC_RAND_SEED -CYGNUM_LIBC_RAND_TRACE_LEVEL > 5</PRE
></TD
></TR
></TABLE
><P
>This could be parsed in two ways:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> requires ((CYGNUM_LIBC_RAND_SEED - CYGNUM_LIBC_RAND_TRACE_LEVEL) > 5)
requires CYGNUM_LIBC_RAND_SEED && ((-CYGNUM_LIBC_RAND_TRACE_LEVEL) > 5)</PRE
></TD
></TR
></TABLE
><P
>The goal expression parsing code will always use the largest ordinary
expression for each goal, so the first interpretation will be used.
In such cases it is a good idea to use brackets and avoid possible
confusion. </P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="LANGUAGE.LIST-EXPRESSION"
>List Expressions</A
></H2
><P
>The arguments to the <SPAN
CLASS="PROPERTY"
>legal_values</SPAN
> property constitute a goal
expression. As with an ordinary and goal expressions, all of the
arguments get combined and then the expression parser takes over. The
same care has to be taken with constant strings and anything else that
may get processed by the Tcl interpreter, so often a list expression
is enclosed entirely in braces and the expression parsing code sees
just a single argument.</P
><P
>Most list expressions take one of two forms:</P
><TABLE
BORDER="5"
BGCOL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -