Directives implemented by eĿlipsis. More...
Variables | |
C standard directives | |
__directive__ | define |
The define directive as specified by the C standard. | |
__directive__ | elif |
The elif directive as specified by the C standard. | |
__directive__ | else |
The else directive as specified by the C standard. | |
__directive__ | embed |
The embed directive as specified by the C standard plus extension. | |
__directive__ | endif |
The endif directive as specified by the C standard. | |
__directive__ | error |
The error directive as specified by the C standard. | |
__directive__ | if |
The else directive as specified by the C standard. | |
__directive__ | include |
The include directive as specified by the C standard plus extensions. | |
__directive__ | line |
The line directive as specified by the C standard. | |
__directive__ | undef |
The undef directive as specified by the C standard. | |
__directive__ | warning |
The warning directive as specified by the C standard. | |
C standard shortcuts for directives | |
__directive__ | elifdef |
alias for #elif defined | |
__directive__ | elifndef |
alias for #elif !defined | |
__directive__ | ifdef |
alias for #if defined | |
__directive__ | ifndef |
alias for #if !defined | |
EĿlipsis specific variations of directives | |
__directive__ | always |
Always expand the code up to the next #end or #endif. | |
__directive__ | bind |
A local equivalent to #define. | |
__directive__ | embed_resource |
Embed the data source file but without expanding the token list of the directive. | |
__directive__ | environment |
Find an environment variable through the C library call getenv and define a macro of the same name. | |
__directive__ | expand |
Expand the remaining tokens on the line and re-interpret the result as a directive. | |
__directive__ | include_directives |
Execute only the directives in the given header file. | |
__directive__ | include_source |
Include the source file but without expanding the token list of the directive. | |
__directive__ | linenumber |
As the #line directive but without expanding the rest of the line. | |
__directive__ | never |
Never expand the code up to the next #end or #endif. | |
__directive__ | once |
Only expand the code up to the next #end, #endif or the end of the header once. | |
EĿlipsis extensions to handle argument lists | |
Using recursive inclusion would quickly hit a complexity wall if we are not careful. This is because with "normal" directives we expand a whole argument lists, for example, just to split off the first argument and collect the remainder. This easily makes iterative algorithms quadratic because all the arguments are touched over and over again. EĿlipsis provides specialized macro assignment directives that avoid this complexity. | |
__directive__ | gather |
Gather token lists into a macro. | |
__directive__ | move |
Delete the contents of target and move the contents of source into it. | |
__directive__ | scatter |
Scatter comma-separated parts of a token list into other macros. | |
Shortcuts for explicit expansion | |
__directive__ | end |
alias for #endif | |
__directive__ | xbind |
alias for #expand __bind__ | |
__directive__ | xdefine |
alias for #expand __define__ | |
__directive__ | xembed_resource |
alias for #expand __embed_resource__ | |
__directive__ | xinclude_source |
alias for #expand __include_source__ | |
__directive__ | xlinenumber |
alias for #expand __linenumber__ | |
Directives implemented by eĿlipsis.
These are only artificially combined into this pseudo-source file for reference.
Some form proper directives of their own, others are just shortcuts (aliases) for some other combination.
__directive__ always |
Always expand the code up to the next #end or #endif.
This can be used for example to ensure that a set of #bind directives is restricted to the lines up to the end of this construct.
is the same as
__directive__ bind |
__directive__ define |
The define directive as specified by the C standard.
__directive__ elif |
The elif directive as specified by the C standard.
__directive__ elifdef |
alias for #elif defined
__directive__ elifndef |
alias for #elif !defined
__directive__ else |
The else directive as specified by the C standard.
__directive__ embed |
The embed directive as specified by the C standard plus extension.
__directive__ embed_resource |
Embed the data source file but without expanding the token list of the directive.
Other arguments to this directive are not expanded, unless the #expand prefix is applied.
__directive__ end |
alias for #endif
Referenced by ellipsis‿include‿embed(), ellipsis_special_scan_str32(), ellipsis_special_scan_str8(), and has_file_callback().
__directive__ endif |
The endif directive as specified by the C standard.
__directive__ environment |
Find an environment variable through the C library call getenv
and define a macro of the same name.
The contents of the environment variable is tokenized as if it were given in a #‿define directive. The remaining token list (which may be empty) is the default setting if the environment variable is not found.
Example:
inspects the environment variables and defines the macros LOOP_DEPTH
, VALUES
, QUESTION
and HOME
. If there is no such environment variable it is set to the token list as indicated. So if there is no QUESTION
environment variable, the replacement list of that macro would be empty.
For HOME
most operating systems provide a name of a directory so in general the macro HOME
will not be empty. Note thought that eĿlipsis provides the contents of this variable as raw token sequence, not as a string. This allows for more flexibility when you have to compose path names.
Would establish a subdirectory of the user′s home directory as a place to seek for include files.
Or, if you want something like this inside a string
__directive__ error |
The error directive as specified by the C standard.
__directive__ expand |
Expand the remaining tokens on the line and re-interpret the result as a directive.
So, after expansion, the first token in the resulting list should be a directive. Here, the resulting directive may be uglified by appending double underscores in front and back to avoid expansion if that happens to be defined as a macro.
If for example ARRAY(100)
is a macro and expands to array_name_100
and VALUE(100)
expands to 100*37
the following
leads to
which is the same as if we had the following directive
which defines a new macro array_name_100
with the indicated expression as expansion.
__directive__ gather |
Gather token lists into a macro.
The general form of that directive is
where NAME
is a name of a possibly pre-existing macro, and tokenᵢ
are tokens. The difference to #define
and similar are
tokenᵢ
is a name of a macro, the replacement list of that macro is removed from that macro (so it becomes empty) and spliced in place instead of tokenᵢ
. But other than for #define
no further expansion takes place.NAME
is not a pre-existing macro, a new macro is defined that has the resulting list as replacement list.NAME
is already a macro, the resulting list is appended to the current replacement list.Consider the following example that uses three function-like macros
Note that in the #gather
line, none of the macros is "invoked", there are no ()
parenthesis.
After that, the following three source lines
expand to the replacements
That is, C()
has the concatenation of the three lists in the order they appear in #gather
, and A()
and B()
are now empty macros that expand to nothing.
For a more complicated example, take the source of the ellipsis-foreach-loop.dirs Xfile, which is the bottom of the recursion of ellipsis-foreach.dirs
If we have that
FOREACH_RESULT
is a function-like macro with no parameter that expands to the tokens "a , b , c
"BODY
is function-like macro that receives one parameter X
and returns the tokens "array [X ]
"FOREACH_FIR
expands to the single token "100
",the line
First expands the tokens on the line, to maybe result in something like
Note that gather
and FOREACH_RESULT
are not expanded. This new token list is then taken as a directive and FOREACH_RESULT
now contains a, b, c, array[100]
k
that are given, not on the lengths of their replacement lists or the length of the existing replacement list of NAME
. __directive__ if |
The else directive as specified by the C standard.
__directive__ ifdef |
alias for #if defined
__directive__ ifndef |
alias for #if !defined
__directive__ include |
The include directive as specified by the C standard plus extensions.
__directive__ include_directives |
Execute only the directives in the given header file.
All tokens that would be produced are discarded, only side effects such as macro definitions have an effect on the source that uses this directive.
Other arguments to this directive are not expanded, unless the #expand prefix is applied.
__directive__ include_source |
Include the source file but without expanding the token list of the directive.
Other arguments to this directive are not expanded, unless the #expand prefix is applied.
__directive__ line |
The line directive as specified by the C standard.
Referenced by ellipsis‿include‿embed(), ellipsis‿tokenize(), and get_a_line().
__directive__ linenumber |
As the #line directive but without expanding the rest of the line.
__directive__ move |
Delete the contents of target
and move the contents of source
into it.
O(1)
. __directive__ never |
__directive__ once |
Only expand the code up to the next #end, #endif or the end of the header once.
In particular this can be used to skip over a whole header file that has already be seen.
The directive receives one optional argument, which is an identifier that helps to identify the source file (or #if construct) in question. If omitted, a hash of the base-name of the current file name is used.
once
. __directive__ scatter |
Scatter comma-separated parts of a token list into other macros.
The general form of that directive is
where NAME
is a name of a pre-existing macro, and targetᵢ
are identifiers. Here the starting sequence of tokens in NAME
up to the first comma is removed from NAME
, target1
is made a macro if it was not before, and the replacement sequence of target1
is set to (or replaced by) that starting sequence. Then the now leading comma is also removed from NAME
and the procedure is performed in turn for target2
etc. Once all targetᵢ
macros are processed, NAME
keeps the remaining token list (again without the possible comma).
Note that in the #scatter
line, none of the macros is "invoked", there are no ()
parenthesis.
After that, the following three source lines
expand to the replacements
That is, A()
has the tokens up to the first comma, B()
those up to the second then C()
keeps the remaining list after the second comma.
For a more complicated example, take the source of the ellipsis-foreach-loop.dirs Xfile, which is the bottom of the recursion of ellipsis-foreach.dirs
If we have that
FOREACH_ARGS
is a function-like macro with no parameter that expands to the tokens "17 , 9 , 100
"FOREACH_FIR
is a function-like macro with no parameter that might have any contentsafter the line
the snippet
would expand to
k
that are given and on the length of the corresponding lists in NAME
. If n₁
, ..., nₖ
are the lengths of these lists, the complexity is O(Σᵢ nᵢ)
. The remaining list in NAME
stays otherwise untouched and may be arbitrarily long without influencing the complexity. __directive__ undef |
The undef directive as specified by the C standard.
__directive__ warning |
The warning directive as specified by the C standard.
__directive__ xbind |
alias for #expand __bind__
__directive__ xdefine |
alias for #expand __define__
__directive__ xembed_resource |
alias for #expand __embed_resource__
__directive__ xinclude_source |
alias for #expand __include_source__
__directive__ xlinenumber |
alias for #expand __linenumber__