--- /dev/null
+#define _POSIX_C_SOURCE 199509L
+
+extern "C" {
+ #include <string.h>
+}
+
+#include "paramGetRecord.h"
+
+void ArrayDestructor::run(void *todelete) {
+ aitString *pd = (aitString *) todelete;
+ delete [] pd;
+}
+
+ParamGetRecord::ParamGetRecord(caServer& cas, const Param *p, const char *rn, const char *u) :
+ ParamRecord(cas, p, rn, u)
+{
+ index = 0;
+ funcTable.installReadFunc("units", &Record::readUnits);
+ funcTable.installReadFunc("status", &Record::readStatus);
+ funcTable.installReadFunc("severity", &Record::readSeverity);
+
+ funcTable.installReadFunc("controlLow", &ParamRecord::readLowCtrl);
+ funcTable.installReadFunc("controlHigh", &ParamRecord::readHighCtrl);
+ funcTable.installReadFunc("graphicLow", &ParamRecord::readLopr);
+ funcTable.installReadFunc("graphicHigh", &ParamRecord::readHopr);
+ funcTable.installReadFunc("precision", &ParamRecord::readPrecision);
+
+ funcTable.installReadFunc("value", &ParamGetRecord::readValue);
+}
+
+ParamGetRecord::~ParamGetRecord()
+{
+ for(int k = 0 ; k < index ; k++) {
+ delete ourValue[k];
+ }
+}
+
+aitBool ParamGetRecord::paramDoesReallyExist()
+{
+ aitBool retVal = aitFalse;
+ for (int k = 0 ; k < PARAM_MAX_ARRAY_LEN ; k++) {
+ ourValue[k] = new char[PARAM_MAX_VALUE_LEN];
+ }
+
+ int rows;
+
+ if((Param_getStringArray(param, name, idx, PARAM_MAX_ARRAY_LEN, &rows, ourValue) == 0) && (rows > 0)) {
+ index = rows;
+ retVal = aitTrue;
+ }
+
+ for(int k = index ; k < PARAM_MAX_ARRAY_LEN ; k++) {
+ delete ourValue[k];
+ }
+ return retVal;
+}
+
+epicsShareFunc unsigned ParamGetRecord::maxDimension() const
+{
+ return 1u;
+}
+
+epicsShareFunc aitIndex ParamGetRecord::maxBound(unsigned dimension) const
+{
+ aitIndex retVal;
+ if(dimension == 0) {
+ retVal = index;
+ } else {
+ retVal = 1u;
+ }
+ return retVal;
+}
+
+gddAppFuncTableStatus ParamGetRecord::readValue(gdd &value)
+{
+ if(index == 1) {
+ aitString stringValue = new aitString;
+
+ stringValue = ourValue[0];
+
+ value.putConvert(stringValue);
+ } else {
+ aitString *stringValue;
+ stringValue = new aitString[index];
+ for (int k = 0 ; k < index ; k++) {
+ stringValue[k] = ourValue[k];
+ }
+
+ value.putRef(stringValue);
+ }
+
+ return S_casApp_success;
+}
+
+caStatus ParamGetRecord::scan()
+{
+ caStatus retVal;
+ caServer *pCAS = this->getCAS();
+
+ if(index == 1) {
+ aitString stringValue = new aitString;
+ val = new gddScalar(gddAppType_value, aitEnumString);
+
+ stringValue = ourValue[0];
+
+ val->putConvert(stringValue);
+ } else {
+ aitString *stringValue;
+
+ val = new gddAtomic(gddAppType_value, aitEnumString, 1, index);
+
+ stringValue = new aitString[index];
+ for (int k = 0 ; k < index ; k++) {
+ stringValue[k] = ourValue[k];
+ }
+
+ ArrayDestructor *pDest = new ArrayDestructor;
+
+ val->putRef(stringValue, pDest);
+ }
+
+ val->setStat(epicsAlarmNone);
+ val->setSevr(epicsSevNone);
+
+ if (this->interest == aitTrue && pCAS != NULL) {
+ casEventMask select(pCAS->valueEventMask|pCAS->logEventMask|pCAS->alarmEventMask);
+ this->postEvent (select, *val);
+ }
+
+ retVal = S_cas_success;
+
+ return retVal;
+}
+
+caStatus ParamGetRecord::read(const casCtx &ctx, gdd &prototype)
+{
+ return ((scan() == S_cas_success) && funcTable.read(*this, prototype));
+}
+
+caStatus ParamGetRecord::write(const casCtx &ctx, gdd &value)
+{
+ return S_cas_noWrite;
+}
+
--- /dev/null
+#ifndef PARAMGETRECORD_H
+#define PARAMGETRECORD_H
+
+#include "paramRecord.h"
+
+class ArrayDestructor : public gddDestructor {
+ virtual void run(void *);
+};
+
+class ParamGetRecord : public ParamRecord {
+ private:
+ aitIndex index;
+ char *ourValue[PARAM_MAX_ARRAY_LEN];
+ gddAppFuncTable<ParamGetRecord> funcTable;
+
+ public:
+ ParamGetRecord(caServer&, const Param *, const char *, const char *);
+ ~ParamGetRecord();
+
+ aitBool paramDoesReallyExist();
+ epicsShareFunc unsigned maxDimension() const;
+ epicsShareFunc aitIndex maxBound(unsigned int) const;
+ gddAppFuncTableStatus readValue(gdd &);
+ caStatus scan();
+ caStatus read(const casCtx &, gdd &);
+ caStatus write(const casCtx &, gdd &);
+};
+
+#endif
+
--- /dev/null
+#define _POSIX_C_SOURCE 199509L
+
+extern "C" {
+ #include <stdio.h>
+ #include <string.h>
+ #include <ctype.h>
+}
+
+#include "paramRecord.h"
+
+ParamRecord::ParamRecord(caServer& cas, const Param *p, const char *rn, const char *u) :
+ Record(cas, rn, u, aitEnumString), param(p)
+{
+ char tmp;
+ char buf1[PARAM_MAX_NAME_LEN];
+ char buf2[PARAM_MAX_NAME_LEN];
+ char buf3[PARAM_MAX_NAME_LEN];
+
+ strcpy(buf1, "");
+ strcpy(buf2, "");
+ strcpy(buf3, "");
+ sscanf(rn, "HAD:P%c:%[^:]:%[^:]:%[^:]", &tmp, buf1, buf2, buf3);
+ if(strcmp(buf3, "") == 0) {
+ strcpy(name, buf1);
+ strcpy(idx, buf2);
+ } else {
+ strcpy(name, buf2);
+ strcpy(idx, buf3);
+ }
+
+ for (int i = 0 ; i < strlen(name) ; i++) {
+ name[i] = tolower(name[i]);
+ }
+ for (int i = 0 ; i < strlen(idx) ; i++) {
+ idx[i] = tolower(idx[i]);
+ }
+ interest = aitFalse;
+}
+
+ParamRecord::~ParamRecord()
+{
+}
+
+epicsShareFunc aitEnum ParamRecord::bestExternalType() const
+{
+ return aitEnumString;
+}
+
+gddAppFuncTableStatus ParamRecord::readLowCtrl(gdd &value)
+{
+ value.putConvert(0);
+ return S_casApp_success;
+}
+
+gddAppFuncTableStatus ParamRecord::readHighCtrl(gdd &value)
+{
+ value.putConvert(0);
+ return S_casApp_success;
+}
+
+gddAppFuncTableStatus ParamRecord::readLopr(gdd &value)
+{
+ value.putConvert(0);
+ return S_casApp_success;
+}
+
+gddAppFuncTableStatus ParamRecord::readHopr(gdd &value)
+{
+ value.putConvert(0);
+ return S_casApp_success;
+}
+
+gddAppFuncTableStatus ParamRecord::readPrecision(gdd &value)
+{
+ value.putConvert(0);
+ return S_casApp_success;
+}
+
--- /dev/null
+#ifndef PARAMRECORD_H
+#define PARAMRECORD_H
+
+extern "C" {
+ #include <allParam.h>
+}
+
+#include <gdd.h>
+
+#include "record.h"
+
+class ParamRecord : public Record {
+ protected:
+ const Param *param;
+ char name[PARAM_MAX_VALUE_LEN];
+ char idx[PARAM_MAX_VALUE_LEN];
+ public:
+ ParamRecord(caServer&, const Param *, const char *, const char *);
+ ~ParamRecord();
+
+ epicsShareFunc aitEnum bestExternalType() const;
+
+ virtual gddAppFuncTableStatus readLowCtrl(gdd &);
+ virtual gddAppFuncTableStatus readHighCtrl(gdd &);
+ virtual gddAppFuncTableStatus readLopr(gdd &);
+ virtual gddAppFuncTableStatus readHopr(gdd &);
+ virtual gddAppFuncTableStatus readPrecision(gdd &);
+
+ virtual gddAppFuncTableStatus readValue(gdd &) = 0;
+
+ virtual caStatus scan() = 0;
+ virtual caStatus read(const casCtx &, gdd &) = 0;
+ virtual caStatus write(const casCtx &, gdd &) = 0;
+};
+
+#endif
+
--- /dev/null
+#define _POSIX_C_SOURCE 199509L
+
+extern "C" {
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <ctype.h>
+ #include <syslog.h>
+}
+
+#include "paramRecordSet.h"
+#include "paramGetRecord.h"
+#include "paramStoreRecord.h"
+
+ParamRecordSet::ParamRecordSet(unsigned int pvCountEstimate) :
+ caServer(pvCountEstimate)
+{
+ numParamSrc = 0;
+ numPv = 0;
+}
+
+ParamRecordSet::~ParamRecordSet()
+{
+ for (int i = 0 ; i < numParamSrc ; i++) {
+ desParam(param[i]);
+ delete param[i];
+ }
+}
+
+Param *ParamRecordSet::pParam(const char *setup)
+{
+ for (int i = 0 ; i < numParamSrc ; i++) {
+ if (param[i]->setup != NULL) {
+ if (strcmp(param[i]->setup, setup) == 0) {
+ return param[i];
+ }
+ } else {
+ if (setup == NULL) {
+ return param[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+pvExistReturn ParamRecordSet::pvExistTest(const casCtx &ctx, const char *pPVName)
+{
+ char *setup;
+ char buf1[PARAM_MAX_NAME_LEN];
+ char buf2[PARAM_MAX_NAME_LEN];
+ char buf3[PARAM_MAX_NAME_LEN];
+
+ strcpy(buf1, "");
+ strcpy(buf2, "");
+ strcpy(buf3, "");
+ if(strncmp(pPVName, "HAD:PS:", strlen("HAD:PS:")) == 0) {
+ sscanf(pPVName, "HAD:PS:[^:]:[^:]:[^:]", buf1, buf2, buf3);
+ if (strcmp(buf3, "") == 0) {
+ setup = NULL;
+ } else {
+ setup = buf1;
+ for (int i = 0 ; i < strlen(setup) ; i++) {
+ setup[i] = tolower(setup[i]);
+ }
+ }
+ if(pParam(setup) == NULL) {
+ param[numParamSrc] = new Param;
+ if (conSetupParam(param[numParamSrc], setup) == 0) {
+ numParamSrc++;
+ } else {
+ desParam(param[numParamSrc]);
+ delete param[numParamSrc];
+ }
+ }
+ if(pParam(setup) != NULL) {
+ return pverExistsHere;
+ } else {
+ return pverDoesNotExistHere;
+ }
+ } else if(strncmp(pPVName, "HAD:PG:", strlen("HAD:PG:")) == 0) {
+ sscanf(pPVName, "HAD:PG:[^:]:[^:]:[^:]", buf1, buf2, buf3);
+ if (strcmp(buf3, "") == 0) {
+ setup = NULL;
+ } else {
+ setup = buf1;
+ for (int i = 0 ; i < strlen(setup) ; i++) {
+ setup[i] = tolower(setup[i]);
+ }
+ }
+ if(pParam(setup) == NULL) {
+ param[numParamSrc] = new Param;
+ if (conSetupParam(param[numParamSrc], setup) == 0) {
+ numParamSrc++;
+ } else {
+ desParam(param[numParamSrc]);
+ delete param[numParamSrc];
+ }
+ }
+ if(pParam(setup) != NULL) {
+ ParamGetRecord *record = new ParamGetRecord(*this, pParam(setup), pPVName, "String Array");
+ if(record->paramDoesReallyExist()) {
+ delete record;
+ return pverExistsHere;
+ } else {
+ delete record;
+ return pverDoesNotExistHere;
+ }
+ } else {
+ return pverDoesNotExistHere;
+ }
+ }
+ return pverDoesNotExistHere;
+}
+
+pvCreateReturn ParamRecordSet::createPV(const casCtx &ctx, const char *pPVName)
+{
+ pvCreateReturn retVal(S_casApp_pvNotFound);
+ char *setup;
+ char buf1[PARAM_MAX_NAME_LEN];
+ char buf2[PARAM_MAX_NAME_LEN];
+ char buf3[PARAM_MAX_NAME_LEN];
+
+ strcpy(buf1, "");
+ strcpy(buf2, "");
+ strcpy(buf3, "");
+ if(strncmp(pPVName, "HAD:PS:", strlen("HAD:PS:")) == 0) {
+ sscanf(pPVName, "HAD:PS:[^:]:[^:]:[^:]", buf1, buf2, buf3);
+ if (strcmp(buf3, "") == 0) {
+ setup = NULL;
+ } else {
+ setup = buf1;
+ for (int i = 0 ; i < strlen(setup) ; i++) {
+ setup[i] = tolower(setup[i]);
+ }
+ }
+ if(pParam(setup) != NULL) {
+ retVal = (pvs[numPv++] = new ParamStoreRecord(*this, pParam(setup), pPVName, "String"));
+ return retVal;
+ } else {
+ return S_casApp_pvNotFound;
+ }
+ } else if(strncmp(pPVName, "HAD:PG:", strlen("HAD:PG:")) == 0) {
+ sscanf(pPVName, "HAD:PG:[^:]:[^:]:[^:]", buf1, buf2, buf3);
+ if (strcmp(buf3, "") == 0) {
+ setup = NULL;
+ } else {
+ setup = buf1;
+ for (int i = 0 ; i < strlen(setup) ; i++) {
+ setup[i] = tolower(setup[i]);
+ }
+ }
+ if(pParam(setup) != NULL) {
+ ParamGetRecord *record = new ParamGetRecord(*this, pParam(setup), pPVName, "String Array");
+ if(record->paramDoesReallyExist()) {
+ pvs[numPv++] = record;
+ retVal = record;
+ return retVal;
+ } else {
+ delete record;
+ return S_casApp_pvNotFound;
+ }
+ } else {
+ return S_casApp_pvNotFound;
+ }
+ }
+ return S_casApp_pvNotFound;
+}
+
--- /dev/null
+#ifndef PARAMRECORDSET_H
+#define PARAMRECORDSET_H
+
+extern "C" {
+ #include <allParam.h>
+}
+
+#include <casdef.h>
+
+#include "paramRecord.h"
+
+#define MAX_PARAM_SRC 16
+#define PV_COUNT_EST 1024
+
+class ParamRecordSet : public caServer {
+ private:
+ int numPv;
+ ParamRecord *pvs[PV_COUNT_EST];
+
+ int numParamSrc;
+ Param *param[MAX_PARAM_SRC];
+ Param *pParam(const char *);
+
+ public:
+ ParamRecordSet(unsigned int);
+ ~ParamRecordSet();
+ pvExistReturn pvExistTest(const casCtx &, const char *);
+ pvCreateReturn createPV(const casCtx &, const char *);
+};
+
+#endif
+
--- /dev/null
+#define _POSIX_C_SOURCE 199509L
+
+#include <stdiostream.h>
+
+extern "C" {
+ #include <unistd.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <syslog.h>
+}
+
+#include <fdManager.h>
+
+#include "paramRecordSet.h"
+
+int main(int argc, char *argv[]) {
+ openlog(argv[0], LOG_PERROR | LOG_PID, LOG_LOCAL0);
+
+ ParamRecordSet *cas;
+
+ if (NULL == (cas = new ParamRecordSet(PV_COUNT_EST))) {
+ syslog(LOG_ERR, "Cannot allocate memory for the RecordSet. Exiting.\n");
+ exit(-1);
+ }
+
+ cas->setDebugLevel(0u);
+
+ while (aitTrue) {
+ osiTime delay(1000u, 0u);
+ fileDescriptorManager.process(delay);
+ }
+
+ delete cas;
+ closelog();
+ return 0;
+}
+
--- /dev/null
+#define _POSIX_C_SOURCE 199509L
+
+extern "C" {
+ #include <string.h>
+}
+
+#include "paramStoreRecord.h"
+
+ParamStoreRecord::ParamStoreRecord(caServer& cas, const Param *p, const char *rn, const char *u) :
+ ParamRecord(cas, p, rn, u)
+{
+ funcTable.installReadFunc("units", &Record::readUnits);
+ funcTable.installReadFunc("status", &Record::readStatus);
+ funcTable.installReadFunc("severity", &Record::readSeverity);
+
+ funcTable.installReadFunc("controlLow", &ParamRecord::readLowCtrl);
+ funcTable.installReadFunc("controlHigh", &ParamRecord::readHighCtrl);
+ funcTable.installReadFunc("graphicLow", &ParamRecord::readLopr);
+ funcTable.installReadFunc("graphicHigh", &ParamRecord::readHopr);
+ funcTable.installReadFunc("precision", &ParamRecord::readPrecision);
+
+ funcTable.installReadFunc("value", &ParamStoreRecord::readValue);
+}
+
+ParamStoreRecord::~ParamStoreRecord()
+{
+}
+
+gddAppFuncTableStatus ParamStoreRecord::readValue(gdd &value)
+{
+ return S_casApp_noSupport;
+}
+
+caStatus ParamStoreRecord::scan()
+{
+ return S_casApp_noSupport;
+}
+
+caStatus ParamStoreRecord::read(const casCtx &ctx, gdd &prototype)
+{
+ return S_casApp_noSupport;
+}
+
+caStatus ParamStoreRecord::write(const casCtx &ctx, gdd &value)
+{
+ fprintf(stderr, "Entered ParamStoreRecord::write\n");
+ caServer *pCAS = this->getCAS();
+
+ aitString stringValue;
+
+ value.getConvert(stringValue);
+
+ char ourValue[PARAM_MAX_VALUE_LEN];
+ strcpy(ourValue, (const char *) stringValue);
+ fprintf(stderr, "ourValue to write: %s\n", ourValue);
+
+ Param_storeString(param, name, idx, ourValue);
+
+ fprintf(stderr, "Leaving ParamStoreRecord::write\n");
+ return S_cas_success;
+}
+
--- /dev/null
+#ifndef PARAMSTORERECORD_H
+#define PARAMSTORERECORD_H
+
+#include "paramRecord.h"
+
+class ParamStoreRecord : public ParamRecord {
+ private:
+ aitIndex index;
+ gddAppFuncTable<ParamStoreRecord> funcTable;
+
+ public:
+ ParamStoreRecord(caServer&, const Param *, const char *, const char *);
+ ~ParamStoreRecord();
+
+ gddAppFuncTableStatus readValue(gdd &);
+ caStatus scan();
+ caStatus read(const casCtx &, gdd &);
+ caStatus write(const casCtx &, gdd &);
+};
+
+#endif
+
--- /dev/null
+#define _POSIX_C_SOURCE 199509L
+
+extern "C" {
+ #include <string.h>
+}
+
+#include "record.h"
+
+/********************
+ * record Functions *
+ ********************/
+
+Record::Record(caServer &cas, const char *n, const char *u, aitEnum t) : casPV(cas), units(u), type(t) {
+ strcpy (name, n);
+ interest = aitFalse;
+
+ alarmStatus = epicsAlarmNone;
+ alarmSeverity = epicsSevNone;
+
+ recordScanTimer = new scanTimer(*this);
+}
+
+Record::~Record() {
+}
+
+/* Misc Functions which are the same in all records */
+
+void Record::destroy() {
+}
+
+caStatus Record::interestRegister() {
+ interest = aitTrue;
+ return S_casApp_success;
+}
+
+void Record::interestDelete() {
+ interest = aitFalse;
+}
+
+const char *Record::getName() const {
+ return name;
+}
+
+aitEnum Record::bestExternalType() const {
+ return type;
+}
+
+/* Read Functions which are the same for all records */
+
+gddAppFuncTableStatus Record::readUnits(gdd &value) {
+ value.putConvert(*units);
+ return S_casApp_success;
+}
+
+gddAppFuncTableStatus Record::readStatus(gdd &value) {
+ value.putConvert(alarmStatus);
+ return S_casApp_success;
+}
+
+gddAppFuncTableStatus Record::readSeverity(gdd &value) {
+ value.putConvert(alarmSeverity);
+ return S_casApp_success;
+}
+
+/***********************
+ * scanTimer Functions *
+ ***********************/
+
+scanTimer::scanTimer (Record &pv) : osiTimer(1.0), procVar(pv) {
+}
+
+void scanTimer::expire() {
+ procVar.scan();
+}
+
+osiBool scanTimer::again() const {
+ return osiTrue;
+}
+
--- /dev/null
+#ifndef RECORD_H
+#define RECORD_H
+
+#include <casdef.h>
+
+#include <osiTimer.h>
+#include <aitTypes.h>
+#include <aitHelpers.h>
+
+#include <gddApps.h>
+#include <gddAppFuncTable.h>
+
+#define NAMELENGTH 28
+
+class scanTimer;
+
+class Record : public casPV {
+ protected:
+ char name[NAMELENGTH + 1];
+ const char *units;
+ aitEnum type;
+ gdd *val;
+ scanTimer *recordScanTimer;
+ aitBool interest;
+ epicsAlarmCondition alarmStatus;
+ epicsAlarmSeverity alarmSeverity;
+ public:
+ Record(caServer&, const char*, const char*, aitEnum);
+ ~Record();
+
+ void destroy();
+ caStatus interestRegister();
+ void interestDelete();
+ const char *getName() const;
+ aitEnum bestExternalType() const;
+
+ gddAppFuncTableStatus readUnits(gdd &);
+ gddAppFuncTableStatus readStatus(gdd &);
+ gddAppFuncTableStatus readSeverity(gdd &);
+
+ virtual gddAppFuncTableStatus readValue(gdd &) = 0;
+ virtual caStatus scan() = 0;
+ virtual caStatus read(const casCtx &, gdd &) = 0;
+ virtual caStatus write(const casCtx &, gdd &) = 0;
+};
+
+class scanTimer : public osiTimer {
+ private:
+ Record &procVar;
+ public:
+ scanTimer(Record &);
+ void expire();
+ osiBool again() const;
+};
+
+#endif
+