Added the aSub record type, derived from Andy Foster's genSub.
This commit is contained in:
@@ -12,6 +12,37 @@
|
||||
<h2 align="center">Changes between 3.14.9 and 3.14.10</h2>
|
||||
<!-- Insert new items below here ... -->
|
||||
|
||||
<h4>Array Subroutine Record added (aSub)</h4>
|
||||
|
||||
<p>A heavily modified version of Andy Foster's genSub record type has been
|
||||
added, called the aSub (Array Subroutine) record type. The new name is so that
|
||||
genSub records can continue to be used in IOCs that need those features that
|
||||
have changed or been removed in creating the aSub record type. The main
|
||||
differences between genSub and aSub are:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The fields <tt>UFA..UFU</tt>, <tt>UFVA..UFVU</tt>, <tt>TOVA..TOVU</tt> and
|
||||
<tt>VERS</tt> have been removed.</li>
|
||||
<li>The <tt>INPA..INPU</tt> and <tt>OUTA..OUTU</tt> link fields can now be
|
||||
changed at runtime.</li>
|
||||
<li>A new set of fields <tt>NEA..NEU</tt> and <tt>NEVA..NEVU</tt> have been
|
||||
added which hold the current element count for the associated input and ouput
|
||||
fields. These count fields ensure that putting an array to the <tt>A..U</tt> or
|
||||
<tt>VALA..VALU</tt> fields cannot permanently shorten the number of elements
|
||||
that the array fields can hold.</li>
|
||||
<li>The default value for the <tt>FTA..FTU</tt> and <tt>FTVA..FTVU</tt> fields
|
||||
has been changed from "STRING" to "DOUBLE", to reduce the memory footprint of
|
||||
unneeded fields.</li>
|
||||
<li>aSub subroutines can be asynchronous, using the usual method of setting
|
||||
prec->pact to <tt>TRUE</tt> before returning and arranging for the record's
|
||||
<tt>process()</tt> routine to be called to signal completion. The output links
|
||||
are not written until the asynchronous completion callback, and input links are
|
||||
not read at asnychronous completion.</li>
|
||||
<li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h4>epicsTimeEventDeviceTime support for soft channel input records</h4>
|
||||
|
||||
<p>The Soft Channel device support for all input record types now supports the
|
||||
|
||||
@@ -3,3 +3,11 @@ record(sub,"$(user):subExample")
|
||||
field(INAM,"mySubInit")
|
||||
field(SNAM,"mySubProcess")
|
||||
}
|
||||
record(aSub,"$(user):aSubExample")
|
||||
{
|
||||
field(INAM,"myAsubInit")
|
||||
field(SNAM,"myAsubProcess")
|
||||
field(FTA,"DOUBLE")
|
||||
field(NOA,"10")
|
||||
field(INPA,"$(user):compressExample CPP")
|
||||
}
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
#include <dbDefs.h>
|
||||
#include <registryFunction.h>
|
||||
#include <subRecord.h>
|
||||
#include <aSubRecord.h>
|
||||
#include <epicsExport.h>
|
||||
|
||||
int mySubDebug;
|
||||
|
||||
typedef long (*processMethod)(subRecord *precord);
|
||||
|
||||
static long mySubInit(subRecord *precord,processMethod process)
|
||||
static long mySubInit(subRecord *precord)
|
||||
{
|
||||
if (mySubDebug)
|
||||
printf("Record %s called mySubInit(%p, %p)\n",
|
||||
precord->name, (void*) precord, (void*) process);
|
||||
return(0);
|
||||
printf("Record %s called mySubInit(%p)\n",
|
||||
precord->name, (void*) precord);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long mySubProcess(subRecord *precord)
|
||||
@@ -22,7 +21,23 @@ static long mySubProcess(subRecord *precord)
|
||||
if (mySubDebug)
|
||||
printf("Record %s called mySubProcess(%p)\n",
|
||||
precord->name, (void*) precord);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long myAsubInit(aSubRecord *precord)
|
||||
{
|
||||
if (mySubDebug)
|
||||
printf("Record %s called myAsubInit(%p)\n",
|
||||
precord->name, (void*) precord);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long myAsubProcess(aSubRecord *precord)
|
||||
{
|
||||
if (mySubDebug)
|
||||
printf("Record %s called myAsubProcess(%p)\n",
|
||||
precord->name, (void*) precord);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Register these symbols for use by IOC code: */
|
||||
@@ -30,3 +45,5 @@ static long mySubProcess(subRecord *precord)
|
||||
epicsExportAddress(int, mySubDebug);
|
||||
epicsRegisterFunction(mySubInit);
|
||||
epicsRegisterFunction(mySubProcess);
|
||||
epicsRegisterFunction(myAsubInit);
|
||||
epicsRegisterFunction(myAsubProcess);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
variable(mySubDebug)
|
||||
function(mySubInit)
|
||||
function(mySubProcess)
|
||||
function(myAsubInit)
|
||||
function(myAsubProcess)
|
||||
|
||||
@@ -10,6 +10,7 @@ include "menuConvert.dbd"
|
||||
# Record types
|
||||
include "aiRecord.dbd"
|
||||
include "aoRecord.dbd"
|
||||
include "aSubRecord.dbd"
|
||||
include "biRecord.dbd"
|
||||
include "boRecord.dbd"
|
||||
include "calcRecord.dbd"
|
||||
|
||||
@@ -14,6 +14,7 @@ DBDINC += aaiRecord
|
||||
DBDINC += aaoRecord
|
||||
DBDINC += aiRecord
|
||||
DBDINC += aoRecord
|
||||
DBDINC += aSubRecord
|
||||
DBDINC += biRecord
|
||||
DBDINC += boRecord
|
||||
DBDINC += calcRecord
|
||||
@@ -43,6 +44,7 @@ LIBSRCS += aaiRecord.c
|
||||
LIBSRCS += aaoRecord.c
|
||||
LIBSRCS += aiRecord.c
|
||||
LIBSRCS += aoRecord.c
|
||||
LIBSRCS += aSubRecord.c
|
||||
LIBSRCS += biRecord.c
|
||||
LIBSRCS += boRecord.c
|
||||
LIBSRCS += calcRecord.c
|
||||
|
||||
501
src/rec/aSubRecord.c
Normal file
501
src/rec/aSubRecord.c
Normal file
@@ -0,0 +1,501 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* $Id$
|
||||
*
|
||||
* Record Support Routines for the Array Subroutine Record type,
|
||||
* derived from Andy Foster's genSub record, with some features
|
||||
* removed and asynchronous support added.
|
||||
*
|
||||
* Original Author: Andy Foster
|
||||
* Revised by: Andrew Johnson
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alarm.h"
|
||||
#include "cantProceed.h"
|
||||
#include "dbDefs.h"
|
||||
#include "dbEvent.h"
|
||||
#include "dbAccess.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "errMdef.h"
|
||||
#include "recSup.h"
|
||||
#include "devSup.h"
|
||||
#include "special.h"
|
||||
#include "registryFunction.h"
|
||||
#include "epicsExport.h"
|
||||
#include "recGbl.h"
|
||||
|
||||
#define GEN_SIZE_OFFSET
|
||||
#include "aSubRecord.h"
|
||||
#undef GEN_SIZE_OFFSET
|
||||
|
||||
|
||||
typedef long (*GENFUNCPTR)(struct aSubRecord *);
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
|
||||
#define report NULL
|
||||
#define initialize NULL
|
||||
static long init_record(aSubRecord *, int);
|
||||
static long process(aSubRecord *);
|
||||
static long special(DBADDR *, int);
|
||||
static long get_value(aSubRecord *, struct valueDes *);
|
||||
static long cvt_dbaddr(DBADDR *);
|
||||
static long get_array_info(DBADDR *, long *, long *);
|
||||
static long put_array_info(DBADDR *, long );
|
||||
#define get_units NULL
|
||||
static long get_precision(DBADDR *, long *);
|
||||
#define get_enum_str NULL
|
||||
#define get_enum_strs NULL
|
||||
#define put_enum_str NULL
|
||||
#define get_graphic_double NULL
|
||||
#define get_control_double NULL
|
||||
#define get_alarm_double NULL
|
||||
|
||||
rset aSubRSET = {
|
||||
RSETNUMBER,
|
||||
report,
|
||||
initialize,
|
||||
init_record,
|
||||
process,
|
||||
special,
|
||||
get_value,
|
||||
cvt_dbaddr,
|
||||
get_array_info,
|
||||
put_array_info,
|
||||
get_units,
|
||||
get_precision,
|
||||
get_enum_str,
|
||||
get_enum_strs,
|
||||
put_enum_str,
|
||||
get_graphic_double,
|
||||
get_control_double,
|
||||
get_alarm_double
|
||||
};
|
||||
epicsExportAddress(rset, aSubRSET);
|
||||
|
||||
static long initFields(epicsEnum16 *pft, epicsUInt32 *pno, epicsUInt32 *pne,
|
||||
const char **fldnames, void **pval, void **povl);
|
||||
static long fetch_values(aSubRecord *prec);
|
||||
static void monitor(aSubRecord *);
|
||||
static long do_sub(aSubRecord *);
|
||||
|
||||
#define NUM_ARGS 21
|
||||
#define MAX_ARRAY_SIZE 10000000
|
||||
|
||||
/* These are the names of the Input fields */
|
||||
static const char *Ifldnames[] = {
|
||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
|
||||
"L", "M", "N", "O", "P", "Q", "R", "S", "T", "U"
|
||||
};
|
||||
|
||||
/* These are the names of the Output fields */
|
||||
static const char *Ofldnames[] = {
|
||||
"VALA", "VALB", "VALC", "VALD", "VALE", "VALF", "VALG",
|
||||
"VALH", "VALI", "VALJ", "VALK", "VALL", "VALM", "VALN",
|
||||
"VALO", "VALP", "VALQ", "VALR", "VALS", "VALT", "VALU"
|
||||
};
|
||||
|
||||
|
||||
static long init_record(aSubRecord *prec, int pass)
|
||||
{
|
||||
GENFUNCPTR pfunc;
|
||||
long status;
|
||||
int i;
|
||||
|
||||
status = 0;
|
||||
if (pass == 0) {
|
||||
/* Allocate memory for arrays */
|
||||
initFields(&prec->fta, &prec->noa, &prec->nea, Ifldnames,
|
||||
&prec->a, NULL);
|
||||
initFields(&prec->ftva, &prec->nova, &prec->neva, Ofldnames,
|
||||
&prec->vala, &prec->ovla);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize the Subroutine Name Link */
|
||||
switch (prec->subl.type) {
|
||||
case CONSTANT:
|
||||
recGblInitConstantLink(&prec->subl, DBF_STRING, prec->snam);
|
||||
break;
|
||||
|
||||
case PV_LINK:
|
||||
case DB_LINK:
|
||||
case CA_LINK:
|
||||
break;
|
||||
|
||||
default:
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
"aSubRecord(init_record) Bad SUBL link type");
|
||||
return S_db_badField;
|
||||
}
|
||||
|
||||
/* Initialize Input Links */
|
||||
for (i = 0; i < NUM_ARGS; i++) {
|
||||
struct link *plink = &(&prec->inpa)[i];
|
||||
switch (plink->type) {
|
||||
case CONSTANT:
|
||||
if ((&prec->noa)[i] < 2) {
|
||||
if (recGblInitConstantLink(plink, (&prec->fta)[i], (&prec->a)[i])) {
|
||||
prec->udf = FALSE;
|
||||
} else
|
||||
prec->udf = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PV_LINK:
|
||||
case CA_LINK:
|
||||
case DB_LINK:
|
||||
break;
|
||||
|
||||
default:
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
"aSubRecord(init_record) Illegal INPUT LINK");
|
||||
status = S_db_badField;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Initialize Output Links */
|
||||
for (i = 0; i < NUM_ARGS; i++) {
|
||||
switch ((&prec->outa)[i].type) {
|
||||
case CONSTANT:
|
||||
case PV_LINK:
|
||||
case CA_LINK:
|
||||
case DB_LINK:
|
||||
break;
|
||||
|
||||
default:
|
||||
recGblRecordError(S_db_badField, (void *)prec,
|
||||
"aSubRecord(init_record) Illegal OUTPUT LINK");
|
||||
status = S_db_badField;
|
||||
}
|
||||
}
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Call the user initialization routine if there is one */
|
||||
if (prec->inam[0] != 0) {
|
||||
pfunc = (GENFUNCPTR)registryFunctionFind(prec->inam);
|
||||
if (pfunc) {
|
||||
pfunc(prec);
|
||||
} else {
|
||||
recGblRecordError(S_db_BadSub, (void *)prec,
|
||||
"aSubRecord::init_record - INAM subr not found");
|
||||
return S_db_BadSub;
|
||||
}
|
||||
}
|
||||
|
||||
if (prec->lflg == aSubLFLG_IGNORE &&
|
||||
prec->snam[0] != 0) {
|
||||
pfunc = (GENFUNCPTR)registryFunctionFind(prec->snam);
|
||||
if (pfunc)
|
||||
prec->sadr = pfunc;
|
||||
else {
|
||||
recGblRecordError(S_db_BadSub, (void *)prec,
|
||||
"aSubRecord::init_record - SNAM subr not found");
|
||||
return S_db_BadSub;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long initFields(epicsEnum16 *pft, epicsUInt32 *pno, epicsUInt32 *pne,
|
||||
const char **fldnames, void **pval, void **povl)
|
||||
{
|
||||
int i;
|
||||
long status = 0;
|
||||
|
||||
for (i = 0; i < NUM_ARGS; i++, pft++, pno++, pne++, pval++) {
|
||||
epicsUInt32 num;
|
||||
epicsUInt32 flen;
|
||||
|
||||
if (*pft > DBF_ENUM)
|
||||
*pft = DBF_CHAR;
|
||||
|
||||
if (*pno == 0)
|
||||
*pno = 1;
|
||||
|
||||
flen = dbValueSize(*pft);
|
||||
num = *pno * flen;
|
||||
|
||||
if (num > MAX_ARRAY_SIZE) {
|
||||
epicsPrintf("Link %s - Array too large! %d Bytes\n", fldnames[i], num);
|
||||
*pno = num = 0;
|
||||
status = S_db_errArg;
|
||||
} else
|
||||
*pval = (char *)callocMustSucceed(*pno, flen,
|
||||
"aSubRecord::init_record");
|
||||
|
||||
*pne = *pno;
|
||||
|
||||
if (povl) {
|
||||
if (num)
|
||||
*povl = (char *)callocMustSucceed(*pno, flen,
|
||||
"aSubRecord::init_record");
|
||||
povl++;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static long process(aSubRecord *prec)
|
||||
{
|
||||
int pact = prec->pact;
|
||||
long status = 0;
|
||||
|
||||
if (!pact) {
|
||||
prec->pact = TRUE;
|
||||
status = fetch_values(prec);
|
||||
prec->pact = FALSE;
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
status = do_sub(prec);
|
||||
prec->val = status;
|
||||
}
|
||||
|
||||
if (!pact && prec->pact)
|
||||
return 0;
|
||||
|
||||
prec->pact = TRUE;
|
||||
|
||||
/* Push the output link values */
|
||||
if (!status) {
|
||||
int i;
|
||||
for (i = 0; i < NUM_ARGS; i++)
|
||||
dbPutLink(&(&prec->outa)[i], (&prec->ftva)[i], (&prec->vala)[i],
|
||||
(&prec->neva)[i]);
|
||||
}
|
||||
|
||||
recGblGetTimeStamp(prec);
|
||||
monitor(prec);
|
||||
recGblFwdLink(prec);
|
||||
prec->pact = FALSE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long fetch_values(aSubRecord *prec)
|
||||
{
|
||||
long status;
|
||||
int i;
|
||||
|
||||
if (prec->lflg == aSubLFLG_READ) {
|
||||
/* Get the Subroutine Name and look it up if changed */
|
||||
status = dbGetLink(&prec->subl, DBR_STRING, prec->snam, 0, 0);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (prec->snam[0] != 0 &&
|
||||
strcmp(prec->snam, prec->onam)) {
|
||||
GENFUNCPTR pfunc = (GENFUNCPTR)registryFunctionFind(prec->snam);
|
||||
|
||||
if (!pfunc)
|
||||
return S_db_BadSub;
|
||||
|
||||
prec->sadr = pfunc;
|
||||
strcpy(prec->onam, prec->snam);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the input link values */
|
||||
for (i = 0; i < NUM_ARGS; i++) {
|
||||
long nRequest = (&prec->noa)[i];
|
||||
status = dbGetLink(&(&prec->inpa)[i], (&prec->fta)[i], (&prec->a)[i], 0,
|
||||
&nRequest);
|
||||
if (nRequest > 0)
|
||||
(&prec->nea)[i] = nRequest;
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_precision(DBADDR *paddr, long *precision)
|
||||
{
|
||||
aSubRecord *prec = (aSubRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if (fieldIndex == aSubRecordVAL) {
|
||||
*precision = prec->prec;
|
||||
return 0;
|
||||
}
|
||||
recGblGetPrec(paddr, precision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long get_value(aSubRecord *prec, struct valueDes *pvdes)
|
||||
{
|
||||
pvdes->no_elements = 1;
|
||||
pvdes->pvalue = (void *)(&prec->val);
|
||||
pvdes->field_type = DBF_LONG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void monitor(aSubRecord *prec)
|
||||
{
|
||||
int i;
|
||||
unsigned short monitor_mask;
|
||||
|
||||
monitor_mask = recGblResetAlarms(prec) | DBE_VALUE | DBE_LOG;
|
||||
|
||||
/* Post events for VAL field */
|
||||
if (prec->val != prec->oval) {
|
||||
db_post_events(prec, &prec->val, monitor_mask);
|
||||
prec->oval = prec->val;
|
||||
}
|
||||
|
||||
/* Event posting on VAL arrays depends on the setting of prec->eflg */
|
||||
switch (prec->eflg) {
|
||||
case aSubEFLG_NEVER:
|
||||
break;
|
||||
case aSubEFLG_ON_CHANGE:
|
||||
for (i = 0; i < NUM_ARGS; i++) {
|
||||
epicsUInt32 alen = dbValueSize((&prec->ftva)[i]) * (&prec->neva)[i];
|
||||
void *povl = (&prec->ovla)[i];
|
||||
void *pval = (&prec->vala)[i];
|
||||
if (memcmp(povl, pval, alen)) {
|
||||
memcpy(povl, pval, alen);
|
||||
db_post_events(prec, pval, monitor_mask);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case aSubEFLG_ALWAYS:
|
||||
for (i = 0; i < NUM_ARGS; i++)
|
||||
db_post_events(prec, (&prec->vala)[i], monitor_mask);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static long do_sub(aSubRecord *prec)
|
||||
{
|
||||
GENFUNCPTR pfunc = prec->sadr;
|
||||
long status;
|
||||
|
||||
if (prec->snam[0] == 0)
|
||||
return 0;
|
||||
|
||||
if (pfunc == NULL) {
|
||||
recGblSetSevr(prec, BAD_SUB_ALARM, INVALID_ALARM);
|
||||
return S_db_BadSub;
|
||||
}
|
||||
status = pfunc(prec);
|
||||
if (status < 0)
|
||||
recGblSetSevr(prec, SOFT_ALARM, prec->brsv);
|
||||
else
|
||||
prec->udf = FALSE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static long cvt_dbaddr(DBADDR *paddr)
|
||||
{
|
||||
aSubRecord *prec = (aSubRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if (fieldIndex >= aSubRecordA &&
|
||||
fieldIndex <= aSubRecordU) {
|
||||
int offset = fieldIndex - aSubRecordA;
|
||||
paddr->pfield = (&prec->a )[offset];
|
||||
paddr->no_elements = (&prec->noa)[offset];
|
||||
paddr->field_type = (&prec->fta)[offset];
|
||||
}
|
||||
else if (fieldIndex >= aSubRecordVALA &&
|
||||
fieldIndex <= aSubRecordVALU) {
|
||||
int offset = fieldIndex - aSubRecordVALA;
|
||||
paddr->pfield = (&prec->vala)[offset];
|
||||
paddr->no_elements = (&prec->nova)[offset];
|
||||
paddr->field_type = (&prec->ftva)[offset];
|
||||
}
|
||||
else {
|
||||
errlogPrintf("aSubRecord::cvt_dbaddr called for %s.%s\n",
|
||||
prec->name, ((dbFldDes *)paddr->pfldDes)->name);
|
||||
return 0;
|
||||
}
|
||||
paddr->dbr_field_type = paddr->field_type;
|
||||
paddr->field_size = dbValueSize(paddr->field_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
|
||||
{
|
||||
aSubRecord *prec = (aSubRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if (fieldIndex >= aSubRecordA &&
|
||||
fieldIndex <= aSubRecordU) {
|
||||
*no_elements = (&prec->nea)[fieldIndex - aSubRecordA];
|
||||
}
|
||||
else if (fieldIndex >= aSubRecordVALA &&
|
||||
fieldIndex <= aSubRecordVALU) {
|
||||
*no_elements = (&prec->neva)[fieldIndex - aSubRecordVALA];
|
||||
}
|
||||
else {
|
||||
errlogPrintf("aSubRecord::get_array_info called for %s.%s\n",
|
||||
prec->name, ((dbFldDes *)paddr->pfldDes)->name);
|
||||
}
|
||||
*offset = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long put_array_info(DBADDR *paddr, long nNew)
|
||||
{
|
||||
aSubRecord *prec = (aSubRecord *)paddr->precord;
|
||||
int fieldIndex = dbGetFieldIndex(paddr);
|
||||
|
||||
if (fieldIndex >= aSubRecordA &&
|
||||
fieldIndex <= aSubRecordU) {
|
||||
(&prec->nea)[fieldIndex - aSubRecordA] = nNew;
|
||||
}
|
||||
else if (fieldIndex >= aSubRecordVALA &&
|
||||
fieldIndex <= aSubRecordVALU) {
|
||||
(&prec->neva)[fieldIndex - aSubRecordVALA] = nNew;
|
||||
}
|
||||
else {
|
||||
errlogPrintf("aSubRecord::put_array_info called for %s.%s\n",
|
||||
prec->name, ((dbFldDes *)paddr->pfldDes)->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long special(DBADDR *paddr, int after)
|
||||
{
|
||||
aSubRecord *prec = (aSubRecord *)paddr->precord;
|
||||
|
||||
if (after &&
|
||||
prec->lflg == aSubLFLG_IGNORE) {
|
||||
if (prec->snam[0] == 0)
|
||||
return 0;
|
||||
|
||||
prec->sadr = (GENFUNCPTR)registryFunctionFind(prec->snam);
|
||||
if (!prec->sadr) {
|
||||
recGblRecordError(S_db_BadSub, (void *)prec, prec->snam);
|
||||
return S_db_BadSub;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
1637
src/rec/aSubRecord.dbd
Normal file
1637
src/rec/aSubRecord.dbd
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user