Expand embedded decision tables and copy supporting code to generate compilable or executable code.
ccide [-V]
ccide [-s [nnn] ]
The output from ccide can be modified (or not) then used as input to ccide
subsequently. In other words if ccide is run as follows:
ccide -b < foobar.d | tee foobar.c | ccide -b > foobar.t
then foobar.c will be identical to foobar.t. (The -b option suppresses
the timestamps that would otherwise cause differences.)
All statements not within a decision table are copied unchanged to STDOUT. Decision tables are analyzed and written to STDOUT. Generated code is written to STDOUT, surrounded by the statements: '//GENERATED_CODE:' and '//END_GENERATED_CODE:'.
If the two '//...GENERATED_CODE:' statements appear in the input file, ccide ignores them and all the statements in between.
If the statement '//CCIDE_INLINE_CODE:' is encountered, ccide generates definitions of CcideFindRule... functions. This code follows the '//CCIDE_INLINE_CODE:' statement and is surrounded by '//...GENERATED_CODE:' statements. If the input contains multiple/P '//CCIDE_INLINE_CODE:' statements, only the first will be expanded.
A decision table takes the following general form:
//DECISION_TABLE: // c0,0 c0,1 c0,2 ... c0,r | e0 // c1,0 c1,1 c1,2 ... c1,r | e1 // ... // cn,0 cn,1 cn,2 ... cn,r | en //------------------------ | -- // r0,0 r0,1 r0,2 ... r0,r | a0 // r1,0 r1,1 r1,2 ... r1,r | a0 // ... // rm,0 rm,1 rm,2 ... rm,r | a0 //END_TABLE:
The '//-----------------------------' statement is required. There may be any number of spaces hyphens(-) and underscores(_), but no other characters except for a single, optional, fence, '|'. The current parser allows multiple fences, but this is not guaranteed.
where c0,0 ... cn,r (condition entries) can be Y(yes), N(no), -(don't care), or a decimal integer from 0 to 99;
r is the number of rules; a rule is defined by a vertical column of conditions and actions through a table;
n is the number of condition rows;
| is a 'fence' which divides the rule entries (left side) from the condition stub or action stub on the right side;
e0 ... en are conditional expressions;
r0,0 ... rm,r (action entries) can be X(act), -(don't care), or a decimal number from 0 to 99; '#' and '/' characters will be ignored, by the current parser.
a0 ... am are action stubs -- program language dependent code;
m is the number of action rows.
Decision table statements may be preceded with whitespace(blanks and tab characters). The generated output will duplicate the whitespace preceding the '//DECISION_TABLE:' statement.
There is no provision for commentary within a table, except as comments may appear in stub entries. However, if all entries are ``don't care'' entries, then the statement is effectively a comment.
Ccide analyzes the table, copies the table to STDOUT, followd by generated code. Every conditional expression is evaluated just once and in the order of appearance in the table. In case all the condition entries are ``Don't care'', the condition is not evaluated, since the condition cannot affect the logical outcome.
When analyzing the table, ccide reorders the rules, placing the more specific rules in front of less specific rules. You can safely assume that the order of rules in the table has no effect on the resulting program and accordingly you should enter rules in whatever order is most convenient(readable).
If integers appear as condition or action entries, a '$$' in the row stub will be replaced by the entry integer. A separate row is generated, in effect, for each unique digit that appears as a rule entry in the original row.
If NEWGROUP appears as a condition stub, ccide will generate code to test the group variable against the integers supplied in the condition entries. Effectively, ccide will replace ``NEWGROUP'' with ``ccide_group == $$''.
If 'NEWGROUP' appears as the last action stub, the integer variable, 'ccide_group' (initially = 1), will be assigned the integer value specified in the appropriate rule and the table will be re-entered from the beginning. This has the effect of combining two, or more, smaller tables into one larger table. There should be a corresponding condition stub which checks for the ccide_group value. Like this:
1 2 2 2 2 3 | NEWGROUP .... ----------------------- .... 2 2 2 2 3 - | NEWGROUP
In the preceding example, the decision table will be left(not re-entered) when rule 6 finally takes effect.
If '$@' appears in an action stub, ccide will replace the $@ with the name of the decision table entry point. This is mainly useful when NEWGROUP is not used in an action stub --- something like this:
X - | goto $@;
Note that the substitution delimiters(``$$'' and ``$@'' may be replaced by invoking the '-d' option on the command line.
Ccide employs one of two functions, CcideFindRule or CcideFindRuleYes, in a 'switch' statement to select actions to be taken. The numbers in the generated 'case' statements do not correspond to the decision table rule numbers, so a comment is appended to the case statement giving the number of the applicable rule, starting with rule 1 at the leftmost column.
Ccide optimizes case output sequence by reordering cases so as to minimize action stub generation redundancy.
All cases are labeled with a string showing the table number and the case number. This allows ccide to use goto's to reduce the amount of output in some situations.
Ccide reduces the amount of generated code by combining cases wherever appropriate. I.e., if two cases specify the same set of actions, the actions are generated only once, preceded by the two case statements.
Regardless of any other reordering, ccide always evaluates conditions in the sequence given in the decision table. Actions(when taken) are also performed in the order given. This strategy helps avoid problems with side effects.
The function, CcideFindRuleYes, is employed when there are no 'N' condition entries in the table. Performance will be somewhat improved in this case. There is no corresponding, CcideFindRuleNo, function. In the highly unusual situation where there are no 'Y' condition entries, ccide performance can be improved slightly by reversing the logic of all the condition stubs and replacing all the 'N' condition entries with 'Y' entries.
In the special case where a single condition row containing integers(and
no '-'s(don't care) is specified and the condition stub is in the form
of:
... | EXPRESSION == $$
ccide will generate more efficient 'state machine' code replacing the CcideFindRule.. function with a switch(EXPRESSION) statement, and using the row integers in a case statement. NEWGROUP may be specified as the last action, and will cause a 'goto' back to the switch statement. However, the ccide-group variable will not be set. Highly complex state machines depending on N variables can be efficiently defined by using an N dimensioned array to contain the state values for N variables.
See ccidemain.c or one of the '.in' suffix files for examples of decision tables.
Alphabetic entries (Y,N, and X) may be upper or lower case. Generated entries will be upper case.
Ccide is a wrapper script for, ccidew, the actual decision table processing engine. For C language tables, ccidew generates all the output. For other languages, ccidew generates M4 output which is processed by the m4 macro processor. There is no guarantee that this arrangement will continue in future releases. In other words, use 'ccide' not 'ccidew' in your projects.
-b The -b(blanktime) option causes ccide to bypass
timestamping output.
-c The -c(colum size) option sets the number of characters that ccide
assigns to each output rule.
-d The -d(CCIDE Delimiter) option repaces the two stub substitution
strings (``$$'' and ``$@'') with SUBSTITUTE_STRING1 and SUBSTITUTE_STRING2, respectively.
SUBSTITUTE_STRING1 and SUBSTITUTE_STRING2 may be any reasonable size, but may not be NULL, nor
may SUBSTITUTE_STRING1 equal SUBSTITUTE_STRING2. Neither string may contain a single
quote ``''' nor a back quote ```''. These two quote characters are used
as delimiters by m4. In case of multiple -d options the last one
remains in effect.
If -L BASH is specified, "$$" and "$@" are replaced with "/::" and "@@/". These can be replaced using the B<-d> option after the <-L> option. If, for instance, ccide -L BASH -d "/!!!" "&&&/" is specified, the delimiters "/!!!" and "&&&/" will be used. It is almost always a good idea to avoid quotes('`"), brackets([]), braces({}), semicolons(;), number signs(#), dollar signs($), hyphens(-), backslashes(\), and underscores(_) in bash delimiters.
-e ccide normally checks condition stub expressions for
a single equal sign '=' (double equal sign '==' is OK), and
issues an error message if one is found. The
-e option bypasses this check. This option is automatic
for euphoria programs (lang=ex).
If the -m4 output option is in effect, single quotes ("'") and backquotes("`") are not allowed in condition or action stubs. For BASH scripts use the, "$(command)", form of command substitution instead of the back quote form, "`command`". Use functions, as necessary, to avoid syntax problems with quotes.
-l The -l(localtime) option causes ccide to use local time
instead of UTC on timestamps.
-L The -L(language) option determines the output programming language
for ccide. In case of multiple -L options, the last one
remains in effect.
-m4 Produce m4 output instead of C code. The m4 output can be
used to create language independent decision table code.
This option is useful when working with an unsupported
language.
-n The -n option causes ccide to suppress the generation
of inline code when the ``//CCIDE_INLINE_CODE:'' statement
is encountered. This is useful when multiple source files
contain the ``//CCIDE_INLINE_CODE:'' statement.
-p The -p STRING option changes the ``CCIDE'' prefix in generated code
to the supplied STRING. STRING can contain only alphanumeric
characters and the underscore('_').
-q The -q(m4 quote) option changes the characters ccide uses
in output m4 macros from the default ```'' and ``''' to the supplied
LEFTQUOTE and RIGHTQUOTE strings, which must differ from each other
and from the ccide delimiters.
In case -L BASH has been specified, "^^^" and "%%%" replace the LEFTQUOTE and RIGHTQUOTE strings, "`" and "'", in order to reduce the possibility of ambiguous m4 input. It is not a good idea to replace these strings later in the command line, since the supplied BASH m4 macro file depends on these.
-s The -s [n] option causes ccide to produce an example, skeleton,
program on STDOUT, then terminate with return code 0.
The -s option can be followed by an optional integer(default 4)
defining the size of the table. You can test ccide this way,
'ccide -s 10 | ccide ', without having a decision table of your own.
-t The -t(trace) option causes ccide to set the parser
yydebug parameter. This will cause the parser to issue
a flood of debugging messages on STDERR.
-u The -u(undo) option causes ccide to not generate
any code, effectively recreating its original input.
-V The -V option causes ccide to display the software version
and a copyright notice on STDERR, and terminate with return code 0.
-x The -x option causes ccide add a ``don't care'' rule to every
decision table. Multiple -x options cause multiple rules
to be added. This option is intended to save clerical effort
when adding rules to tables. A don't care rule can also serve
to complete a table (an incomplete table does not account for
all condition permutations). Ccide does not check to ensure that
tables are complete, as most real world tables are incomplete
and it would become annoying to keep pointing them out.
--help
The --help option causes ccide to display a ccide usage
synopsis on STDOUT and terminate with return code 0.
The message ``Rules x and y overlap.'' is issued when a rule cannot take effect. The program is not terminated and the return code is not set --- will be 0, unless other errors are detected.
A usage message is issued when the '--help' option is supplied or if an option is not recognizable.
The message ``Error in line ...: Inconsistent number of rules. near ''. State=7'' is written to STDERR and a more informative message is written to STDOUT when a row is found with the wrong number of rule entries.
Error messages are issued and the return code is set to 1, if a condition stub or action stub exactly matches a preceding condition or action stub, respectively. The -a option allows duplicate actions without any errors.
Unless the -e option is specified, ccide will issue an error message when a single equal sign(=) is encountered in a condition stub expression. (A single equal sign is almost always a logic error --- in C programs, anyway.)
/* The beginning of the program. */ #ifdef CCIDE_LIB #include <ccide.h> #else //CCIDE_INLINE_CODE: #endif
/* Supporting code */ //DECISION_TABLE: // 1 3 2 2 | light == $$ /* 1=red, 2= yellow, 3=green. */ // N - - - | speed == STOPPED // - - Y - | speed == SLOW // - N - Y | speed == FAST // _________________________ // X - X - | Stop(); // - - - X | SlowDown(); // - X - - | SpeedUp(); //END_TABLE: /* End of the program. */
Explanation:
The //CCIDE_INLINE_CODE: statement causes ccide to
generate the CcideFindRule... functions in source form.
To avoid linkedit clashes, only one module in a
multi-module program should contain these functions.
The #ifdef CCIDE_LIB ... logic gives the compiler a chance to eliminate the generated functions; to link the program with a separately compiled module later on. In this case, the ccide.h file provides prototypes for the CcideFindRule... functions.
Rule 1 states that if the light is red and your car is moving, then stop.
M4 is required only for processing other than C language input. Anyway, m4 is itself widely distributed.
It is intended that future versions of ccide will be backward compatible, i.e. if this version of ccide produces correct, compilable output, any future version will also.
The current scheme of using a wrapper script, ccide, and separate executable will continue unless a new ccide program replaces them both --- a very unlikely event, as this would raise some new portability issues.
There can be any number of decision tables in a single module or program.
There can be any number of statements, other than decision table statements in a program.
Please note that the GPL imposes no license or distribution restrictions on programs which are developed using ccide.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
It can be downloaded from SourceForge at
http://www.sourceforge.net/projects/ccide
Last changed 2010/07/13