extend calc records and expressions to inputs A-U

This commit is contained in:
2025-05-22 16:34:16 +02:00
parent 1804bcef7d
commit 45ea3d5664
11 changed files with 457 additions and 54 deletions

View File

@ -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;
}

View File

@ -34,8 +34,8 @@ 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
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
@ -45,7 +45,7 @@ See L<Address
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
for information on how to specify database links.
=fields INPA, INPB, INPC, INPD, INPE, INPF, INPG, INPH, INPI, INPJ, INPK, INPL
=fields INPA - INPU
=head3 Expression
@ -113,7 +113,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
@ -121,7 +121,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, B, C, D, E, F, G, H, I, J, K, L
=fields A - L
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
@ -492,12 +492,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, LB, LC, LD, LE, LF, LG, LH, LI, LJ, LK, LL
=fields LALM, ALST, MLST, LA - LU
=cut
@ -575,6 +575,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")
@ -733,6 +787,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)
@ -793,6 +883,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)
@ -911,7 +1046,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.

View File

@ -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;
}

View File

@ -57,18 +57,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
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, INPB, INPC, INPD, INPE, INPF, INPG, INPH, INPI, INPJ, INPK, INPL
=fields INPA - INPU
=head3 Expression
@ -139,14 +139,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, B, C, D, E, F, G, H, I, J, K, 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
@ -543,8 +543,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
@ -568,7 +568,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
@ -579,7 +579,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, INBV, INCV, INDV, INEV, INFV, INGV, INHV, INIV, INJV, INKV, INLV, OUTV, CLCV, OCLV, DLYA, NAME, DESC
=fields EGU, PREC, HOPR, LOPR, INAV - INUV, OUTV, CLCV, OCLV, DLYA, NAME, DESC
=head3 Alarm Parameters
@ -623,12 +623,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, LB, LC, LD, LE, LF, LG, LH, LI, LJ, LK, LL
=fields LALM, ALST, MLST, LA - LU
=cut
@ -739,6 +739,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)
@ -829,6 +883,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)
@ -1043,6 +1160,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)
@ -1107,6 +1260,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)
@ -1241,7 +1439,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

View File

@ -222,11 +222,11 @@ sub rtypeToPod {
my ($rtyp, $dbd) = @_;
return map {
# Handle a 'fields' Pod directive
if (m/^ =fields \s+ (\w+ (?:\s* , \s* \w+ )* )/x) {
my @names = split /\s*,\s*/, $1;
if (m/^ =fields \s+ (\w+ (?:\s* [,-] \s* \w+ )* )/x) {
my @names = split /\s*,\s*|\s*(?=-)|(?<=-)\s*/, $1;
# Look up the named fields
my @fields = map {
my $field = $rtyp->field($_);
my $field = $_ eq '-' ? $_ : $rtyp->field($_);
die "Unknown field name '$_' in $infile POD\n"
unless $field;
$field;
@ -256,6 +256,9 @@ sub rtypeToPod {
sub fieldTableRow {
my ($fld, $dbd) = @_;
if ($fld eq '-') {
return '<tr><td class="cell" colspan=8>&vellip;</td></tr>'."\n";
}
my $html = '<tr><td class="cell">';
$html .= $fld->name;
$html .= '</td><td class="cell">';

View File

@ -149,33 +149,33 @@ close $out;
sub menuToMD {
my ($menu) = @_;
my $index = 0;
return "| Index | Identifier | Choice String |",
"| ----- | ---------- | ------------- |",
return "| Index | Identifier | Choice String |",
"| ----- | -------------------------------------- | ---------------------- |",
map({choiceTableRow($_, $index++)} $menu->choices);
}
sub choiceTableRow {
my ($ch, $index) = @_;
my ($id, $name) = @{$ch};
return "| $index | $id | $name |";
return sprintf("| %5d | %-*s | %-22s |", $index, 38-( () = $id =~ /_/g), $id, $name);
}
sub rtypeToMD {
my ($rtyp, $dbd) = @_;
return map {
# Handle a 'fields' Pod directive
if (m/^ =fields \s+ (\w+ (?:\s* , \s* \w+ )* )/x) {
my @names = split /\s*,\s*/, $1;
if (m/^ =fields \s+ (\w+ (?:\s* [,-] \s* \w+ )* )/x) {
my @names = split /\s*,\s*|\s*(?=-)|(?<=-)\s*/, $1;
# Look up the named fields
my @fields = map {
my $field = $rtyp->field($_);
my $field = $_ eq '-' ? $_ : $rtyp->field($_);
die "Unknown field name '$_' in $infile POD\n"
unless $field;
$field;
} @names;
# Generate Pod for the table
"| Field | Summary | Type | DCT | Default | Read | Write | CA PP |",
"| ----- | ------- | ---- | --- | ------- | ---- | ----- | ----- |",
"| Field | Summary | Type | DCT | Default | Read | Write | CA PP |",
"| ----- | -------------------------- | ------------- | --- | ------- | ---- | ----- | ----- |",
map({fieldTableRow($_, $dbd)} @fields);
}
# Handle a 'menu' Pod directive
@ -195,12 +195,15 @@ sub rtypeToMD {
sub fieldTableRow {
my ($fld, $dbd) = @_;
if ($fld eq '-') {
return "| \x{22EE}".(" " x 83)."||||||||";
}
my @md;
push @md, $fld->name, $fld->attribute('prompt');
push @md, sprintf("%-5s", $fld->name), sprintf("%-26s", $fld->attribute('prompt'));
my $type = $fld->public_type;
if ($type eq 'STRING') {
$type .= ' [' . $fld->attribute('size') . ']';
$type .= sprintf("%-5s", ' [' . $fld->attribute('size') . ']');
} elsif ($type eq 'MENU') {
my $mn = $fld->attribute('menu');
my $menu = $dbd->menu($mn);
@ -208,14 +211,16 @@ sub fieldTableRow {
my $url = $menu ? "/menu-$mnl" : "${mn}.md";
#just pass a L directive for the parser
$type .= " L<$mn|$url>";
} else {
$type = sprintf("%-13s", $type);
}
push @md, $type;
push @md, $fld->attribute('promptgroup') ? 'Yes' : 'No';
push @md, $fld->attribute('initial') || ' ';
push @md, $fld->readable;
push @md, $fld->writable;
push @md, $fld->attribute('pp') eq 'TRUE' ? 'Yes' : 'No';
push @md, sprintf("%-3s", $fld->attribute('promptgroup') ? 'Yes' : 'No');
push @md, sprintf("%7s", $fld->attribute('initial') || ' ');
push @md, sprintf("%-4s",$fld->readable);
push @md, sprintf("%-5s",$fld->writable);
push @md, sprintf("%-5s",$fld->attribute('pp') eq 'TRUE' ? 'Yes' : 'No');
return '| ' . join(' | ', @md) . ' |';
}

View File

@ -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;

View File

@ -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;

View File

@ -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},
};
@ -287,7 +296,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;
}
@ -549,9 +558,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",

View File

@ -22,8 +22,8 @@
#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) */
#define CALCPERFORM_NARGS 21
/** \brief Size of the internal partial result stack */
#define CALCPERFORM_STACK 80
@ -163,11 +163,11 @@ extern "C" {
*
* -# ***Variables***
* Variables are used to provide inputs to an expression, and are named
* using the single letters A through L inclusive or the keyword VAL which
* using the single letters A through U inclusive or the keyword 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 record type the input
* links INPA through INPL can be used to obtain these from other record fields,
* links INPA through INPU can be used to obtain these from other record fields,
* and VAL refers to the the VAL field (which can be overwritten from outside
* the record via Channel Access or a database link).
*
@ -310,7 +310,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 A-L
* \param parg Pointer to an array of double values for the arguments 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 or Infinity.
@ -331,8 +331,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.

View File

@ -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,