diff --git a/documentation/Compiling.txt b/documentation/Compiling.txt
index b747a1fabc645a5901583acc47803c4259afa096..a3c4817644700dcc2e3c672c29f614a433c833a9 100644
--- a/documentation/Compiling.txt
+++ b/documentation/Compiling.txt
@@ -1,10 +1,10 @@
 Compiling SNL Programs
 ======================
 
-*snc*, the SNL to C Compiler
-----------------------------
+:program:`snc`, the SNL to C Compiler
+-------------------------------------
 
-The SNL to C compiler *snc* compiles the state notation
+The SNL to C compiler :program:`snc` compiles the state notation
 language into C code. The resulting file can then be compiled
 with a C compiler.
 
@@ -17,40 +17,49 @@ SNC options start by a plus or minus sign, followed by a single
 character. A plus sign turns the option on, and a minus turns the
 option off.
 
-======  ===============================================================
-Option  Description
-======  ===============================================================
-  +a    Asynchronous ``pvGet``: the program continues without
-        waiting for completion of the ``pvGet`` operation.
-  -a    Synchronous ``pvGet``: the program waits for completion.
-        This is the default if an option is not specified.
-  +c    Wait for process variables to connect before allowing the
-        program to begin execution. This is the default.
-  -c    Allow the program to begin execution before connections
-        are established to all channel.
-  +d    Turn on run-time debug messages.
-  -d    Turn off run-time debug messages. This is the default.
-  +e    Use the new event flag mode. This is the default.
-  -e    Use the old event flag mode (clear flags after executing a
-        when statement).
-  +i    Generate registrar procedure that registers shell commands
-        and programs with an IOC shell. This is the default.
-  -i    Do not generate registrar procedure.
-  +l    Add line markers to the generated code, so that C compiler
-        messages refer to the SNL source file. This is the default.
-  -l    Do not produce line markers.
-  +m    Include main procedure (seqMain.c) for a stand-alone program.
-  -m    Do not include seqMain.c. This is the default.
-  +s    :ref:`Safe mode`: variables are local to state set
-        and must be communicated explicitly. Implies +r.
-  -s    Traditional (non-safe) mode. This is the default for
-        compatibility.
-  +r    Make the generated code reentrant, thus allowing more than one
-        instance of the program to run on an IOC.
-  -r    Generated code is not reentrant. This is the default.
-  +w    Display SNC warning messages. This is the default.
-  -w    Suppress SNC warnings.
-======  ===============================================================
+============== ===============================================================
+Option         Description
+============== ===============================================================
+.. option:: +a Asynchronous ``pvGet``: the program continues without
+               waiting for completion of the ``pvGet`` operation.
+.. option:: -a Synchronous ``pvGet``: the program waits for completion.
+               This is the default if an option is not specified.
+.. option:: +c Wait for process variables to connect before allowing the
+               program to begin execution. This is the default.
+.. option:: -c Allow the program to begin execution before connections
+               are established to all channel.
+.. option:: +d Turn on run-time debug messages.
+.. option:: -d Turn off run-time debug messages. This is the default.
+.. option:: +e Use the new event flag mode. This is the default.
+.. option:: -e Use the old event flag mode (clear flags after executing a
+               when statement).
+.. option:: +i Generate registrar procedure that registers shell commands
+               and programs with an IOC shell. This is the default.
+.. option:: -i Do not generate registrar procedure.
+.. option:: +l Add line markers to the generated code, so that C compiler
+               messages refer to the SNL source file. This is the default.
+.. option:: -l Do not produce line markers.
+.. option:: +m Include main procedure (seqMain.c) for a stand-alone program.
+.. option:: -m Do not include seqMain.c. This is the default.
+.. option:: +s :ref:`Safe mode`: variables are local to state set
+               and must be communicated explicitly. Implies +r.
+.. option:: -s Traditional (non-safe) mode. This is the default for
+               compatibility.
+.. option:: +r Make the generated code reentrant, thus allowing more than one
+               instance of the program to run on an IOC.
+.. option:: -r Generated code is not reentrant. This is the default.
+.. option:: +w Display warning messages. This is the default.
+.. option:: -w Suppress warnings.
+============== ===============================================================
+
+.. versionadded:: 2.2
+
+============== ===============================================================
+Option         Description
+============== ===============================================================
+.. option:: +W Display extra warnings for undefined objects.
+.. option:: -W Suppress extra warnings. This is the default.
+============== ===============================================================
 
 Note that :option:`+a` and :option:`-a` are ignored for calls to
 :c:func:`pvGet` that explicitly specify ``SYNC`` or ``ASYNC`` in the
@@ -81,26 +90,26 @@ compiler option overrides.
 Errors
 ^^^^^^
 
-If *snc* detects an error, it displays a message describing the error
+If :program:`snc` detects an error, it displays a message describing the error
 and the location in the source file and aborts further compilation.
-Note, however, that *snc* does *not* contain a type checker: all it
+Note, however, that :program:`snc` does *not* contain a type checker: all it
 knows (and cares) about C is the syntax. This means that many errors
 will only be found only during the C compilation phase. The C compiler
 will attributed these to the corresponding location in the SNL source
-file, since by default *snc* generates line markers in the output that
+file, since by default :program:`snc` generates line markers in the output that
 point back to the original source. This can be turned off with the
 :option:`-l` ("ell") compiler switch.
 
 Warnings
 ^^^^^^^^
 
-In certain cases *snc* cannot ultimately decide whether the code is
+In certain cases :program:`snc` cannot ultimately decide whether the code is
 erroneous. In such cases it will issue a warning message and continue.
 
 The most prominent example is the use of a variable or CPP macro that
 has not been declared in the SNL code, but could well be defined when
 compiling the generated C code (for example if the declaration has been
-in embedded C code, which *snc* does not interpret at all). Warnings
+in embedded C code, which :program:`snc` does not interpret at all). Warnings
 can be suppressed with the :option:`-w` compiler option.
 
 Note that since version 2.1 you can avoid these warnings by declaring
@@ -110,16 +119,17 @@ C Pre-processor
 ---------------
 
 Depending on the application, it might be useful to pre-process the SNL
-source with a C pre-processor (*cpp*). Using the C pre-processor allows
-you to include other SNL files, define macros, and perform conditional
-compilation. *snc* supports this by interpreting *cpp*-generated line
-markers, so that error and warning messages refer to the line numbers
-in the un-pre-processed SNL source.
+source with a C pre-processor (:program:`cpp`). Using the C
+pre-processor allows you to include other SNL files, define macros, and
+perform conditional compilation. :program:`snc` supports this by
+interpreting :program:`cpp`-generated line markers, so that error and
+warning messages refer to the line numbers in the un-pre-processed SNL
+source.
 
 Complete Build
 --------------
 
-The C code generated by *snc* from an SNL program is not a complete
+The C code generated by :program:`snc` from an SNL program is not a complete
 program, but merely a collection of procedures, data types, and
 variables. The generated procedures are supposed to be called by the
 sequencer library, which must be linked to the program. Furthermore,
diff --git a/documentation/Installation.txt b/documentation/Installation.txt
index a9946b847430f4bd7aecdb8bba7c6536f823e437..22f859dd92ff92095c89d6996a2b265406f7675b 100644
--- a/documentation/Installation.txt
+++ b/documentation/Installation.txt
@@ -342,7 +342,7 @@ program to your application, write something like ::
 
 into your Makefile. Here, ``xyz.st`` is the name of your SNL program, and
 ``abc`` is the name of the library or binary to produce. Note that ``.st``
-files are run through the C preprocessor (*cpp*) before giving them to
+files are run through the C preprocessor (:program:`cpp`) before giving them to
 the SNL compiler. Use the extension ``.stt`` to avoid this. For details,
 see Chapter 4 of the `EPICS Application Developer's Guide`_.
 
diff --git a/documentation/Introduction.txt b/documentation/Introduction.txt
index bcc6b832782fbc64269a812b03397bec1d243a2c..18288b683ffdffff02504e12006d75b43f54e5b3 100644
--- a/documentation/Introduction.txt
+++ b/documentation/Introduction.txt
@@ -45,7 +45,7 @@ of its syntax and semantics are directly inherited from C. The language is
 designed for seamless integration with C code; for instance, you can
 directly call C procedures in SNL action blocks and state transition
 conditions, and the types of variables you can declare in SNL map directly
-to C types. The compiler for SNL (called *snc*, see :doc:`Compiling`) takes
+to C types. The compiler for SNL (called :program:`snc`, see :doc:`Compiling`) takes
 a very minimalistic approach to compilation by generating portable standard
 C89/90 code that works on all platforms supported by EPICS. In fact, most of
 the SNL action code is compiled almost verbatim to C, and the generated code
diff --git a/documentation/Reference.txt b/documentation/Reference.txt
index 917ac1ed951a3a6640f0052dba64e10d471f91ed..1fd830d2fb307388345382c8d0bd2f8a9ff0d009 100644
--- a/documentation/Reference.txt
+++ b/documentation/Reference.txt
@@ -100,7 +100,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 :program:`cpp`.
 
 Program
 -------
@@ -212,35 +212,38 @@ Variable Declarations
    init_declarators: `init_declarators` "," `init_declarator`
    init_declarator: `declarator`
    init_declarator: `declarator` "=" `init_expr`
+   declarator: `variable`
+   declarator: "(" `declarator` ")"
+   declarator: `declarator` `subscript`
+   declarator: `declarator` "(" `param_decls` ")"
    declarator: "*" `declarator`
-   declarator: `direct_declarator`
-   direct_declarator: `variable`
-   direct_declarator: "(" `declarator` ")"
-   direct_declarator: `direct_declarator` `subscript`
-   init_expr: "(" `type_expr` ")" "{" `init_exprs` "}"
+   variable: `identifier`
    init_expr: "{" `init_exprs` "}"
+   init_expr: "(" `type_expr` ")" "{" `init_exprs` "}"
    init_expr: `expr`
    init_exprs: `init_exprs` "," `init_expr`
    init_exprs: `init_expr`
    init_exprs: 
-   variable: `identifier`
-
-Variable declarations are quite similar to C.
 
 .. versionadded:: 2.1
 
 You can declare more than one variable in a single declaration (comma
-separated) and add pointer and array markers (subscripts) ad libitum as well
-as initializers.
+separated) and add pointer and array markers (subscripts) ad libitum as
+well as initializers.
 
-The remain some limitations:
+.. versionadded:: 2.2
+
+Function declarations and initializers with type casts.
 
-* arrays must have a defined size (i.e. the integer in the
-  subscript brackets is not optional as in C)
+The still remain some limitations:
+
+* arrays must have a defined size: the expression inside the subscript
+  brackets is not optional as in C; it must also be an integer literal,
+  not a constant expression as in C.
 * you cannot declare new types or type synonyms
-* you cannot declare functions
-* no qualifiers ("static", "extern", "const" etc.)
-* only certain types are allowed, see below
+* no type qualifiers ("const", "volatile")
+* no storage specifiers ("static", "extern", "auto", register")
+* only certain base types are allowed, see below
 
 Some of these restrictions may be lifted in future versions.
 
@@ -250,24 +253,37 @@ Some of these restrictions may be lifted in future versions.
 Foreign Declarations
 ~~~~~~~~~~~~~~~~~~~~
 
+.. warning::
+
+   Foreign declarations are now deprecated. They might be removed in future
+   versions.
+
 .. productionlist::
-   declaration: "foreign" `declarators` ";"
-   declarators: `declarator`
-   declarators: `declarators` "," `declarator`
+   declaration: "foreign" `variables` ";"
+   variables: `variable`
+   variables: `variables` "," `variable`
 
 .. versionadded:: 2.1
 
-Foreign declarations are used let the SNL compiler know about the existence
-of C variables or C preprocessor macros (without arguments) that have been 
-defined outside the SNL program or in escaped C code. No warning will be
-issued if such a variable or macro is used in the program even if warnings
-are enabled.
+Foreign declarations are used to let the SNL compiler know about the
+existence of C variables or C preprocessor macros (without arguments)
+that have been  defined outside the SNL program or in escaped C code. No
+warning will be issued if such a variable or macro is used in the
+program even if warnings are enabled.
 
 .. versionadded:: 2.2
 
 It is no longer needed to declare struct or union members as foreign
 entities, since the parser no longer confuses them with variables. See
-section `Primary Expression Operators`_ below.
+section `Postfix Operators`_ below.
+
+Also, warnings for undefined entities are now disabled by default. You
+can use the "extra warnings" option :option:`+W` to enable them. In
+contrast to older versions, this will also warn about foreign functions
+when called from SNL code. Note that enabling extra warnings is normally
+not needed: if a variable or function is actually undefined in the
+generated C code, the C compiler will issue a warning (or an error)
+anyway.
 
 
 .. _Types:
@@ -342,25 +358,31 @@ not yet support 64 bit integers.
 Type Expressions
 ~~~~~~~~~~~~~~~~
 
+.. versionadded:: 2.2
+
 .. productionlist::
-   type_expr: `basetype` `opt_abstract_declarator`
-   opt_abstract_declarator: 
-   opt_abstract_declarator: `abstract_declarator`
-   abstract_declarator: "*"
-   abstract_declarator: "*" `direct_abstract_declarator`
-   abstract_declarator: `direct_abstract_declarator`
-   direct_abstract_declarator: "(" `abstract_declarator` ")"
-   direct_abstract_declarator: `direct_abstract_declarator` `subscript`
-   direct_abstract_declarator: `subscript`
-
-Type expressions closely follow declaration syntax just as in C. They are
-used for type casts (`Unary Prefix Operators`_) and the special sizeof
-operator (`Primary Expression Operators`_).
+   type_expr: `basetype`
+   type_expr: `basetype` `abs_decl`
+   abs_decl: "*"
+   abs_decl: "(" `abs_decl` ")"
+   abs_decl: "*" `abs_decl`
+   abs_decl: `abs_decl` "(" `param_decls` ")"
+   abs_decl: `abs_decl` `subscript`
+   abs_decl: "(" `param_decls` ")"
+   abs_decl: `subscript`
+   param_decls: `param_decl`
+   param_decls: `param_decls` "," `param_decl`
+   param_decl: `basetype` `declarator`
+   param_decl: `type_expr`
+
+Type expressions closely follow declaration syntax just as in C. They
+are used for parameter declarations as well as type casts and the
+special sizeof operator (see `Prefix Operators`_).
 
 Strings
 ~~~~~~~
 
-The type :token:`string` is defined in C as::
+The type ``string`` is defined in C as::
 
    typedef char string[MAX_STRING_SIZE];
 
@@ -373,7 +395,7 @@ recommend not to rely too much on the numeric value. (You can use
 .. note::
 
    In contrast to C, in SNL ``string s`` is *not* a synonym for
-   ``char s[MAX_STRING_SIZE]``, since variables of type :token:`string`
+   ``char s[MAX_STRING_SIZE]``, since variables of type ``string``
    are treated differently when it comes to interacting with PVs: the
    former gets requested with type DBR_STRING and a count of one, while
    the latter gets requested with type DBR_CHAR and a count of
@@ -905,7 +927,7 @@ Statements
    statement: "continue" ";"
    statement: "state" `identifier` ";"
    statement: `c_code`
-   statement: "{" `block_defns` `statements` "}"
+   statement: `block`
    statement: "if" "(" `comma_expr` ")" `statement`
    statement: "if" "(" `comma_expr` ")" `statement` "else" `statement`
    statement: "while" "(" `comma_expr` ")" `statement`
@@ -927,10 +949,11 @@ Expressions
 ^^^^^^^^^^^
 
 Formation rules for expressions are listed in groups of descending order
-of precedence.
+of precedence. Precedence is determined by the standard C operator
+precedence table.
 
-Atomic Expression
-~~~~~~~~~~~~~~~~~
+Primary Expressions
+~~~~~~~~~~~~~~~~~~~
 
 .. productionlist::
    expr: `integer_literal`
@@ -938,23 +961,16 @@ Atomic Expression
    expr: `string`
    expr: `variable`
    string: `string_literal`
-
-These are literals and variables.
-
-Parenthesized Expression
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. productionlist::
    expr: "(" `comma_expr` ")"
 
-Primary Expression Operators
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+These are literals, variables, and parenthesized expressions.
+
+Postfix Operators
+~~~~~~~~~~~~~~~~~
 
 .. productionlist::
-   expr: `identifier` "(" `args` ")"
+   expr: `expr` "(" `args` ")"
    expr: "exit" "(" `args` ")"
-   expr: "sizeof" "(" `expr` ")"
-   expr: "sizeof" "(" `type_expr` ")"
    expr: `expr` "[" `expr` "]"
    expr: `expr` "." `member`
    expr: `expr` "->" `member`
@@ -962,24 +978,21 @@ Primary Expression Operators
    expr: `expr` "--"
    member: `identifier`
 
-These are: function call, array subscript, record selection, pointer to
-record selection, and postfix operators (increment and decrement).
+These are all left associative.
 
 .. note::
 
-   :token:`exit` is listed explicitly because it is a keyword, not an
-   identifier, but can also be used as a function.
+   ``exit`` must be listed explicitly because in SNL it is a keyword,
+   not an identifier. The extra rule allows calls to the standard
+   library function ``exit``.
 
-.. note::
+.. versionadded:: 2.2
 
-   SNL makes no use of the semantics of structure member access and
-   struct tags are treated as if they were expressions (variables, in
-   fact). A side-effect is that *snc* will warn that structure tags are
-   "used but not declared", which can be silenced with a :ref:`foreign
-   entities` declaration, just as with variables.
+.. productionlist::
+   expr: "sizeof" "(" `type_expr` ")"
 
-Unary Prefix Operators
-~~~~~~~~~~~~~~~~~~~~~~
+Prefix Operators
+~~~~~~~~~~~~~~~~
 
 .. productionlist::
    expr: "+" `expr`
@@ -991,44 +1004,69 @@ Unary Prefix Operators
    expr: "++" `expr`
    expr: "--" `expr`
 
+Prefix operators are right-associative.
+
 .. versionadded:: 2.2
 
-Type casts:
+Type casts and sizeof operator:
 
 .. productionlist::
    expr: "(" `type_expr` ")" `expr`
+   expr: "sizeof" `expr`
 
-Left-associative Binary Operators
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Binary Operators
+~~~~~~~~~~~~~~~~
 
 .. productionlist::
    expr: `expr` "-" `expr`
    expr: `expr` "+" `expr`
+
+.. productionlist::
+   expr: `expr` "<<" `expr`
+   expr: `expr` ">>" `expr`
+
+.. productionlist::
    expr: `expr` "*" `expr`
    expr: `expr` "/" `expr`
+
+.. productionlist::
    expr: `expr` ">" `expr`
    expr: `expr` ">=" `expr`
-   expr: `expr` "==" `expr`
-   expr: `expr` "!=" `expr`
    expr: `expr` "<=" `expr`
    expr: `expr` "<" `expr`
+
+.. productionlist::
+   expr: `expr` "==" `expr`
+   expr: `expr` "!=" `expr`
+
+.. productionlist::
+   expr: `expr` "&" `expr`
+
+.. productionlist::
+   expr: `expr` "^" `expr`
+
+.. productionlist::
+   expr: `expr` "|" `expr`
+
+.. productionlist::
    expr: `expr` "||" `expr`
+
+.. productionlist::
    expr: `expr` "&&" `expr`
-   expr: `expr` "<<" `expr`
-   expr: `expr` ">>" `expr`
-   expr: `expr` "|" `expr`
-   expr: `expr` "^" `expr`
-   expr: `expr` "&" `expr`
+
+.. productionlist::
    expr: `expr` "%" `expr`
 
+All binary operators associate to the left.
+
 .. note::
 
-   Like in most programming languages, evaluation of conditional
-   expressions using ``&&`` and ``||`` is done *lazily*: the second operand
-   is not evaluated if evaluation of the first already determines the
-   result. This particularly applies to the boolean expressions in
-   :token:`transition` clauses. See the built-in function :c:func:`pvGetQ`
-   for an extended discussion.
+   Like in most programming languages, including C, evaluation of
+   conditional expressions using ``&&`` and ``||`` is done *lazily*: the
+   second operand is not evaluated if evaluation of the first already
+   determines the result. This particularly applies to the boolean
+   expressions in :token:`transition` clauses. See the built-in function
+   :c:func:`pvGetQ` for an extended discussion.
 
 Ternary Operator
 ~~~~~~~~~~~~~~~~
@@ -1164,9 +1202,9 @@ compType
 
 .. note::
 
-   Only ``SYNC`` and ``ASYNC`` are SNL built-in constants (i.e.
-   known to *snc*). The constant ``DEFAULT`` is for use in C code
-   (to represent a missing optional argument).
+   Only ``SYNC`` and ``ASYNC`` are SNL built-in constants (i.e. known to
+   :program:`snc`). The constant ``DEFAULT`` is for use in C code (to
+   represent a missing optional argument).
 
 
 seqBool
@@ -1211,10 +1249,10 @@ statically checked by the compiler.
 
 Several of these functions are intended to be called only from
 :token:`transition` clauses or only from action code. It is safe to call
-them in another context, but the effect is probably not what you want. For
-instance, calling :c:func:`delay` in action code does *not* introduce a
-delay at this point. Later versions of *snc* may output a warning or even
-stop with an error.
+them in another context, but the effect is probably not what you want.
+For instance, calling :c:func:`delay` in action code does *not*
+introduce a delay at this point. Later versions of :program:`snc` may
+output a warning or even stop with an error.
 
 .. todo:: What about changing this so that :c:func:`delay` in action code
    *does* introduce a delay? In other words, compile 'delay(<expr>)' to
@@ -2208,9 +2246,9 @@ by adding a line ::
 
 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 preprocessor macro in SNL code (but not for foreign
-function calls). This can be suppressed by adding a foreign
+For historical reasons, :program:`snc` complains with a warning if you
+use a foreign variable or preprocessor macro in SNL code (but not for
+foreign function calls). This can be suppressed by adding a foreign
 declaration (see `Foreign Entities`_).
 
 
@@ -2218,9 +2256,9 @@ 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*,
-instead it is literally copied to the generated C code. There are two
-escape methods:
+escaped in the program. The escaped code is not compiled by
+:program:`snc`, instead it is literally copied to the generated C code.
+There are two escape methods:
 
 #. Any code between ``%%`` and the next newline character is escaped.
    Example::
@@ -2265,10 +2303,10 @@ 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 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 ::
+You can defer interpretation of a preprocessor directive until after
+:program:`snc` has compiled the code to C, by ensuring that some extra
+non-blank characters appear in front of the ``#`` sign, so
+:program:`cpp` does not recognize the directive. For instance ::
 
    %%#include <abcLib.h>
 
@@ -2340,8 +2378,8 @@ file is always included by the generated C code.
 Variable Modification for Reentrant Option
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-If the reentrant option (:option:`+r`) is specified to *snc* then all
-variables are made part of a structure. Suppose we have the
+If the reentrant option (:option:`+r`) is specified to :program:`snc`
+then all variables are made part of a structure. Suppose we have the
 following top-level declarations in the SNL program::
 
    int sw1;
@@ -2366,7 +2404,7 @@ Reference to variable ``sw1`` is made as ::
 
    pVar->sw1
 
-This conversion is automatically performed by *snc* for all SNL
+This conversion is automatically performed by :program:`snc` for all SNL
 statements, but you will have to handle escaped C code yourself.
 
 .. note::