extend calc, calcout and sub records and calc expressions to inputs A - U
To accomodate for the increased number of inputs, the size of CALC and OCAL fields has been doubled to 160 characters.
This commit is contained in:
7
documentation/new-notes/PR-655.md
Normal file
7
documentation/new-notes/PR-655.md
Normal file
@@ -0,0 +1,7 @@
|
||||
### Records calc, calcout and sub extended
|
||||
|
||||
The record types calc, calcout and sub have been extended from 12 inputs
|
||||
A - L to 21 inputs A - U.
|
||||
The macro `CALCPERFORM_NARGS` reflects this change.
|
||||
The new inputs can be used in calc links and access security as well.
|
||||
The size of CALC and OCAL fields has been doubled to 160 chars.
|
||||
@@ -81,11 +81,13 @@ link(calc, lnkCalcIf)
|
||||
=head3 Calculation Link C<"calc">
|
||||
|
||||
A calculation link is an input link that can evaluate mathematical expressions
|
||||
on scalar (double-precision floating-point) values obtained from up to 12 child
|
||||
on scalar (double-precision floating-point) values obtained from up to 21 child
|
||||
input links, and returns a double-precision floating-point result. The
|
||||
expression is evaluated by the EPICS Calc engine, and the result is returned as
|
||||
the value of the link.
|
||||
|
||||
Since UNRELEASED the number of inputs has been increased from 12 to 21.
|
||||
|
||||
Two additional expressions may also be provided and are evaluated to determine
|
||||
whether the record owning the link should be placed in alarm state. In both
|
||||
cases the result of the main calculation is available to these expressions as
|
||||
@@ -95,7 +97,7 @@ record will be placed in C<LINK/MAJOR> alarm. If not and the C<minor> expression
|
||||
evaluates to non-zero the record will be placed in C<LINK/MINOR> alarm state.
|
||||
|
||||
A calculation link can also be an output link, with the scalar output value
|
||||
being converted to a double and provided to the expression as C<VAL>. Up to 12
|
||||
being converted to a double and provided to the expression as C<VAL>. Up to 21
|
||||
additional input links can also be read and provided to the expression as above.
|
||||
The result of the calculation is forwarded to a child output link specified in
|
||||
the link's C<out> parameter.
|
||||
@@ -126,8 +128,8 @@ An optional expression that returns non-zero to raise a minor alarm.
|
||||
|
||||
=item args
|
||||
|
||||
A JSON list of up to 12 input arguments for the expression, which are assigned
|
||||
to the inputs C<A>, C<B>, C<C>, ... C<L>. Each input argument may be either a
|
||||
A JSON list of up to 24 input arguments for the expression, which are assigned
|
||||
to the inputs C<A>, C<B>, C<C>, ... C<U>. Each input argument may be either a
|
||||
numeric literal or an embedded JSON link inside C<{}> braces. The same input
|
||||
values are provided to the two alarm expressions as to the primary expression.
|
||||
|
||||
@@ -149,7 +151,7 @@ result should be displayed. Equivalent to the C<PREC> field of a record.
|
||||
|
||||
=item time
|
||||
|
||||
An optional string containing a single upper or lower-case letter C<A> ... C<L>
|
||||
An optional string containing a single upper or lower-case letter C<A> ... C<U>
|
||||
which must correspond to an input provided in the C<args> parameter. When the
|
||||
record containing such a link has C<TSEL> set to -2 (epicsTimeEventDeviceTime)
|
||||
the record's timestamp field C<TIME> will be read from the indicated input link
|
||||
|
||||
@@ -177,7 +177,7 @@ static jlif_result lnkCalc_string(jlink *pjlink, const char *val, size_t len)
|
||||
if (clink->pstate == ps_time) {
|
||||
char tinp;
|
||||
|
||||
if (len != 1 || (tinp = toupper((int) val[0])) < 'A' || tinp > 'L') {
|
||||
if (len != 1 || (tinp = toupper((int) val[0])) < 'A' || tinp >= 'A' + CALCPERFORM_NARGS) {
|
||||
errlogPrintf("lnkCalc: Bad 'time' parameter \"%.*s\"\n", (int) len, val);
|
||||
return jlif_stop;
|
||||
}
|
||||
|
||||
@@ -159,9 +159,9 @@ static long special(DBADDR *paddr, int after)
|
||||
#define indexof(field) calcRecord##field
|
||||
|
||||
static long get_linkNumber(int fieldIndex) {
|
||||
if (fieldIndex >= indexof(A) && fieldIndex <= indexof(L))
|
||||
if (fieldIndex >= indexof(A) && fieldIndex < indexof(A) + CALCPERFORM_NARGS)
|
||||
return fieldIndex - indexof(A);
|
||||
if (fieldIndex >= indexof(LA) && fieldIndex <= indexof(LL))
|
||||
if (fieldIndex >= indexof(LA) && fieldIndex < indexof(LA) + CALCPERFORM_NARGS)
|
||||
return fieldIndex - indexof(LA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ and logical operations on values retrieved from other records. The result
|
||||
of its operations can then be accessed by another record so that it can
|
||||
then be used.
|
||||
|
||||
Since UNRELEASED the number of inputs has been increased from 12 to 21.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
@@ -34,9 +36,9 @@ These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
|
||||
=head3 Read Parameters
|
||||
|
||||
The read parameters for the Calc record consist of 12 input links INPA,
|
||||
INPB, ... INPL. The fields can be database links, channel access links, or
|
||||
constants. If they are links, they must specify another record's field or a
|
||||
The read parameters for the Calc record consist of 21 input links INPA -
|
||||
INPU. The fields can be database links, channel access links, or constants.
|
||||
If they are links, they must specify another record's field or a
|
||||
channel access link. If they are constants, they will be initialized with
|
||||
the value they are configured with and can be changed via C<dbPuts>. They
|
||||
cannot be hardware addresses.
|
||||
@@ -45,7 +47,7 @@ See L<Address
|
||||
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
||||
for information on how to specify database links.
|
||||
|
||||
=fields INPA - INPL
|
||||
=fields INPA - INPU
|
||||
|
||||
=head3 Expression
|
||||
|
||||
@@ -117,7 +119,7 @@ radians to degrees
|
||||
|
||||
The expression uses the values retrieved from the INPx links as operands,
|
||||
though constants can be used as operands too. These values retrieved from
|
||||
the input links are stored in the A-L fields. The values to be used in the
|
||||
the input links are stored in the A-U fields. The values to be used in the
|
||||
expression are simply referenced by the field letter. For instance, the
|
||||
value obtained from INPA link is stored in the field A, and the value
|
||||
obtained from INPB is stored in field B. The field names can be included in
|
||||
@@ -125,7 +127,7 @@ the expression which will operate on their respective values, as in A+B.
|
||||
Also, the RNDM nullary function can be included as an operand in the
|
||||
expression in order to generate a random number between 0 and 1.
|
||||
|
||||
=fields A - L
|
||||
=fields A - U
|
||||
|
||||
The keyword VAL returns the current contents of the VAL field (which can be
|
||||
written to by a CA put, so it might I<not> be the result from the last time
|
||||
@@ -549,12 +551,12 @@ modifiable at run-time. They are used to process the record.
|
||||
The LALM field is used to implement the hysteresis factor for the alarm
|
||||
limits.
|
||||
|
||||
The LA-LL fields are used to decide when to trigger monitors for the
|
||||
The LA-LU fields are used to decide when to trigger monitors for the
|
||||
corresponding fields. For instance, if LA does not equal the value A,
|
||||
monitors for A are triggered. The MLST and ALST fields are used in the same
|
||||
manner for the VAL field.
|
||||
|
||||
=fields LALM, ALST, MLST, LA - LL
|
||||
=fields LALM, ALST, MLST, LA - LU
|
||||
|
||||
=cut
|
||||
|
||||
@@ -569,7 +571,7 @@ manner for the VAL field.
|
||||
promptgroup("30 - Action")
|
||||
special(SPC_CALC)
|
||||
pp(TRUE)
|
||||
size(80)
|
||||
size(160)
|
||||
initial("0")
|
||||
}
|
||||
field(INPA,DBF_INLINK) {
|
||||
@@ -632,6 +634,60 @@ manner for the VAL field.
|
||||
promptgroup("42 - Input G-L")
|
||||
interest(1)
|
||||
}
|
||||
field(INPM,DBF_INLINK) {
|
||||
prompt("Input M")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPN,DBF_INLINK) {
|
||||
prompt("Input N")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPO,DBF_INLINK) {
|
||||
prompt("Input O")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPP,DBF_INLINK) {
|
||||
prompt("Input P")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPQ,DBF_INLINK) {
|
||||
prompt("Input Q")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPR,DBF_INLINK) {
|
||||
prompt("Input R")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPS,DBF_INLINK) {
|
||||
prompt("Input S")
|
||||
special(SPC_MOD)
|
||||
promptgroup("44 - Input S-U")
|
||||
interest(1)
|
||||
}
|
||||
field(INPT,DBF_INLINK) {
|
||||
prompt("Input T")
|
||||
special(SPC_MOD)
|
||||
promptgroup("44 - Input S-U")
|
||||
interest(1)
|
||||
}
|
||||
field(INPU,DBF_INLINK) {
|
||||
prompt("Input U")
|
||||
special(SPC_MOD)
|
||||
promptgroup("44 - Input S-U")
|
||||
interest(1)
|
||||
}
|
||||
field(EGU,DBF_STRING) {
|
||||
prompt("Engineering Units")
|
||||
promptgroup("80 - Display")
|
||||
@@ -790,6 +846,42 @@ manner for the VAL field.
|
||||
prompt("Value of Input L")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(M,DBF_DOUBLE) {
|
||||
prompt("Value of Input M")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(N,DBF_DOUBLE) {
|
||||
prompt("Value of Input N")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(O,DBF_DOUBLE) {
|
||||
prompt("Value of Input O")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(P,DBF_DOUBLE) {
|
||||
prompt("Value of Input P")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(Q,DBF_DOUBLE) {
|
||||
prompt("Value of Input Q")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(R,DBF_DOUBLE) {
|
||||
prompt("Value of Input R")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(S,DBF_DOUBLE) {
|
||||
prompt("Value of Input S")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(T,DBF_DOUBLE) {
|
||||
prompt("Value of Input T")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(U,DBF_DOUBLE) {
|
||||
prompt("Value of Input U")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(LA,DBF_DOUBLE) {
|
||||
prompt("Prev Value of A")
|
||||
special(SPC_NOMOD)
|
||||
@@ -850,6 +942,51 @@ manner for the VAL field.
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LM,DBF_DOUBLE) {
|
||||
prompt("Prev Value of M")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LN,DBF_DOUBLE) {
|
||||
prompt("Prev Value of N")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LO,DBF_DOUBLE) {
|
||||
prompt("Prev Value of O")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LP,DBF_DOUBLE) {
|
||||
prompt("Prev Value of P")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LQ,DBF_DOUBLE) {
|
||||
prompt("Prev Value of Q")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LR,DBF_DOUBLE) {
|
||||
prompt("Prev Value of R")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LS,DBF_DOUBLE) {
|
||||
prompt("Prev Value of S")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LT,DBF_DOUBLE) {
|
||||
prompt("Prev Value of T")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LU,DBF_DOUBLE) {
|
||||
prompt("Prev Value of U")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LALM,DBF_DOUBLE) {
|
||||
prompt("Last Value Alarmed")
|
||||
special(SPC_NOMOD)
|
||||
@@ -870,7 +1007,7 @@ manner for the VAL field.
|
||||
prompt("Reverse Polish Calc")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
|
||||
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(160)]")
|
||||
}
|
||||
|
||||
=head2 Record Support
|
||||
@@ -970,7 +1107,7 @@ Archive and values change monitors are invoked if ADEL and MDEL conditions
|
||||
are met.
|
||||
|
||||
=item *
|
||||
Monitors for A-L are checked whenever other monitors are invoked.
|
||||
Monitors for A-U are checked whenever other monitors are invoked.
|
||||
|
||||
=item *
|
||||
NSEV and NSTA are reset to 0.
|
||||
|
||||
@@ -355,6 +355,15 @@ static long special(DBADDR *paddr, int after)
|
||||
case(calcoutRecordINPJ):
|
||||
case(calcoutRecordINPK):
|
||||
case(calcoutRecordINPL):
|
||||
case(calcoutRecordINPM):
|
||||
case(calcoutRecordINPN):
|
||||
case(calcoutRecordINPO):
|
||||
case(calcoutRecordINPP):
|
||||
case(calcoutRecordINPQ):
|
||||
case(calcoutRecordINPR):
|
||||
case(calcoutRecordINPS):
|
||||
case(calcoutRecordINPT):
|
||||
case(calcoutRecordINPU):
|
||||
case(calcoutRecordOUT):
|
||||
lnkIndex = fieldIndex - calcoutRecordINPA;
|
||||
plink = &prec->inpa + lnkIndex;
|
||||
@@ -406,9 +415,9 @@ static long special(DBADDR *paddr, int after)
|
||||
#define indexof(field) calcoutRecord##field
|
||||
|
||||
static long get_linkNumber(int fieldIndex) {
|
||||
if (fieldIndex >= indexof(A) && fieldIndex <= indexof(L))
|
||||
if (fieldIndex >= indexof(A) && fieldIndex < indexof(A) + CALCPERFORM_NARGS)
|
||||
return fieldIndex - indexof(A);
|
||||
if (fieldIndex >= indexof(LA) && fieldIndex <= indexof(LL))
|
||||
if (fieldIndex >= indexof(LA) && fieldIndex < indexof(LA) + CALCPERFORM_NARGS)
|
||||
return fieldIndex - indexof(LA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ rather than the DBF_STRING fields used in the Wait record. For new
|
||||
databases, it is recommended that the Calcout record be used instead of the
|
||||
Wait record.
|
||||
|
||||
Since UNRELEASED the number of inputs has been increased from 12 to 21.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
@@ -57,18 +59,18 @@ These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
|
||||
=head3 Read Parameters
|
||||
|
||||
The read parameters for the Calcout record consists of 12 input links INPA,
|
||||
INPB, ... INPL. The fields can be database links, channel access links, or
|
||||
constants. If they are links, they must specify another record's field. If
|
||||
The read parameters for the Calcout record consists of 21 input links INPA -
|
||||
INPU. The fields can be database links, channel access links, or constants.
|
||||
If they are links, they must specify another record's field. If
|
||||
they are constants, they will be initialized with the value they are
|
||||
configured with and can be changed via C<dbPuts>. These fields cannot be
|
||||
hardware addresses. In addition, the Calcout record contains the INAV,
|
||||
INBV, ... INLV fields which indicate the status of the link fields, for
|
||||
hardware addresses. In addition, the Calcout record contains the INAV -
|
||||
INUV fields which indicate the status of the link fields, for
|
||||
example, whether or not the specified PV was found and a link to it
|
||||
established. See L<Operator Display Parameters> for an explanation of these
|
||||
fields.
|
||||
|
||||
=fields INPA - INPL
|
||||
=fields INPA - INPU
|
||||
|
||||
=head3 Expressions
|
||||
|
||||
@@ -146,14 +148,14 @@ angle from radians to degrees
|
||||
|
||||
The expression can use the values retrieved from the INPx links as
|
||||
operands, though constants can be used as operands too. These values
|
||||
retrieved from the input links are stored in the A-L fields. The values to
|
||||
retrieved from the input links are stored in the A-U fields. The values to
|
||||
be used in the expression are simple references by the field letter. For
|
||||
instance, the value obtained from the INPA link is stored in field A, and
|
||||
the values obtained from the INPB link is stored in the field B. The names
|
||||
can be included in the expression will operate on their respective values,
|
||||
as in A+B.
|
||||
|
||||
=fields A - L
|
||||
=fields A - U
|
||||
|
||||
The keyword VAL returns the current contents of the expression's result
|
||||
field, i.e. the VAL field for the CALC expression and the OVAL field for
|
||||
@@ -604,8 +606,8 @@ LOW, and LOLO fields. PREC controls the precision of the VAL field.
|
||||
|
||||
=head4 Menu calcoutINAV
|
||||
|
||||
The INAV-INLV fields indicate the status of the link to the PVs specified
|
||||
in the INPA-INPL fields respectively. These fields can have four possible
|
||||
The INAV-INUV fields indicate the status of the link to the PVs specified
|
||||
in the INPA-INPU fields respectively. These fields can have four possible
|
||||
values:
|
||||
|
||||
=menu calcoutINAV
|
||||
@@ -629,7 +631,7 @@ C<Constant> -- the corresponding link field is a constant.
|
||||
=back
|
||||
|
||||
The OUTV field indicates the status of the OUT link. If has the same
|
||||
possible values as the INAV-INLV fields.
|
||||
possible values as the INAV-INUV fields.
|
||||
|
||||
The CLCV and OLCV fields indicate the validity of the expression in the
|
||||
CALC and OCAL fields respectively. If the expression in invalid, the field
|
||||
@@ -640,7 +642,7 @@ The DLYA field is set to one during the delay specified in ODLY.
|
||||
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
|
||||
Parameters> for more on the record name (NAME) and description (DESC) fields.
|
||||
|
||||
=fields EGU, PREC, HOPR, LOPR, INAV - INLV, OUTV, CLCV, OCLV, DLYA, NAME, DESC
|
||||
=fields EGU, PREC, HOPR, LOPR, INAV - INUV, OUTV, CLCV, OCLV, DLYA, NAME, DESC
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
@@ -684,12 +686,12 @@ modifiable at run-time. They are used to process the record.
|
||||
The LALM field is used to implement the hysteresis factor for the alarm
|
||||
limits.
|
||||
|
||||
The LA-LL fields are used to decide when to trigger monitors for the
|
||||
The LA-LU fields are used to decide when to trigger monitors for the
|
||||
corresponding fields. For instance, if LA does not equal the value for A,
|
||||
monitors for A are triggered. The MLST and ALST fields are used in the same
|
||||
manner for the VAL field.
|
||||
|
||||
=fields LALM, ALST, MLST, LA - LL
|
||||
=fields LALM, ALST, MLST, LA - LU
|
||||
|
||||
=cut
|
||||
|
||||
@@ -721,7 +723,7 @@ manner for the VAL field.
|
||||
promptgroup("30 - Action")
|
||||
special(SPC_CALC)
|
||||
pp(TRUE)
|
||||
size(80)
|
||||
size(160)
|
||||
initial("0")
|
||||
}
|
||||
field(CLCV,DBF_LONG) {
|
||||
@@ -800,6 +802,60 @@ manner for the VAL field.
|
||||
promptgroup("42 - Input G-L")
|
||||
interest(1)
|
||||
}
|
||||
field(INPM,DBF_INLINK) {
|
||||
prompt("Input M")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPN,DBF_INLINK) {
|
||||
prompt("Input N")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPO,DBF_INLINK) {
|
||||
prompt("Input O")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPP,DBF_INLINK) {
|
||||
prompt("Input P")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPQ,DBF_INLINK) {
|
||||
prompt("Input Q")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPR,DBF_INLINK) {
|
||||
prompt("Input R")
|
||||
special(SPC_MOD)
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPS,DBF_INLINK) {
|
||||
prompt("Input S")
|
||||
special(SPC_MOD)
|
||||
promptgroup("44 - Input S-U")
|
||||
interest(1)
|
||||
}
|
||||
field(INPT,DBF_INLINK) {
|
||||
prompt("Input T")
|
||||
special(SPC_MOD)
|
||||
promptgroup("44 - Input S-U")
|
||||
interest(1)
|
||||
}
|
||||
field(INPU,DBF_INLINK) {
|
||||
prompt("Input U")
|
||||
special(SPC_MOD)
|
||||
promptgroup("44 - Input S-U")
|
||||
interest(1)
|
||||
}
|
||||
field(OUT,DBF_OUTLINK) {
|
||||
prompt("Output Specification")
|
||||
special(SPC_MOD)
|
||||
@@ -890,6 +946,69 @@ manner for the VAL field.
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(INMV,DBF_MENU) {
|
||||
prompt("INPM PV Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(INNV,DBF_MENU) {
|
||||
prompt("INPN PV Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(INOV,DBF_MENU) {
|
||||
prompt("INPO PV Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(INPV,DBF_MENU) {
|
||||
prompt("INPP PV Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(INQV,DBF_MENU) {
|
||||
prompt("INPQ PV Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(INRV,DBF_MENU) {
|
||||
prompt("INPR PV Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(INSV,DBF_MENU) {
|
||||
prompt("INPS PV Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(INTV,DBF_MENU) {
|
||||
prompt("INPT PV Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(INUV,DBF_MENU) {
|
||||
prompt("INPU PV Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
menu(calcoutINAV)
|
||||
initial("1")
|
||||
}
|
||||
field(OUTV,DBF_MENU) {
|
||||
prompt("OUT PV Status")
|
||||
special(SPC_NOMOD)
|
||||
@@ -924,7 +1043,7 @@ manner for the VAL field.
|
||||
promptgroup("30 - Action")
|
||||
special(SPC_CALC)
|
||||
pp(TRUE)
|
||||
size(80)
|
||||
size(160)
|
||||
initial("0")
|
||||
}
|
||||
field(OCLV,DBF_LONG) {
|
||||
@@ -1104,6 +1223,42 @@ manner for the VAL field.
|
||||
prompt("Value of Input L")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(M,DBF_DOUBLE) {
|
||||
prompt("Value of Input M")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(N,DBF_DOUBLE) {
|
||||
prompt("Value of Input N")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(O,DBF_DOUBLE) {
|
||||
prompt("Value of Input O")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(P,DBF_DOUBLE) {
|
||||
prompt("Value of Input P")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(Q,DBF_DOUBLE) {
|
||||
prompt("Value of Input Q")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(R,DBF_DOUBLE) {
|
||||
prompt("Value of Input R")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(S,DBF_DOUBLE) {
|
||||
prompt("Value of Input S")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(T,DBF_DOUBLE) {
|
||||
prompt("Value of Input T")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(U,DBF_DOUBLE) {
|
||||
prompt("Value of Input U")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(OVAL,DBF_DOUBLE) {
|
||||
prompt("Output Value")
|
||||
asl(ASL0)
|
||||
@@ -1168,6 +1323,51 @@ manner for the VAL field.
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LM,DBF_DOUBLE) {
|
||||
prompt("Prev Value of M")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LN,DBF_DOUBLE) {
|
||||
prompt("Prev Value of N")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LO,DBF_DOUBLE) {
|
||||
prompt("Prev Value of O")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LP,DBF_DOUBLE) {
|
||||
prompt("Prev Value of P")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LQ,DBF_DOUBLE) {
|
||||
prompt("Prev Value of Q")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LR,DBF_DOUBLE) {
|
||||
prompt("Prev Value of R")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LS,DBF_DOUBLE) {
|
||||
prompt("Prev Value of S")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LT,DBF_DOUBLE) {
|
||||
prompt("Prev Value of T")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LU,DBF_DOUBLE) {
|
||||
prompt("Prev Value of U")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(POVL,DBF_DOUBLE) {
|
||||
prompt("Prev Value of OVAL")
|
||||
asl(ASL0)
|
||||
@@ -1192,13 +1392,13 @@ manner for the VAL field.
|
||||
prompt("Reverse Polish Calc")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
|
||||
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(160)]")
|
||||
}
|
||||
field(ORPC,DBF_NOACCESS) {
|
||||
prompt("Reverse Polish OCalc")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("char orpc[INFIX_TO_POSTFIX_SIZE(80)]")
|
||||
extra("char orpc[INFIX_TO_POSTFIX_SIZE(160)]")
|
||||
}
|
||||
|
||||
=head2 Record Support
|
||||
@@ -1307,7 +1507,7 @@ Archive and value change monitors are invoked if ADEL and MDEL conditions
|
||||
are met.
|
||||
|
||||
=item *
|
||||
Monitors for A-L are checked whenever other monitors are invoked.
|
||||
Monitors for A-U are checked whenever other monitors are invoked.
|
||||
|
||||
=item *
|
||||
NSEV and NSTA are reset to 0
|
||||
|
||||
@@ -86,7 +86,7 @@ static long do_sub(subRecord *);
|
||||
static long fetch_values(subRecord *);
|
||||
static void monitor(subRecord *);
|
||||
|
||||
#define INP_ARG_MAX 12
|
||||
#define INP_ARG_MAX 21
|
||||
|
||||
static long init_record(struct dbCommon *pcommon, int pass)
|
||||
{
|
||||
@@ -196,9 +196,9 @@ static long special(DBADDR *paddr, int after)
|
||||
#define indexof(field) subRecord##field
|
||||
|
||||
static long get_linkNumber(int fieldIndex) {
|
||||
if (fieldIndex >= indexof(A) && fieldIndex <= indexof(L))
|
||||
if (fieldIndex >= indexof(A) && fieldIndex < indexof(A) + INP_ARG_MAX)
|
||||
return fieldIndex - indexof(A);
|
||||
if (fieldIndex >= indexof(LA) && fieldIndex <= indexof(LL))
|
||||
if (fieldIndex >= indexof(LA) && fieldIndex < indexof(LA) + INP_ARG_MAX)
|
||||
return fieldIndex - indexof(LA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
The subroutine record is used to call a C initialization routine and a recurring
|
||||
scan routine. There is no device support for this record.
|
||||
|
||||
Since UNRELEASED the number of inputs has been increased from 12 to 21.
|
||||
|
||||
=recordtype sub
|
||||
|
||||
=cut
|
||||
@@ -30,17 +32,17 @@ These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
||||
|
||||
=head3 Read Parameters
|
||||
|
||||
The subroutine record has twelve input links (INPA-INPL), each of which has a
|
||||
corresponding value field (A-L). These fields are used to retrieve and store
|
||||
The subroutine record has 21 input links INPA - INPU, each of which has a
|
||||
corresponding value field A - U. These fields are used to retrieve and store
|
||||
values that can be passed to the subroutine that the record calls.
|
||||
|
||||
The input links can be either channel access or database links, or constants.
|
||||
When constants, the corresponding value field for the link is initialized with
|
||||
the constant value and the field's value can be changed at run-time via dbPuts.
|
||||
Otherwise, the values for (A-F) are fetched from the input links when the record
|
||||
is processed.
|
||||
Otherwise, the values for A - U are fetched from the input links when the
|
||||
record is processed.
|
||||
|
||||
=fields INPA - INPL, A - L
|
||||
=fields INPA - INPU, A - U
|
||||
|
||||
=head3 Subroutine Connection
|
||||
|
||||
@@ -115,11 +117,11 @@ processing routines or the monitors.
|
||||
VAL should be set by the subroutine. SADR holds the subroutine address and is
|
||||
set by the record processing routine.
|
||||
|
||||
The rest of these fields--LALM, ALST, MLST, and the LA-LL fields--are used to
|
||||
The rest of these fields--LALM, ALST, MLST, and the LA-LU fields--are used to
|
||||
implement the monitors. For example, when LA is not equal to A, the value-change
|
||||
monitors are called for that field.
|
||||
|
||||
=fields VAL, SADR, LALM, ALST, MLST, LA - LL
|
||||
=fields VAL, SADR, LALM, ALST, MLST, LA - LU
|
||||
|
||||
=head2 Record Support
|
||||
|
||||
@@ -161,7 +163,7 @@ recGblGetPrec() >>>.
|
||||
long (*get_graphic_double)(struct dbAddr *paddr, struct dbr_grDouble *p)
|
||||
|
||||
Sets the upper display and lower display limits for a field. If the field is
|
||||
VAL, A-L, LA-LL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR,
|
||||
VAL, A-U, LA-LU, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR,
|
||||
else if the field has upper and lower limits defined they will be used, else the
|
||||
upper and lower maximum values for the field type will be used.
|
||||
|
||||
@@ -170,7 +172,7 @@ upper and lower maximum values for the field type will be used.
|
||||
long (*get_control_double)(struct dbAddr *paddr, struct dbr_ctrlDouble *p)
|
||||
|
||||
Sets the upper control and the lower control limits for a field. If the field is
|
||||
VAL, A-L, LA-LL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR,
|
||||
VAL, A-U, LA-LU, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR,
|
||||
else if the field has upper and lower limits defined they will be used, else the
|
||||
upper and lower maximum values for the field type will be used.
|
||||
|
||||
@@ -241,7 +243,7 @@ met.
|
||||
|
||||
=item *
|
||||
|
||||
Monitors for A-L are invoked if value has changed.
|
||||
Monitors for A-U are invoked if value has changed.
|
||||
|
||||
=item *
|
||||
|
||||
@@ -500,6 +502,51 @@ processing.
|
||||
promptgroup("42 - Input G-L")
|
||||
interest(1)
|
||||
}
|
||||
field(INPM,DBF_INLINK) {
|
||||
prompt("Input M")
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPN,DBF_INLINK) {
|
||||
prompt("Input N")
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPO,DBF_INLINK) {
|
||||
prompt("Input O")
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPP,DBF_INLINK) {
|
||||
prompt("Input P")
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPQ,DBF_INLINK) {
|
||||
prompt("Input Q")
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPR,DBF_INLINK) {
|
||||
prompt("Input R")
|
||||
promptgroup("43 - Input M-R")
|
||||
interest(1)
|
||||
}
|
||||
field(INPS,DBF_INLINK) {
|
||||
prompt("Input S")
|
||||
promptgroup("44 - Input S-U")
|
||||
interest(1)
|
||||
}
|
||||
field(INPT,DBF_INLINK) {
|
||||
prompt("Input T")
|
||||
promptgroup("44 - Input S-U")
|
||||
interest(1)
|
||||
}
|
||||
field(INPU,DBF_INLINK) {
|
||||
prompt("Input U")
|
||||
promptgroup("44 - Input S-U")
|
||||
interest(1)
|
||||
}
|
||||
field(EGU,DBF_STRING) {
|
||||
prompt("Engineering Units")
|
||||
promptgroup("80 - Display")
|
||||
@@ -655,6 +702,42 @@ processing.
|
||||
prompt("Value of Input L")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(M,DBF_DOUBLE) {
|
||||
prompt("Value of Input M")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(N,DBF_DOUBLE) {
|
||||
prompt("Value of Input N")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(O,DBF_DOUBLE) {
|
||||
prompt("Value of Input O")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(P,DBF_DOUBLE) {
|
||||
prompt("Value of Input P")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(Q,DBF_DOUBLE) {
|
||||
prompt("Value of Input Q")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(R,DBF_DOUBLE) {
|
||||
prompt("Value of Input R")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(S,DBF_DOUBLE) {
|
||||
prompt("Value of Input S")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(T,DBF_DOUBLE) {
|
||||
prompt("Value of Input T")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(U,DBF_DOUBLE) {
|
||||
prompt("Value of Input U")
|
||||
pp(TRUE)
|
||||
}
|
||||
field(LA,DBF_DOUBLE) {
|
||||
prompt("Prev Value of A")
|
||||
special(SPC_NOMOD)
|
||||
@@ -715,6 +798,51 @@ processing.
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LM,DBF_DOUBLE) {
|
||||
prompt("Prev Value of M")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LN,DBF_DOUBLE) {
|
||||
prompt("Prev Value of N")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LO,DBF_DOUBLE) {
|
||||
prompt("Prev Value of O")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LP,DBF_DOUBLE) {
|
||||
prompt("Prev Value of P")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LQ,DBF_DOUBLE) {
|
||||
prompt("Prev Value of Q")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LR,DBF_DOUBLE) {
|
||||
prompt("Prev Value of R")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LS,DBF_DOUBLE) {
|
||||
prompt("Prev Value of S")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LT,DBF_DOUBLE) {
|
||||
prompt("Prev Value of T")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LU,DBF_DOUBLE) {
|
||||
prompt("Prev Value of U")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(LALM,DBF_DOUBLE) {
|
||||
prompt("Last Value Alarmed")
|
||||
special(SPC_NOMOD)
|
||||
|
||||
@@ -18,7 +18,7 @@ stringchar [^"\n\\]
|
||||
name [a-zA-Z0-9_\-+:.\[\]<>;]
|
||||
digit [0-9]
|
||||
punctuation [(){},]
|
||||
link [A-L]
|
||||
link [A-U]
|
||||
|
||||
%{
|
||||
static ASINPUTFUNCPTR *my_yyinput;
|
||||
|
||||
@@ -86,6 +86,15 @@ LIBCOM_API long
|
||||
case FETCH_J:
|
||||
case FETCH_K:
|
||||
case FETCH_L:
|
||||
case FETCH_M:
|
||||
case FETCH_N:
|
||||
case FETCH_O:
|
||||
case FETCH_P:
|
||||
case FETCH_Q:
|
||||
case FETCH_R:
|
||||
case FETCH_S:
|
||||
case FETCH_T:
|
||||
case FETCH_U:
|
||||
*++ptop = parg[op - FETCH_A];
|
||||
break;
|
||||
|
||||
@@ -101,6 +110,15 @@ LIBCOM_API long
|
||||
case STORE_J:
|
||||
case STORE_K:
|
||||
case STORE_L:
|
||||
case STORE_M:
|
||||
case STORE_N:
|
||||
case STORE_O:
|
||||
case STORE_P:
|
||||
case STORE_Q:
|
||||
case STORE_R:
|
||||
case STORE_S:
|
||||
case STORE_T:
|
||||
case STORE_U:
|
||||
parg[op - STORE_A] = *ptop--;
|
||||
break;
|
||||
|
||||
@@ -441,6 +459,15 @@ calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
|
||||
case FETCH_J:
|
||||
case FETCH_K:
|
||||
case FETCH_L:
|
||||
case FETCH_M:
|
||||
case FETCH_N:
|
||||
case FETCH_O:
|
||||
case FETCH_P:
|
||||
case FETCH_Q:
|
||||
case FETCH_R:
|
||||
case FETCH_S:
|
||||
case FETCH_T:
|
||||
case FETCH_U:
|
||||
/* Don't claim to use an arg we already stored to */
|
||||
inputs |= (1 << (op - FETCH_A)) & ~stores;
|
||||
break;
|
||||
@@ -457,6 +484,15 @@ calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
|
||||
case STORE_J:
|
||||
case STORE_K:
|
||||
case STORE_L:
|
||||
case STORE_M:
|
||||
case STORE_N:
|
||||
case STORE_O:
|
||||
case STORE_P:
|
||||
case STORE_Q:
|
||||
case STORE_R:
|
||||
case STORE_S:
|
||||
case STORE_T:
|
||||
case STORE_U:
|
||||
stores |= (1 << (op - STORE_A));
|
||||
break;
|
||||
|
||||
|
||||
@@ -117,20 +117,29 @@ static const ELEMENT operands[] = {
|
||||
{"LN", 7, 8, 0, UNARY_OPERATOR, LOG_E},
|
||||
{"LOG", 7, 8, 0, UNARY_OPERATOR, LOG_10},
|
||||
{"LOGE", 7, 8, 0, UNARY_OPERATOR, LOG_E},
|
||||
{"M", 0, 0, 1, OPERAND, FETCH_M},
|
||||
{"MAX", 7, 8, 0, VARARG_OPERATOR,MAX},
|
||||
{"MIN", 7, 8, 0, VARARG_OPERATOR,MIN},
|
||||
{"N", 0, 0, 1, OPERAND, FETCH_N},
|
||||
{"NINT", 7, 8, 0, UNARY_OPERATOR, NINT},
|
||||
{"NAN", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"NOT", 7, 8, 0, UNARY_OPERATOR, BIT_NOT},
|
||||
{"O", 0, 0, 1, OPERAND, FETCH_O},
|
||||
{"P", 0, 0, 1, OPERAND, FETCH_P},
|
||||
{"PI", 0, 0, 1, OPERAND, CONST_PI},
|
||||
{"Q", 0, 0, 1, OPERAND, FETCH_Q},
|
||||
{"R", 0, 0, 1, OPERAND, FETCH_R},
|
||||
{"R2D", 0, 0, 1, OPERAND, CONST_R2D},
|
||||
{"RNDM", 0, 0, 1, OPERAND, RANDOM},
|
||||
{"S", 0, 0, 1, OPERAND, FETCH_S},
|
||||
{"SIN", 7, 8, 0, UNARY_OPERATOR, SIN},
|
||||
{"SINH", 7, 8, 0, UNARY_OPERATOR, SINH},
|
||||
{"SQR", 7, 8, 0, UNARY_OPERATOR, SQU_RT},
|
||||
{"SQRT", 7, 8, 0, UNARY_OPERATOR, SQU_RT},
|
||||
{"T", 0, 0, 1, OPERAND, FETCH_T},
|
||||
{"TAN", 7, 8, 0, UNARY_OPERATOR, TAN},
|
||||
{"TANH", 7, 8, 0, UNARY_OPERATOR, TANH},
|
||||
{"U", 0, 0, 1, OPERAND, FETCH_U},
|
||||
{"VAL", 0, 0, 1, OPERAND, FETCH_VAL},
|
||||
{"~", 7, 8, 0, UNARY_OPERATOR, BIT_NOT},
|
||||
};
|
||||
@@ -286,7 +295,7 @@ LIBCOM_API long
|
||||
|
||||
case STORE_OPERATOR:
|
||||
if (pout == pdest || pstacktop > stack ||
|
||||
*--pout < FETCH_A || *pout > FETCH_L) {
|
||||
*--pout < FETCH_A || *pout >= FETCH_A + CALCPERFORM_NARGS) {
|
||||
*perror = CALC_ERR_BAD_ASSIGNMENT;
|
||||
goto bad;
|
||||
}
|
||||
@@ -542,9 +551,13 @@ LIBCOM_API void
|
||||
"LITERAL_DOUBLE", "LITERAL_INT", "VAL",
|
||||
"FETCH_A", "FETCH_B", "FETCH_C", "FETCH_D", "FETCH_E", "FETCH_F",
|
||||
"FETCH_G", "FETCH_H", "FETCH_I", "FETCH_J", "FETCH_K", "FETCH_L",
|
||||
"FETCH_M", "FETCH_N", "FETCH_O", "FETCH_P", "FETCH_Q", "FETCH_R",
|
||||
"FETCH_S", "FETCH_T", "FETCH_U",
|
||||
/* Assignment */
|
||||
"STORE_A", "STORE_B", "STORE_C", "STORE_D", "STORE_E", "STORE_F",
|
||||
"STORE_G", "STORE_H", "STORE_I", "STORE_J", "STORE_K", "STORE_L",
|
||||
"STORE_M", "STORE_N", "STORE_O", "STORE_P", "STORE_Q", "STORE_R",
|
||||
"STORE_S", "STORE_T", "STORE_U",
|
||||
/* Trigonometry Constants */
|
||||
"CONST_PI",
|
||||
"CONST_D2R",
|
||||
|
||||
@@ -22,8 +22,11 @@
|
||||
|
||||
#include "libComAPI.h"
|
||||
|
||||
/** \brief Number of input arguments to a calc expression (A-L) */
|
||||
#define CALCPERFORM_NARGS 12
|
||||
/** \brief Number of input arguments to a calc expression (A-U)
|
||||
*
|
||||
* Since UNRELEASED the number of inputs has been increased from 12 to 21.
|
||||
*/
|
||||
#define CALCPERFORM_NARGS 21
|
||||
/** \brief Size of the internal partial result stack */
|
||||
#define CALCPERFORM_STACK 80
|
||||
|
||||
@@ -61,7 +64,7 @@
|
||||
*
|
||||
* This is not a hard limit, just the default size for the database
|
||||
*/
|
||||
#define MAX_INFIX_SIZE 100
|
||||
#define MAX_INFIX_SIZE 160
|
||||
/**
|
||||
* \brief Size of a "standard" postfix buffer.
|
||||
*
|
||||
@@ -161,13 +164,13 @@ extern "C" {
|
||||
* angle from radians to degrees.
|
||||
*
|
||||
* -# **Variables** are used to provide inputs to an expression, and are
|
||||
* named using the single letters \c A through \c L inclusive or the
|
||||
* named using the single letters \c A through \c U inclusive or the
|
||||
* keyword \c VAL which refers to the previous result of this
|
||||
* calculation.
|
||||
* The software that makes use of the expression evaluation code should
|
||||
* document how the individual variables are given values.
|
||||
* For the calc and calcout record types the input links \c INPA through
|
||||
* \c INPL can be used to obtain values from other record fields, and \c
|
||||
* \c INPU can be used to obtain values from other record fields, and \c
|
||||
* VAL refers to the the VAL field (which can be overwritten from
|
||||
* outside the record via Channel Access or a database link).
|
||||
*
|
||||
@@ -323,7 +326,7 @@ LIBCOM_API long
|
||||
* Evaluates the postfix expression against a set ot input values.
|
||||
*
|
||||
* \param parg Pointer to an array of double values for the arguments
|
||||
* \c A-L that can appear in the expression.
|
||||
* \c A-U that can appear in the expression.
|
||||
* Note that the argument values may be modified if the expression uses
|
||||
* the assignment operator.
|
||||
* \param presult Where to put the calculated result, which may be a NaN
|
||||
@@ -345,8 +348,8 @@ LIBCOM_API long
|
||||
* for either of these pointers is legal if only the other is needed.
|
||||
*
|
||||
* The least significant bit (bit 0) of the bitmap at \c *pinputs will be set
|
||||
* if the expression depends on the argument A, and so on through bit 11 for
|
||||
* the argument L. An argument that is not used until after a value has been
|
||||
* if the expression depends on the argument A, and so on through bit 20 for
|
||||
* the argument U. An argument that is not used until after a value has been
|
||||
* assigned to it will not be set in the pinputs bitmap, thus the bits can
|
||||
* be used to determine whether a value needs to be supplied for their
|
||||
* associated argument or not for the purposes of evaluating the expression.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
/* Notes:
|
||||
* 1. The FETCH_A through FETCH_L and STORE_A through STORE_L opcodes must
|
||||
* 1. The FETCH_A through FETCH_U and STORE_A through STORE_U opcodes must
|
||||
* be contiguous.
|
||||
* 2. The LITERAL opcodes are followed by a binary representation of their
|
||||
* values, but these are not aligned properly.
|
||||
@@ -34,9 +34,13 @@ typedef enum {
|
||||
LITERAL_DOUBLE, LITERAL_INT, FETCH_VAL,
|
||||
FETCH_A, FETCH_B, FETCH_C, FETCH_D, FETCH_E, FETCH_F,
|
||||
FETCH_G, FETCH_H, FETCH_I, FETCH_J, FETCH_K, FETCH_L,
|
||||
FETCH_M, FETCH_N, FETCH_O, FETCH_P, FETCH_Q, FETCH_R,
|
||||
FETCH_S, FETCH_T, FETCH_U,
|
||||
/* Assignment */
|
||||
STORE_A, STORE_B, STORE_C, STORE_D, STORE_E, STORE_F,
|
||||
STORE_G, STORE_H, STORE_I, STORE_J, STORE_K, STORE_L,
|
||||
STORE_M, STORE_N, STORE_O, STORE_P, STORE_Q, STORE_R,
|
||||
STORE_S, STORE_T, STORE_U,
|
||||
/* Trigonometry Constants */
|
||||
CONST_PI,
|
||||
CONST_D2R,
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
double doCalc(const char *expr) {
|
||||
/* Evaluate expression, return result */
|
||||
double args[CALCPERFORM_NARGS] = {
|
||||
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0
|
||||
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0,
|
||||
13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0
|
||||
};
|
||||
char *rpn = (char*)malloc(INFIX_TO_POSTFIX_SIZE(strlen(expr)+1));
|
||||
short err;
|
||||
@@ -48,7 +49,8 @@ void testCalc(const char *expr, double expected) {
|
||||
/* Evaluate expression, test against expected result */
|
||||
bool pass = false;
|
||||
double args[CALCPERFORM_NARGS] = {
|
||||
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0
|
||||
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0,
|
||||
13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0
|
||||
};
|
||||
char *rpn = (char*)malloc(INFIX_TO_POSTFIX_SIZE(strlen(expr)+1));
|
||||
short err;
|
||||
@@ -85,7 +87,8 @@ void testUInt32Calc(const char *expr, epicsUInt32 expected) {
|
||||
/* Evaluate expression, test against expected result */
|
||||
bool pass = false;
|
||||
double args[CALCPERFORM_NARGS] = {
|
||||
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0
|
||||
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0,
|
||||
13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0
|
||||
};
|
||||
char *rpn = (char*)malloc(INFIX_TO_POSTFIX_SIZE(strlen(expr)+1));
|
||||
short err;
|
||||
@@ -162,18 +165,27 @@ void testBadExpr(const char *expr, short expected_err) {
|
||||
#define testExpr(expr) testCalc(#expr, expr);
|
||||
|
||||
/* These are the argument bits for testArgs */
|
||||
#define A_A 0x001
|
||||
#define A_B 0x002
|
||||
#define A_C 0x004
|
||||
#define A_D 0x008
|
||||
#define A_E 0x010
|
||||
#define A_F 0x020
|
||||
#define A_G 0x040
|
||||
#define A_H 0x080
|
||||
#define A_I 0x100
|
||||
#define A_J 0x200
|
||||
#define A_K 0x400
|
||||
#define A_L 0x800
|
||||
#define A_A 0x000001
|
||||
#define A_B 0x000002
|
||||
#define A_C 0x000004
|
||||
#define A_D 0x000008
|
||||
#define A_E 0x000010
|
||||
#define A_F 0x000020
|
||||
#define A_G 0x000040
|
||||
#define A_H 0x000080
|
||||
#define A_I 0x000100
|
||||
#define A_J 0x000200
|
||||
#define A_K 0x000400
|
||||
#define A_L 0x000800
|
||||
#define A_M 0x001000
|
||||
#define A_N 0x002000
|
||||
#define A_O 0x004000
|
||||
#define A_P 0x008000
|
||||
#define A_Q 0x010000
|
||||
#define A_R 0x020000
|
||||
#define A_S 0x040000
|
||||
#define A_T 0x080000
|
||||
#define A_U 0x100000
|
||||
|
||||
|
||||
/* Macros and functions to make some expressions into valid C code */
|
||||
@@ -296,9 +308,11 @@ MAIN(epicsCalcTest)
|
||||
{
|
||||
int repeat;
|
||||
const double a=1.0, b=2.0, c=3.0, d=4.0, e=5.0, f=6.0,
|
||||
g=7.0, h=8.0, i=9.0, j=10.0, k=11.0, l=12.0;
|
||||
g=7.0, h=8.0, i=9.0, j=10.0, k=11.0, l=12.0,
|
||||
m=13.0, n=14.0, o=15.0, p=16.0, q=17.0, r=18.0,
|
||||
s=19.0, t=20.0, u=21.0;
|
||||
|
||||
testPlan(637);
|
||||
testPlan(687);
|
||||
|
||||
/* LITERAL_OPERAND elements */
|
||||
testExpr(0);
|
||||
@@ -335,6 +349,15 @@ MAIN(epicsCalcTest)
|
||||
testExpr(j);
|
||||
testExpr(k);
|
||||
testExpr(l);
|
||||
testExpr(m);
|
||||
testExpr(n);
|
||||
testExpr(o);
|
||||
testExpr(p);
|
||||
testExpr(q);
|
||||
testExpr(r);
|
||||
testExpr(s);
|
||||
testExpr(t);
|
||||
testExpr(u);
|
||||
testExpr(PI);
|
||||
testExpr(D2R);
|
||||
testExpr(R2D);
|
||||
@@ -832,6 +855,15 @@ MAIN(epicsCalcTest)
|
||||
testCalc("j := 0; j", 0);
|
||||
testCalc("k := 0; k", 0);
|
||||
testCalc("l := 0; l", 0);
|
||||
testCalc("m := 0; m", 0);
|
||||
testCalc("n := 0; n", 0);
|
||||
testCalc("o := 0; o", 0);
|
||||
testCalc("p := 0; p", 0);
|
||||
testCalc("q := 0; q", 0);
|
||||
testCalc("r := 0; r", 0);
|
||||
testCalc("s := 0; s", 0);
|
||||
testCalc("t := 0; t", 0);
|
||||
testCalc("u := 0; u", 0);
|
||||
|
||||
testCalc("a; a := 0", a);
|
||||
testCalc("b; b := 0", b);
|
||||
@@ -845,6 +877,15 @@ MAIN(epicsCalcTest)
|
||||
testCalc("j; j := 0", j);
|
||||
testCalc("k; k := 0", k);
|
||||
testCalc("l; l := 0", l);
|
||||
testCalc("m; m := 0", m);
|
||||
testCalc("n; n := 0", n);
|
||||
testCalc("o; o := 0", o);
|
||||
testCalc("p; p := 0", p);
|
||||
testCalc("q; q := 0", q);
|
||||
testCalc("r; r := 0", r);
|
||||
testCalc("s; s := 0", s);
|
||||
testCalc("t; t := 0", t);
|
||||
testCalc("u; u := 0", u);
|
||||
|
||||
// Check relative precedences.
|
||||
testExpr(0 ? 1 : 2 | 4); // 0 1
|
||||
@@ -921,8 +962,17 @@ MAIN(epicsCalcTest)
|
||||
testArgs("J", A_J, 0);
|
||||
testArgs("K", A_K, 0);
|
||||
testArgs("L", A_L, 0);
|
||||
testArgs("A+B+C+D+E+F+G+H+I+J+K+L",
|
||||
A_A|A_B|A_C|A_D|A_E|A_F|A_G|A_H|A_I|A_J|A_K|A_L, 0);
|
||||
testArgs("M", A_M, 0);
|
||||
testArgs("N", A_N, 0);
|
||||
testArgs("O", A_O, 0);
|
||||
testArgs("P", A_P, 0);
|
||||
testArgs("Q", A_Q, 0);
|
||||
testArgs("R", A_R, 0);
|
||||
testArgs("S", A_S, 0);
|
||||
testArgs("T", A_T, 0);
|
||||
testArgs("U", A_U, 0);
|
||||
testArgs("A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U",
|
||||
A_A|A_B|A_C|A_D|A_E|A_F|A_G|A_H|A_I|A_J|A_K|A_L|A_M|A_N|A_O|A_P|A_Q|A_R|A_S|A_T|A_U, 0);
|
||||
testArgs("0.1;A:=0", 0, A_A);
|
||||
testArgs("1.1;B:=0", 0, A_B);
|
||||
testArgs("2.1;C:=0", 0, A_C);
|
||||
@@ -935,6 +985,15 @@ MAIN(epicsCalcTest)
|
||||
testArgs("9.1;J:=0", 0, A_J);
|
||||
testArgs("10.1;K:=0", 0, A_K);
|
||||
testArgs("11.1;L:=0", 0, A_L);
|
||||
testArgs("12.1;M:=0", 0, A_M);
|
||||
testArgs("13.1;N:=0", 0, A_N);
|
||||
testArgs("14.1;O:=0", 0, A_O);
|
||||
testArgs("15.1;P:=0", 0, A_P);
|
||||
testArgs("16.1;Q:=0", 0, A_Q);
|
||||
testArgs("17.1;R:=0", 0, A_R);
|
||||
testArgs("18.1;S:=0", 0, A_S);
|
||||
testArgs("19.1;T:=0", 0, A_T);
|
||||
testArgs("20.1;U:=0", 0, A_U);
|
||||
testArgs("12.1;A:=0;B:=A;C:=B;D:=C", 0, A_A|A_B|A_C|A_D);
|
||||
testArgs("13.1;B:=A;A:=B;C:=D;D:=C", A_A|A_D, A_A|A_B|A_C|A_D);
|
||||
|
||||
@@ -955,6 +1014,11 @@ MAIN(epicsCalcTest)
|
||||
testBadExpr(":1", CALC_ERR_SYNTAX);
|
||||
testBadExpr("0,", CALC_ERR_BAD_SEPERATOR);
|
||||
testBadExpr("0)", CALC_ERR_PAREN_NOT_OPEN);
|
||||
testBadExpr("V", CALC_ERR_SYNTAX);
|
||||
testBadExpr("W", CALC_ERR_SYNTAX);
|
||||
testBadExpr("X", CALC_ERR_SYNTAX);
|
||||
testBadExpr("Y", CALC_ERR_SYNTAX);
|
||||
testBadExpr("Z", CALC_ERR_SYNTAX);
|
||||
|
||||
// Bit manipulations wrt bit 31 (bug lp:1514520)
|
||||
// using integer literals
|
||||
|
||||
Reference in New Issue
Block a user