Skip to content
Snippets Groups Projects
Commit c9b820ef authored by benjamin.franksen's avatar benjamin.franksen
Browse files

docs: expanded reference section on C compatibility features

- make clear that you can reference foreign entities
  directly in action statements w/o recourse to escape syntax
- explain why and how to avoid #include and other CPP directives
  in multi-line escaped code blocks
parent 5b1ecb46
No related branches found
No related tags found
No related merge requests found
......@@ -88,7 +88,7 @@ any) at the given line.
:token:`file_name` must be a single string (no automatic string
concatenation).
Line markers are typically generated by preprocessors, such as CPP.
Line markers are typically generated by preprocessors, such as *cpp*.
.. _StateProgram:
......@@ -323,7 +323,7 @@ Foreign Entities
~~~~~~~~~~~~~~~~
The pseudo type "foreign" is used to declare any number of C variables
or struct tags or CPP macros that have been defined outside the SNL
or struct tags or *cpp* macros that have been defined outside the SNL
program. No warning will be issued if such a variable, struct tag, or
macro is used in the program even if warnings are enabled.
......@@ -1500,8 +1500,7 @@ pvTimeStamp
Returns the time stamp for the last :c:func:`pvGet` completion or monitor
event for this variable. The SNL compiler does not recognize type epicsTimeStamp.
Therefore, variable declarations for this type should be in escaped
C code. This will generate a compiler warning, which can be
ignored or fixed by adding a "foreign" declaration (see `Foreign Entities`_).
C code (see `Escape to C Code`_ and `Foreign Entities`_).
Example::
......@@ -2014,39 +2013,95 @@ these variable are updated from their globally visible copies.
C Compatibility Features
------------------------
Foreign Variables and Functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can use (reference, call) any exported C variable or function that
is linked to your program. For instance, you may link a C library to
the SNL program and simply call functions from it directly in SNL code.
Note, however, that this is restricted to *SNL action statements*
(:token:`statement`). It is advisable to take care that the C code
generated from your SNL program contains (directly oir via ``#include``)
a valid declaration for such entities, otherwise the C compiler will
not be able to catch type errors (the SNL compiler does not do any
type-checking by itself). For libraries, this is usually done
by adding a line ::
%%#include "api-of-your-library.h"
This uses the one-line-escape syntax explained in the next section.
For historical reasons, *snc* complains with a warning if you use a
foreign variable (or structure tag, or macro) in SNL code (but not for
function calls). This can be suppressed by adding a foreign
declaration (see `Foreign Entities`_).
Escape to C Code
^^^^^^^^^^^^^^^^
Because the SNL does not support the full C language, C code may be
escaped in the program. The escaped code is not compiled by SNC,
but is passed the C compiler. There are two escape methods
allowed:
escaped in the program. The escaped code is not compiled by *snc*,
but is passed literally to the C compiler. There are two escape
methods allowed:
#. Any code between ``%%`` and the next newline character is escaped.
Example::
%% for (i=0; i < NVAL; i++) {
%% for (i=0; i < NVAL; i++)
#. Any code between ``%{`` and ``}%`` is escaped. Example::
%{
extern float smooth();
extern LOGICAL accelerator_mode;
}%
%{
extern float smooth();
extern LOGICAL accelerator_mode;
}%
Note that text appearing on the same line after ``%{`` and
before ``}%`` also belongs to the literal code block.
A variable (or struct tag or macro) declared in escaped C code is
foreign to the SNL, just as if it were declared in C code extern to
the SNL program and its use will give a warning if no foreign
declaration preceeds it.
Preprocessor Directives
~~~~~~~~~~~~~~~~~~~~~~~
If you are using the C pre-processor prior to compiling with *snc*,
and you wish to defer interpretation of a preprocessor directive,
then you should use the form::
A very common pitfall is the use of preprocessor directives, such as
``#include``, in multi-line literal C code blocks in conjunction
with using the preprocessor on the unprocessed SNL code (which
happens by the default with the standard build rules if the name of
the source file has the ``.st`` extension).
%%#include <ioLib.h>
%%#include <abcLib.h>
For instance with ::
Any variable declared in escaped C code and used in SNL code will
be flagged with a warning message by the SNC. However, it will be
passed on to the C compiler correctly.
%{
#include <abcLib.h>
/* ... */
}%
the header file will be included *before* the SNL compiler parses
the program, which is most probably not what you wanted to happen
here. For instance,
if the header contains macro definitions, these will not be in effect
when the rest of the C code block gets compiled.
You can defer defer interpretation of a preprocessor directive until
after *snc* has compiled the code to C, by ensuring that some extra
non-blank characters appear in front of the ``#`` sign, so *cpp* does
not recognize the directive. For instance ::
%%#include <abcLib.h>
C Functions within the State Program
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
or ::
%{#include <abcLib.h>}%
Defining C Functions within the Program
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Escaped C code can appear in many places in the SNL program. But only
code that appears at the top level, i.e. outside any SNL code block will
......@@ -2064,17 +2119,18 @@ placed there; this means either inside the definitions section
It matters where the function is defined: if it appears at the end of
the program, it can see all the variable and type definitions generated
by the SNL compiler, so if your C function acesses a global SNL variable,
by the SNL compiler, so if your C function accesses a global SNL variable,
you must place its definition at the end. However, this means that the
generated code for the SNL program does not see the C function definition,
so you might want to place a separate prototype for the function in the
definitions section (i.e. before the state sets).
Note that you can *call* any C function from anywhere in the SNL program
Remember that you can *call* any C function from anywhere in the SNL program
without escaping. You can also link the SNL program to C objects or
libraries, so the only reason to put C function definitions inside the
SNL program is if your function accesses global SNL variables.
Calling pvGet etc. from C
^^^^^^^^^^^^^^^^^^^^^^^^^
......@@ -2100,12 +2156,13 @@ as well as additional supporting macros and type definitions can be found
in the header file ``seqCom.h``. This header file is always included by
the generated C code.
.. _reentrant option:
Variable Modification for Reentrant Option
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If the reentrant option (:option:`+r`) is specified to SNC then all
If the reentrant option (:option:`+r`) is specified to *snc* then all
variables are made part of a structure. Suppose we have the
following top-level declarations in the SNL program::
......@@ -2131,7 +2188,7 @@ Reference to variable ``sw1`` is made as ::
pVar->sw1
This conversion is automatically performed by the SNC for all SNL
This conversion is automatically performed by the *snc* for all SNL
statements, but you will have to handle escaped C code yourself.
.. note::
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment