From 27e80be2e54765000471144b7ff7067f565dd16e Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 26 May 2010 10:42:16 -0700 Subject: [PATCH] read attributes of input fields from links --- src/rec/calcRecord.c | 105 +++++++++++++++++---------------- src/rec/calcoutRecord.c | 117 +++++++++++++++++++----------------- src/rec/seqRecord.c | 127 +++++++++++++++++++++------------------- src/rec/subRecord.c | 96 +++++++++++++++--------------- 4 files changed, 235 insertions(+), 210 deletions(-) diff --git a/src/rec/calcRecord.c b/src/rec/calcRecord.c index 75ae6ed00..ed82f9f91 100644 --- a/src/rec/calcRecord.c +++ b/src/rec/calcRecord.c @@ -150,18 +150,25 @@ 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)) + return fieldIndex - indexof(A); + if (fieldIndex >= indexof(LA) && fieldIndex <= indexof(LL)) + return fieldIndex - indexof(LA); + return -1; +} + static long get_units(DBADDR *paddr, char *units) { calcRecord *prec = (calcRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); + int linkNumber; if(paddr->pfldDes->field_type == DBF_DOUBLE) { - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) { - /* We need a way to get units for A-L */; - } else { + linkNumber = get_linkNumber(dbGetFieldIndex(paddr)); + if (linkNumber >= 0) + dbGetUnits(&prec->inpa + linkNumber, units, DB_UNITS_SIZE); + else strncpy(units,prec->egu,DB_UNITS_SIZE); - } } return 0; } @@ -169,27 +176,32 @@ static long get_units(DBADDR *paddr, char *units) static long get_precision(DBADDR *paddr, long *pprecision) { calcRecord *prec = (calcRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); + int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; *pprecision = prec->prec; - if (index == indexof(VAL)) { + if (fieldIndex == indexof(VAL)) { return 0; } - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) { - /* We need a way to get precision for A-L */; - *pprecision=15; - } - recGblGetPrec(paddr, pprecision); + linkNumber = get_linkNumber(fieldIndex); + if (linkNumber >= 0) { + short precision; + if (dbGetPrecision(&prec->inpa + linkNumber, &precision) == 0) + *pprecision = precision; + else + *pprecision = 15; + } else + recGblGetPrec(paddr, pprecision); return 0; } static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd) { calcRecord *prec = (calcRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); + int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; - switch (index) { + switch (fieldIndex) { case indexof(VAL): case indexof(HIHI): case indexof(HIGH): @@ -198,32 +210,26 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd) case indexof(LALM): case indexof(ALST): case indexof(MLST): -#ifdef __GNUC__ - case indexof(A) ... indexof(L): - case indexof(LA) ... indexof(LL): + pgd->lower_disp_limit = prec->lopr; + pgd->upper_disp_limit = prec->hopr; break; default: -#else - break; - default: - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) - break; -#endif - recGblGetGraphicDouble(paddr,pgd); - return 0; + linkNumber = get_linkNumber(fieldIndex); + if (linkNumber >= 0) { + dbGetGraphicLimits(&prec->inpa + linkNumber, + &pgd->lower_disp_limit, + &pgd->upper_disp_limit); + } else + recGblGetGraphicDouble(paddr,pgd); } - pgd->upper_disp_limit = prec->hopr; - pgd->lower_disp_limit = prec->lopr; return 0; } static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd) { calcRecord *prec = (calcRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); - switch (index) { + switch (dbGetFieldIndex(paddr)) { case indexof(VAL): case indexof(HIHI): case indexof(HIGH): @@ -232,37 +238,36 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd) case indexof(LALM): case indexof(ALST): case indexof(MLST): -#ifdef __GNUC__ - case indexof(A) ... indexof(L): - case indexof(LA) ... indexof(LL): + pcd->lower_ctrl_limit = prec->lopr; + pcd->upper_ctrl_limit = prec->hopr; break; default: -#else - break; - default: - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) - break; -#endif recGblGetControlDouble(paddr,pcd); - return 0; } - pcd->upper_ctrl_limit = prec->hopr; - pcd->lower_ctrl_limit = prec->lopr; return 0; } static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad) { calcRecord *prec = (calcRecord *)paddr->precord; + int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; - if (dbGetFieldIndex(paddr) == indexof(VAL)) { - pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN; - pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN; - pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN; + if (fieldIndex == indexof(VAL)) { pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN; + pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN; + pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN; + pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN; } else { - recGblGetAlarmDouble(paddr, pad); + linkNumber = get_linkNumber(fieldIndex); + if (linkNumber >= 0) { + dbGetAlarmLimits(&prec->inpa + linkNumber, + &pad->lower_alarm_limit, + &pad->lower_warning_limit, + &pad->upper_warning_limit, + &pad->upper_alarm_limit); + } else + recGblGetAlarmDouble(paddr, pad); } return 0; } diff --git a/src/rec/calcoutRecord.c b/src/rec/calcoutRecord.c index 795f1db66..750fdfd0a 100644 --- a/src/rec/calcoutRecord.c +++ b/src/rec/calcoutRecord.c @@ -365,23 +365,31 @@ 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)) + return fieldIndex - indexof(A); + if (fieldIndex >= indexof(LA) && fieldIndex <= indexof(LL)) + return fieldIndex - indexof(LA); + return -1; +} + static long get_units(DBADDR *paddr, char *units) { calcoutRecord *prec = (calcoutRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); + int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; - if(index == indexof(ODLY)) { + if(fieldIndex == indexof(ODLY)) { strcpy(units, "s"); return 0; } if(paddr->pfldDes->field_type == DBF_DOUBLE) { - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) { - /* We need a way to get units for A-L */; - } else { + linkNumber = get_linkNumber(dbGetFieldIndex(paddr)); + if (linkNumber >= 0) + dbGetUnits(&prec->inpa + linkNumber, units, DB_UNITS_SIZE); + else strncpy(units,prec->egu,DB_UNITS_SIZE); - } } return 0; } @@ -389,35 +397,36 @@ static long get_units(DBADDR *paddr, char *units) static long get_precision(DBADDR *paddr, long *pprecision) { calcoutRecord *prec = (calcoutRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); + int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; - if(index == indexof(ODLY)) { + if(fieldIndex == indexof(ODLY)) { *pprecision = 2; return 0; } - *pprecision = prec->prec; - if (index == indexof(VAL)) { + if (fieldIndex == indexof(VAL)) { return 0; } - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) { - /* We need a way to get precision for A-L */; - *pprecision=15; - } - recGblGetPrec(paddr, pprecision); + linkNumber = get_linkNumber(fieldIndex); + if (linkNumber >= 0) { + short precision; + if (dbGetPrecision(&prec->inpa + linkNumber, &precision) == 0) + *pprecision = precision; + else + *pprecision = 15; + } else + recGblGetPrec(paddr, pprecision); return 0; } static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd) { calcoutRecord *prec = (calcoutRecord *)paddr->precord; - - int index = dbGetFieldIndex(paddr); + int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; - switch (index) { - case indexof(ODLY): - return 0; + switch (fieldIndex) { case indexof(VAL): case indexof(HIHI): case indexof(HIGH): @@ -426,32 +435,30 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd) case indexof(LALM): case indexof(ALST): case indexof(MLST): -#ifdef __GNUC__ - case indexof(A) ... indexof(L): - case indexof(LA) ... indexof(LL): + pgd->lower_disp_limit = prec->lopr; + pgd->upper_disp_limit = prec->hopr; break; - default: -#else - break; - default: - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) - break; -#endif + case indexof(ODLY): recGblGetGraphicDouble(paddr,pgd); - return 0; + pgd->lower_disp_limit = 0.0; + break; + default: + linkNumber = get_linkNumber(fieldIndex); + if (linkNumber >= 0) { + dbGetGraphicLimits(&prec->inpa + linkNumber, + &pgd->lower_disp_limit, + &pgd->upper_disp_limit); + } else + recGblGetGraphicDouble(paddr,pgd); } - pgd->upper_disp_limit = prec->hopr; - pgd->lower_disp_limit = prec->lopr; return 0; } static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd) { calcoutRecord *prec = (calcoutRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); - switch (index) { + switch (dbGetFieldIndex(paddr)) { case indexof(VAL): case indexof(HIHI): case indexof(HIGH): @@ -460,38 +467,40 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd) case indexof(LALM): case indexof(ALST): case indexof(MLST): -#ifdef __GNUC__ - case indexof(A) ... indexof(L): - case indexof(LA) ... indexof(LL): + pcd->lower_ctrl_limit = prec->lopr; + pcd->upper_ctrl_limit = prec->hopr; break; + case indexof(ODLY): + pcd->lower_ctrl_limit = 0.0; + pcd->upper_ctrl_limit = 10.0; + break; default: -#else - break; - default: - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) - break; -#endif recGblGetControlDouble(paddr,pcd); - if (index == indexof(ODLY)) pcd->lower_ctrl_limit = 0.0; - return 0; } - pcd->upper_ctrl_limit = prec->hopr; - pcd->lower_ctrl_limit = prec->lopr; return 0; } static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad) { calcoutRecord *prec = (calcoutRecord *)paddr->precord; + int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; - if (dbGetFieldIndex(paddr) == indexof(VAL)) { + if (fieldIndex == indexof(VAL)) { pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN; pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN; pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN; pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN; } else { - recGblGetAlarmDouble(paddr, pad); + linkNumber = get_linkNumber(fieldIndex); + if (linkNumber >= 0) { + dbGetAlarmLimits(&prec->inpa + linkNumber, + &pad->lower_alarm_limit, + &pad->lower_warning_limit, + &pad->upper_warning_limit, + &pad->upper_alarm_limit); + } else + recGblGetAlarmDouble(paddr, pad); } return 0; } diff --git a/src/rec/seqRecord.c b/src/rec/seqRecord.c index 5eff6d513..1990aff0a 100644 --- a/src/rec/seqRecord.c +++ b/src/rec/seqRecord.c @@ -58,9 +58,9 @@ static long get_precision(dbAddr *paddr, long *); #define get_enum_str NULL #define get_enum_strs NULL #define put_enum_str NULL -#define get_graphic_double NULL +static long get_graphic_double(DBADDR *, struct dbr_grDouble *); static long get_control_double(DBADDR *, struct dbr_ctrlDouble *); -#define get_alarm_double NULL +static long get_alarm_double(DBADDR *, struct dbr_alDouble *); rset seqRSET={ RSETNUMBER, @@ -421,39 +421,21 @@ static void processCallback(CALLBACK *arg) * *****************************************************************************/ #define indexof(field) seqRecord##field +#define get_dol(prec, fieldOffset) \ + &((linkDesc*)&prec->dly1)[fieldOffset>>2].dol static long get_units(DBADDR *paddr, char *units) { - switch (dbGetFieldIndex(paddr)) { - /* we need something for DO1-DOA, either EGU1-EGUA or - read EGU from DOL1-DOLA if possible - */ - case indexof(DLY1): - case indexof(DLY2): - case indexof(DLY3): - case indexof(DLY4): - case indexof(DLY5): - case indexof(DLY6): - case indexof(DLY7): - case indexof(DLY8): - case indexof(DLY9): - case indexof(DLYA): + seqRecord *prec = (seqRecord *) paddr->precord; + int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1); + + if (fieldOffset >= 0) switch (fieldOffset & 2) { + case 0: /* DLYn */ strcpy(units, "s"); break; - case indexof(DO1): - case indexof(DO2): - case indexof(DO3): - case indexof(DO4): - case indexof(DO5): - case indexof(DO6): - case indexof(DO7): - case indexof(DO8): - case indexof(DO9): - case indexof(DOA): - /* we need something here, either EGU1-EGUA or - read EGU from DOL1-DOLA if possible - */ - break; + case 2: /* DOn */ + dbGetUnits(get_dol(prec, fieldOffset), + units, DB_UNITS_SIZE); } return(0); } @@ -461,43 +443,68 @@ static long get_units(DBADDR *paddr, char *units) static long get_precision(dbAddr *paddr, long *pprecision) { seqRecord *prec = (seqRecord *) paddr->precord; + int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1); + short precision; - switch (dbGetFieldIndex(paddr)) { - case indexof(DLY1): - case indexof(DLY2): - case indexof(DLY3): - case indexof(DLY4): - case indexof(DLY5): - case indexof(DLY6): - case indexof(DLY7): - case indexof(DLY8): - case indexof(DLY9): - case indexof(DLYA): + if (fieldOffset >= 0) switch (fieldOffset & 2) { + case 0: /* DLYn */ *pprecision = 2; - return(0); - /* maybe we need specific PRECs for DO1-DOA - */ + return 0; + case 2: /* DOn */ + if (dbGetPrecision(get_dol(prec, fieldOffset), + &precision) == 0) { + *pprecision = precision; + return 0; + } } *pprecision = prec->prec; recGblGetPrec(paddr, pprecision); + return 0; +} + +static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd) +{ + seqRecord *prec = (seqRecord *) paddr->precord; + int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1); + + if (fieldOffset >= 0) switch (fieldOffset & 2) { + case 0: /* DLYn */ + pgd->lower_disp_limit = 0.0; + pgd->lower_disp_limit = 10.0; + return 0; + case 2: /* DOn */ + dbGetGraphicLimits(get_dol(prec, fieldOffset), + &pgd->lower_disp_limit, + &pgd->upper_disp_limit); + return 0; + } + recGblGetGraphicDouble(paddr,pgd); + return 0; +} + +static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd) +{ + int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1); + + recGblGetControlDouble(paddr,pcd); + if (fieldOffset >= 0 && (fieldOffset & 2) == 0) /* DLYn */ + pcd->lower_ctrl_limit = 0.0; return(0); } -static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd) +static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad) { - recGblGetControlDouble(paddr,pcd); - switch (dbGetFieldIndex(paddr)) { - case indexof(DLY1): - case indexof(DLY2): - case indexof(DLY3): - case indexof(DLY4): - case indexof(DLY5): - case indexof(DLY6): - case indexof(DLY7): - case indexof(DLY8): - case indexof(DLY9): - case indexof(DLYA): - pcd->lower_ctrl_limit = 0.0; - } - return(0); + seqRecord *prec = (seqRecord *) paddr->precord; + int fieldOffset = dbGetFieldIndex(paddr) - indexof(DLY1); + + if (fieldOffset >= 0 && (fieldOffset & 2) == 2) /* DOn */ + dbGetAlarmLimits(get_dol(prec, fieldOffset), + &pad->lower_alarm_limit, + &pad->lower_warning_limit, + &pad->upper_warning_limit, + &pad->upper_alarm_limit); + else + recGblGetAlarmDouble(paddr, pad); + return 0; } + diff --git a/src/rec/subRecord.c b/src/rec/subRecord.c index 428e6d290..1d6a2a810 100644 --- a/src/rec/subRecord.c +++ b/src/rec/subRecord.c @@ -193,18 +193,25 @@ 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)) + return fieldIndex - indexof(A); + if (fieldIndex >= indexof(LA) && fieldIndex <= indexof(LL)) + return fieldIndex - indexof(LA); + return -1; +} + static long get_units(DBADDR *paddr, char *units) { subRecord *prec = (subRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); + int linkNumber; if(paddr->pfldDes->field_type == DBF_DOUBLE) { - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) { - /* We need a way to get units for A-L */; - } else { + linkNumber = get_linkNumber(dbGetFieldIndex(paddr)); + if (linkNumber >= 0) + dbGetUnits(&prec->inpa + linkNumber, units, DB_UNITS_SIZE); + else strncpy(units,prec->egu,DB_UNITS_SIZE); - } } return 0; } @@ -212,27 +219,32 @@ static long get_units(DBADDR *paddr, char *units) static long get_precision(DBADDR *paddr, long *pprecision) { subRecord *prec = (subRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); + int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; *pprecision = prec->prec; - if (index == indexof(VAL)) { + if (fieldIndex == indexof(VAL)) { return 0; } - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) { - /* We need a way to get precision for A-L */; - *pprecision=15; - } - recGblGetPrec(paddr, pprecision); + linkNumber = get_linkNumber(fieldIndex); + if (linkNumber >= 0) { + short precision; + if (dbGetPrecision(&prec->inpa + linkNumber, &precision) == 0) + *pprecision = precision; + else + *pprecision = 15; + } else + recGblGetPrec(paddr, pprecision); return 0; } static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd) { subRecord *prec = (subRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); + int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; - switch (index) { + switch (fieldIndex) { case indexof(VAL): case indexof(HIHI): case indexof(HIGH): @@ -241,32 +253,26 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd) case indexof(LALM): case indexof(ALST): case indexof(MLST): -#ifdef __GNUC__ - case indexof(A) ... indexof(L): - case indexof(LA) ... indexof(LL): + pgd->lower_disp_limit = prec->lopr; + pgd->upper_disp_limit = prec->hopr; break; default: -#else - break; - default: - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) - break; -#endif - recGblGetGraphicDouble(paddr,pgd); - return 0; + linkNumber = get_linkNumber(fieldIndex); + if (linkNumber >= 0) { + dbGetGraphicLimits(&prec->inpa + linkNumber, + &pgd->lower_disp_limit, + &pgd->upper_disp_limit); + } else + recGblGetGraphicDouble(paddr,pgd); } - pgd->upper_disp_limit = prec->hopr; - pgd->lower_disp_limit = prec->lopr; return 0; } static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd) { subRecord *prec = (subRecord *)paddr->precord; - int index = dbGetFieldIndex(paddr); - switch (index) { + switch (dbGetFieldIndex(paddr)) { case indexof(VAL): case indexof(HIHI): case indexof(HIGH): @@ -275,23 +281,12 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd) case indexof(LALM): case indexof(ALST): case indexof(MLST): -#ifdef __GNUC__ - case indexof(A) ... indexof(L): - case indexof(LA) ... indexof(LL): + pcd->lower_ctrl_limit = prec->lopr; + pcd->upper_ctrl_limit = prec->hopr; break; default: -#else - break; - default: - if((index >= indexof(A) && index <= indexof(L)) - || (index >= indexof(LA) && index <= indexof(LL))) - break; -#endif recGblGetControlDouble(paddr,pcd); - return 0; } - pcd->upper_ctrl_limit = prec->hopr; - pcd->lower_ctrl_limit = prec->lopr; return 0; } @@ -299,6 +294,7 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad) { subRecord *prec = (subRecord *)paddr->precord; int fieldIndex = dbGetFieldIndex(paddr); + int linkNumber; if (fieldIndex == subRecordVAL) { pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN; @@ -306,7 +302,15 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad) pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN; pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN; } else { - recGblGetAlarmDouble(paddr, pad); + linkNumber = get_linkNumber(fieldIndex); + if (linkNumber >= 0) { + dbGetAlarmLimits(&prec->inpa + linkNumber, + &pad->lower_alarm_limit, + &pad->lower_warning_limit, + &pad->upper_warning_limit, + &pad->upper_alarm_limit); + } else + recGblGetAlarmDouble(paddr, pad); } return 0; }