diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 5c957e771..cf0f0b674 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -369,6 +369,10 @@ giving correct initial monitor behavior in some circumstances.
Fixed a crash when ALG (algorithm) was changed to Average at runtime.
+Named Soft Events
+
+Soft events can now be meaningful strings instead of numbers 1-255.
+
configure/RELEASE Enhancements
Variable definitions in a configure/RELEASE file may now use the
diff --git a/named-soft-events.patch b/named-soft-events.patch
new file mode 100644
index 000000000..372969375
--- /dev/null
+++ b/named-soft-events.patch
@@ -0,0 +1,575 @@
+=== modified file 'documentation/RELEASE_NOTES.html'
+--- documentation/RELEASE_NOTES.html 2010-10-26 15:49:26 +0000
++++ documentation/RELEASE_NOTES.html 2010-10-27 20:51:01 +0000
+@@ -138,6 +138,10 @@
+
+
Fixed crash when ALG (algorithm) was changed to Average at runtime.
+
++Named Soft Events
++
++Soft events can now be meaningful strings instead of numbers 1-255.
++
+
configure/RELEASE Enhancements
+
+ Variable definitions in a configure/RELEASE file may now use the
+
+=== modified file 'src/db/dbCommon.dbd'
+--- src/db/dbCommon.dbd 2009-04-23 20:35:02 +0000
++++ src/db/dbCommon.dbd 2010-10-27 20:51:01 +0000
+@@ -43,10 +43,11 @@
+ special(SPC_SCAN)
+ interest(1)
+ }
+- field(EVNT,DBF_SHORT) {
+- prompt("Event Number")
++ field(EVNT,DBF_STRING) {
++ prompt("Event Name")
+ promptgroup(GUI_SCAN)
+ special(SPC_SCAN)
++ size(40)
+ interest(1)
+ }
+ field(TSE,DBF_SHORT) {
+
+=== modified file 'src/db/dbIocRegister.c'
+--- src/db/dbIocRegister.c 2009-01-16 20:50:40 +0000
++++ src/db/dbIocRegister.c 2010-10-27 20:51:01 +0000
+@@ -266,11 +266,11 @@
+ { scanppl(args[0].dval);}
+
+ /* scanpel */
+-static const iocshArg scanpelArg0 = { "event number",iocshArgInt};
++static const iocshArg scanpelArg0 = { "event name",iocshArgString};
+ static const iocshArg * const scanpelArgs[1] = {&scanpelArg0};
+ static const iocshFuncDef scanpelFuncDef = {"scanpel",1,scanpelArgs};
+ static void scanpelCallFunc(const iocshArgBuf *args)
+-{ scanpel(args[0].ival);}
++{ scanpel(args[0].sval);}
+
+ /* scanpiol */
+ static const iocshFuncDef scanpiolFuncDef = {"scanpiol",0};
+
+=== modified file 'src/db/dbScan.c'
+--- src/db/dbScan.c 2009-04-03 17:46:26 +0000
++++ src/db/dbScan.c 2010-10-27 20:51:01 +0000
+@@ -101,12 +101,13 @@
+
+ /* EVENT */
+
+-#define MAX_EVENTS 256
+-typedef struct event_scan_list {
+- CALLBACK callback;
+- scan_list scan_list;
+-} event_scan_list;
+-static event_scan_list *pevent_list[NUM_CALLBACK_PRIORITIES][MAX_EVENTS];
++typedef struct event_list {
++ CALLBACK callback[NUM_CALLBACK_PRIORITIES];
++ scan_list scan_list[NUM_CALLBACK_PRIORITIES];
++ struct event_list *next;
++ char event_name[MAX_STRING_SIZE];
++} event_list;
++static event_list * volatile pevent_list[256];
+
+
+ /* IO_EVENT*/
+@@ -204,35 +205,24 @@
+ recGblRecordError(-1, (void *)precord,
+ "scanAdd detected illegal SCAN value");
+ } else if (scan == menuScanEvent) {
+- int evnt;
++ char* eventname;
+ int prio;
+- event_scan_list *pesl;
++ event_list *pel;
+
+- evnt = precord->evnt;
+- if (evnt < 0 || evnt >= MAX_EVENTS) {
++ eventname = precord->evnt;
++ if (strlen(eventname) >= MAX_STRING_SIZE) {
+ recGblRecordError(S_db_badField, (void *)precord,
+- "scanAdd detected illegal EVNT value");
+- precord->scan = menuScanPassive;
++ "scanAdd: too long EVNT value");
+ return;
+ }
+ prio = precord->prio;
+ if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
+ recGblRecordError(-1, (void *)precord,
+ "scanAdd: illegal prio field");
+- precord->scan = menuScanPassive;
+ return;
+ }
+- pesl = pevent_list[prio][evnt];
+- if (pesl == NULL) {
+- pesl = dbCalloc(1, sizeof(event_scan_list));
+- pevent_list[prio][evnt] = pesl;
+- pesl->scan_list.lock = epicsMutexMustCreate();
+- callbackSetCallback(eventCallback, &pesl->callback);
+- callbackSetPriority(prio, &pesl->callback);
+- callbackSetUser(pesl, &pesl->callback);
+- ellInit(&pesl->scan_list.list);
+- }
+- addToList(precord, &pesl->scan_list);
++ pel = eventNameToHandle(eventname);
++ if (pel) addToList(precord, &pel->scan_list[prio]);
+ } else if (scan == menuScanI_O_Intr) {
+ io_scan_list *piosl = NULL;
+ int prio;
+@@ -287,31 +277,25 @@
+ recGblRecordError(-1, (void *)precord,
+ "scanDelete detected illegal SCAN value");
+ } else if (scan == menuScanEvent) {
+- int evnt;
++ char* eventname;
+ int prio;
+- event_scan_list *pesl;
++ event_list *pel;
+ scan_list *psl = 0;
+
+- evnt = precord->evnt;
+- if (evnt < 0 || evnt >= MAX_EVENTS) {
+- recGblRecordError(S_db_badField, (void *)precord,
+- "scanAdd detected illegal EVNT value");
+- precord->scan = menuScanPassive;
+- return;
+- }
++ eventname = precord->evnt;
+ prio = precord->prio;
+ if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
+ recGblRecordError(-1, (void *)precord,
+- "scanAdd: illegal prio field");
+- precord->scan = menuScanPassive;
++ "scanDelete detected illegal PRIO field");
+ return;
+ }
+- pesl = pevent_list[prio][evnt];
+- if (pesl) psl = &pesl->scan_list;
+- if (!pesl || !psl)
+- recGblRecordError(-1, (void *)precord,
+- "scanDelete for bad evnt");
+- else
++ do /* multithreading: make sure pel is consistent */
++ pel = pevent_list[0];
++ while (pel != pevent_list[0]);
++ for (; pel; pel=pel->next) {
++ if (strcmp(pel->event_name, eventname) == 0) break;
++ }
++ if (pel && (psl = &pel->scan_list[prio]))
+ deleteFromList(precord, psl);
+ } else if (scan == menuScanI_O_Intr) {
+ io_scan_list *piosl=NULL;
+@@ -372,21 +356,22 @@
+ return 0;
+ }
+
+-int scanpel(int event_number) /* print event list */
++int scanpel(char* eventname) /* print event list */
+ {
+ char message[80];
+- int prio, evnt;
+- event_scan_list *pesl;
+-
+- for (evnt = 0; evnt < MAX_EVENTS; evnt++) {
+- if (event_number && evntevent_number) break;
+- for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
+- pesl = pevent_list[prio][evnt];
+- if (!pesl) continue;
+- if (ellCount(&pesl->scan_list.list) == 0) continue;
+- sprintf(message, "Event %d Priority %s", evnt, priorityName[prio]);
+- printList(&pesl->scan_list, message);
++ int prio;
++ event_list *pel;
++
++ do /* multithreading: make sure pel is consistent */
++ pel = pevent_list[0];
++ while (pel != pevent_list[0]);
++ for (; pel; pel = pel->next) {
++ if (!eventname || strcmp(pel->event_name, eventname) == 0) {
++ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
++ if (ellCount(&pel->scan_list[prio].list) == 0) continue;
++ sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]);
++ printList(&pel->scan_list[prio], message);
++ }
+ }
+ }
+ return 0;
+@@ -412,39 +397,73 @@
+
+ static void eventCallback(CALLBACK *pcallback)
+ {
+- event_scan_list *pesl;
++ scan_list *psl;
+
+- callbackGetUser(pesl, pcallback);
+- scanList(&pesl->scan_list);
++ callbackGetUser(psl, pcallback);
++ scanList(psl);
+ }
+
+ static void initEvent(void)
+ {
+- int evnt, prio;
+-
++}
++
++event_list *eventNameToHandle(char *eventname)
++{
++ int prio;
++ event_list *pel;
++ static epicsMutexId lock = NULL;
++
++ if (!lock) lock = epicsMutexMustCreate();
++ if (!eventname || eventname[0] == 0) return NULL;
++ epicsMutexMustLock(lock);
++ for (pel = pevent_list[0]; pel; pel=pel->next) {
++ if (strcmp(pel->event_name, eventname) == 0) break;
++ }
++ if (pel == NULL) {
++ pel = dbCalloc(1, sizeof(event_list));
++ strcpy(pel->event_name, eventname);
++ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
++ callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]);
++ callbackSetPriority(prio, &pel->callback[prio]);
++ callbackSetCallback(eventCallback, &pel->callback[prio]);
++ pel->scan_list[prio].lock = epicsMutexMustCreate();
++ ellInit(&pel->scan_list[prio].list);
++ }
++ pel->next=pevent_list[0];
++ pevent_list[0]=pel;
++ { /* backward compatibility */
++ char* p;
++ long e = strtol(eventname, &p, 0);
++ if (*p == 0 && e > 0 && e <= 255)
++ pevent_list[e]=pel;
++ }
++ }
++ epicsMutexUnlock(lock);
++ return pel;
++}
++
++void postEvent(event_list *pel)
++{
++ int prio;
++
++ if (scanCtl != ctlRun) return;
++ if (!pel) return;
+ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
+- for (evnt = 0; evnt < MAX_EVENTS; evnt++) {
+- pevent_list[prio][evnt] = NULL;
+- }
++ if (ellCount(&pel->scan_list[prio].list) >0)
++ callbackRequest(&pel->callback[prio]);
+ }
+ }
+
++/* backward compatibility */
+ void post_event(int event)
+ {
+- int prio;
+- event_scan_list *pesl;
+-
+- if (scanCtl != ctlRun) return;
+- if (event < 0 || event >= MAX_EVENTS) {
+- errMessage(-1, "illegal event passed to post_event");
+- return;
+- }
+- for (prio=0; prioscan_list.list) >0)
+- callbackRequest((void *)pesl);
+- }
++ event_list* pel;
++
++ if (event <= 0 || event > 255) return;
++ do { /* multithreading: make sure pel is consistent */
++ pel = pevent_list[event];
++ } while (pel != pevent_list[event]);
++ postEvent(pel);
+ }
+
+ void scanIoInit(IOSCANPVT *ppioscanpvt)
+
+=== modified file 'src/db/dbScan.h'
+--- src/db/dbScan.h 2010-10-05 19:27:37 +0000
++++ src/db/dbScan.h 2010-10-27 20:51:01 +0000
+@@ -19,6 +19,7 @@
+
+ #include "menuScan.h"
+ #include "shareLib.h"
++#include "compilerDependencies.h"
+
+ #ifdef __cplusplus
+ extern "C" {
+@@ -36,6 +37,7 @@
+ struct io_scan_list;
+
+ typedef struct io_scan_list *IOSCANPVT;
++typedef struct event_list *EVENTPVT;
+
+ struct dbCommon;
+
+@@ -43,7 +45,9 @@
+ epicsShareFunc void scanRun(void);
+ epicsShareFunc void scanPause(void);
+
+-epicsShareFunc void post_event(int event);
++epicsShareFunc EVENTPVT eventNameToHandle(char* event);
++epicsShareFunc void postEvent(EVENTPVT epvt);
++epicsShareFunc void post_event(int event) EPICS_DEPRECATED;
+ epicsShareFunc void scanAdd(struct dbCommon *);
+ epicsShareFunc void scanDelete(struct dbCommon *);
+ epicsShareFunc double scanPeriod(int scan);
+@@ -54,7 +58,7 @@
+ epicsShareFunc int scanppl(double rate);
+
+ /*print event lists*/
+-epicsShareFunc int scanpel(int event_number);
++epicsShareFunc int scanpel(char *event_name);
+
+ /*print io_event list*/
+ epicsShareFunc int scanpiol(void);
+
+=== modified file 'src/dev/softDev/devEventSoft.c'
+--- src/dev/softDev/devEventSoft.c 2010-10-05 19:27:37 +0000
++++ src/dev/softDev/devEventSoft.c 2010-10-27 20:51:01 +0000
+@@ -51,7 +51,7 @@
+ /* INP must be CONSTANT, PV_LINK, DB_LINK or CA_LINK*/
+ switch (prec->inp.type) {
+ case CONSTANT:
+- if (recGblInitConstantLink(&prec->inp, DBF_USHORT, &prec->val))
++ if (recGblInitConstantLink(&prec->inp, DBF_STRING, &prec->val))
+ prec->udf = FALSE;
+ break;
+ case PV_LINK:
+@@ -69,13 +69,20 @@
+ static long read_event(eventRecord *prec)
+ {
+ long status;
++ char newEvent[MAX_STRING_SIZE];
+
+- status = dbGetLink(&prec->inp, DBR_USHORT, &prec->val, 0, 0);
+- if (!status) {
+- prec->udf = FALSE;
+- if (prec->tsel.type == CONSTANT &&
+- prec->tse == epicsTimeEventDeviceTime)
+- dbGetTimeStamp(&prec->inp, &prec->time);
++ if (prec->inp.type != CONSTANT)
++ {
++ status = dbGetLinkValue(&prec->inp, DBR_STRING, newEvent, 0, 0);
++ if (status) return status;
++ if (strcmp(newEvent, prec->val) != 0) {
++ strcpy(prec->val, newEvent);
++ prec->epvt = eventNameToHandle(prec->val);
++ }
+ }
+- return status;
++ prec->udf = FALSE;
++ if (prec->tsel.type == CONSTANT &&
++ prec->tse == epicsTimeEventDeviceTime)
++ dbGetTimeStamp(&prec->inp, &prec->time);
++ return 0;
+ }
+
+=== modified file 'src/rec/calcoutRecord.c'
+--- src/rec/calcoutRecord.c 2010-04-05 18:49:18 +0000
++++ src/rec/calcoutRecord.c 2010-10-27 20:51:01 +0000
+@@ -197,6 +197,8 @@
+ callbackSetUser(prec, &prpvt->checkLinkCb);
+ prpvt->cbScheduled = 0;
+
++ prec->epvt = eventNameToHandle(prec->oevt);
++
+ if (pcalcoutDSET->init_record) pcalcoutDSET->init_record(prec);
+ prec->pval = prec->val;
+ prec->mlst = prec->val;
+@@ -357,6 +359,9 @@
+ }
+ db_post_events(prec, plinkValid, DBE_VALUE);
+ return 0;
++ case(calcoutRecordOEVT):
++ prec->epvt = eventNameToHandle(prec->oevt);
++ return 0;
+ default:
+ recGblDbaddrError(S_db_badChoice, paddr, "calc: special");
+ return(S_db_badChoice);
+@@ -539,27 +544,21 @@
+ if (prec->nsev < INVALID_ALARM ) {
+ /* Output the value */
+ status = writeValue(prec);
+- /* post event if output event != 0 */
+- if (prec->oevt > 0) {
+- post_event((int)prec->oevt);
+- }
++ /* post output event if set */
++ if (prec->epvt) postEvent(prec->epvt);
+ } else switch (prec->ivoa) {
+ case menuIvoaContinue_normally:
+ status = writeValue(prec);
+- /* post event if output event != 0 */
+- if (prec->oevt > 0) {
+- post_event((int)prec->oevt);
+- }
++ /* post output event if set */
++ if (prec->epvt) postEvent(prec->epvt);
+ break;
+ case menuIvoaDon_t_drive_outputs:
+ break;
+ case menuIvoaSet_output_to_IVOV:
+ prec->oval = prec->ivov;
+ status = writeValue(prec);
+- /* post event if output event != 0 */
+- if (prec->oevt > 0) {
+- post_event((int)prec->oevt);
+- }
++ /* post output event if set */
++ if (prec->epvt) postEvent(prec->epvt);
+ break;
+ default:
+ status = -1;
+
+=== modified file 'src/rec/calcoutRecord.dbd'
+--- src/rec/calcoutRecord.dbd 2010-10-04 18:46:09 +0000
++++ src/rec/calcoutRecord.dbd 2010-10-27 20:51:01 +0000
+@@ -255,10 +255,19 @@
+ prompt("OCAL Valid")
+ interest(1)
+ }
+- field(OEVT,DBF_USHORT) {
++ field(OEVT,DBF_STRING) {
+ prompt("Event To Issue")
+ promptgroup(GUI_CLOCK)
++ special(SPC_MOD)
+ asl(ASL0)
++ size(40)
++ }
++ %#include "dbScan.h"
++ field(EPVT, DBF_NOACCESS) {
++ prompt("Event private")
++ special(SPC_NOMOD)
++ interest(4)
++ extra("EVENTPVT epvt")
+ }
+ field(IVOA,DBF_MENU) {
+ prompt("INVALID output action")
+
+=== modified file 'src/rec/eventRecord.c'
+--- src/rec/eventRecord.c 2010-10-05 19:27:37 +0000
++++ src/rec/eventRecord.c 2010-10-27 20:51:01 +0000
+@@ -32,6 +32,7 @@
+ #include "errMdef.h"
+ #include "recSup.h"
+ #include "recGbl.h"
++#include "special.h"
+ #include "menuYesNo.h"
+ #define GEN_SIZE_OFFSET
+ #include "eventRecord.h"
+@@ -43,7 +44,7 @@
+ #define initialize NULL
+ static long init_record(eventRecord *, int);
+ static long process(eventRecord *);
+-#define special NULL
++static long special(DBADDR *, int);
+ static long get_value(eventRecord *, struct valueDes *);
+ #define cvt_dbaddr NULL
+ #define get_array_info NULL
+@@ -103,9 +104,11 @@
+ }
+
+ if (prec->siol.type == CONSTANT) {
+- recGblInitConstantLink(&prec->siol,DBF_USHORT,&prec->sval);
++ recGblInitConstantLink(&prec->siol,DBF_STRING,&prec->sval);
+ }
+
++ prec->epvt = eventNameToHandle(prec->val);
++
+ if( (pdset=(struct eventdset *)(prec->dset)) && (pdset->init_record) )
+ status=(*pdset->init_record)(prec);
+ return(status);
+@@ -123,7 +126,7 @@
+ if ( !pact && prec->pact ) return(0);
+ prec->pact = TRUE;
+
+- if(prec->val>0) post_event((int)prec->val);
++ postEvent(prec->epvt);
+
+ recGblGetTimeStamp(prec);
+
+@@ -137,10 +140,21 @@
+ return(status);
+ }
+
++
++static long special(DBADDR *paddr, int after)
++{
++ eventRecord *prec = (eventRecord *)paddr->precord;
++
++ if (!after) return 0;
++ if (dbGetFieldIndex(paddr) == eventRecordVAL) {
++ prec->epvt = eventNameToHandle(prec->val);
++ }
++}
+
++
+ static long get_value(eventRecord *prec, struct valueDes *pvdes)
+ {
+- pvdes->field_type = DBF_USHORT;
++ pvdes->field_type = DBF_STRING;
+ pvdes->no_elements=1;
+ pvdes->pvalue = (void *)(&prec->val);
+ return(0);
+@@ -177,10 +191,13 @@
+ return(status);
+ }
+ if (prec->simm == menuYesNoYES){
+- status=dbGetLink(&(prec->siol),DBR_USHORT,
++ status=dbGetLink(&(prec->siol),DBR_STRING,
+ &(prec->sval),0,0);
+ if (status==0) {
+- prec->val=prec->sval;
++ if (strcmp(prec->sval, prec->val) != 0) {
++ strcpy(prec->val, prec->sval);
++ prec->epvt = eventNameToHandle(prec->val);
++ }
+ prec->udf=FALSE;
+ }
+ } else {
+
+=== modified file 'src/rec/eventRecord.dbd'
+--- src/rec/eventRecord.dbd 2002-07-12 21:35:43 +0000
++++ src/rec/eventRecord.dbd 2010-10-27 20:51:01 +0000
+@@ -9,10 +9,19 @@
+ #*************************************************************************
+ recordtype(event) {
+ include "dbCommon.dbd"
+- field(VAL,DBF_USHORT) {
+- prompt("Event Number To Post")
++ field(VAL,DBF_STRING) {
++ prompt("Event Name To Post")
+ promptgroup(GUI_INPUTS)
++ special(SPC_MOD)
+ asl(ASL0)
++ size(40)
++ }
++ %#include "dbScan.h"
++ field(EPVT, DBF_NOACCESS) {
++ prompt("Event private")
++ special(SPC_NOMOD)
++ interest(4)
++ extra("EVENTPVT epvt")
+ }
+ field(INP,DBF_INLINK) {
+ prompt("Input Specification")
+@@ -24,8 +33,9 @@
+ promptgroup(GUI_INPUTS)
+ interest(1)
+ }
+- field(SVAL,DBF_USHORT) {
++ field(SVAL,DBF_STRING) {
+ prompt("Simulation Value")
++ size(40)
+ }
+ field(SIML,DBF_INLINK) {
+ prompt("Sim Mode Location")
+
diff --git a/src/db/dbCommon.dbd b/src/db/dbCommon.dbd
index eb8e7bf35..94128ca35 100644
--- a/src/db/dbCommon.dbd
+++ b/src/db/dbCommon.dbd
@@ -43,10 +43,11 @@
special(SPC_SCAN)
interest(1)
}
- field(EVNT,DBF_SHORT) {
- prompt("Event Number")
+ field(EVNT,DBF_STRING) {
+ prompt("Event Name")
promptgroup(GUI_SCAN)
special(SPC_SCAN)
+ size(40)
interest(1)
}
field(TSE,DBF_SHORT) {
diff --git a/src/db/dbIocRegister.c b/src/db/dbIocRegister.c
index a82337f03..c64738bbd 100644
--- a/src/db/dbIocRegister.c
+++ b/src/db/dbIocRegister.c
@@ -266,11 +266,11 @@ static void scanpplCallFunc(const iocshArgBuf *args)
{ scanppl(args[0].dval);}
/* scanpel */
-static const iocshArg scanpelArg0 = { "event number",iocshArgInt};
+static const iocshArg scanpelArg0 = { "event name",iocshArgString};
static const iocshArg * const scanpelArgs[1] = {&scanpelArg0};
static const iocshFuncDef scanpelFuncDef = {"scanpel",1,scanpelArgs};
static void scanpelCallFunc(const iocshArgBuf *args)
-{ scanpel(args[0].ival);}
+{ scanpel(args[0].sval);}
/* scanpiol */
static const iocshFuncDef scanpiolFuncDef = {"scanpiol",0};
diff --git a/src/db/dbScan.c b/src/db/dbScan.c
index 5a372d6a9..1720a5d85 100644
--- a/src/db/dbScan.c
+++ b/src/db/dbScan.c
@@ -101,12 +101,13 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = {
/* EVENT */
-#define MAX_EVENTS 256
-typedef struct event_scan_list {
- CALLBACK callback;
- scan_list scan_list;
-} event_scan_list;
-static event_scan_list *pevent_list[NUM_CALLBACK_PRIORITIES][MAX_EVENTS];
+typedef struct event_list {
+ CALLBACK callback[NUM_CALLBACK_PRIORITIES];
+ scan_list scan_list[NUM_CALLBACK_PRIORITIES];
+ struct event_list *next;
+ char event_name[MAX_STRING_SIZE];
+} event_list;
+static event_list * volatile pevent_list[256];
/* IO_EVENT*/
@@ -204,35 +205,24 @@ void scanAdd(struct dbCommon *precord)
recGblRecordError(-1, (void *)precord,
"scanAdd detected illegal SCAN value");
} else if (scan == menuScanEvent) {
- int evnt;
+ char* eventname;
int prio;
- event_scan_list *pesl;
+ event_list *pel;
- evnt = precord->evnt;
- if (evnt < 0 || evnt >= MAX_EVENTS) {
+ eventname = precord->evnt;
+ if (strlen(eventname) >= MAX_STRING_SIZE) {
recGblRecordError(S_db_badField, (void *)precord,
- "scanAdd detected illegal EVNT value");
- precord->scan = menuScanPassive;
+ "scanAdd: too long EVNT value");
return;
}
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
"scanAdd: illegal prio field");
- precord->scan = menuScanPassive;
return;
}
- pesl = pevent_list[prio][evnt];
- if (pesl == NULL) {
- pesl = dbCalloc(1, sizeof(event_scan_list));
- pevent_list[prio][evnt] = pesl;
- pesl->scan_list.lock = epicsMutexMustCreate();
- callbackSetCallback(eventCallback, &pesl->callback);
- callbackSetPriority(prio, &pesl->callback);
- callbackSetUser(pesl, &pesl->callback);
- ellInit(&pesl->scan_list.list);
- }
- addToList(precord, &pesl->scan_list);
+ pel = eventNameToHandle(eventname);
+ if (pel) addToList(precord, &pel->scan_list[prio]);
} else if (scan == menuScanI_O_Intr) {
io_scan_list *piosl = NULL;
int prio;
@@ -287,31 +277,25 @@ void scanDelete(struct dbCommon *precord)
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal SCAN value");
} else if (scan == menuScanEvent) {
- int evnt;
+ char* eventname;
int prio;
- event_scan_list *pesl;
+ event_list *pel;
scan_list *psl = 0;
- evnt = precord->evnt;
- if (evnt < 0 || evnt >= MAX_EVENTS) {
- recGblRecordError(S_db_badField, (void *)precord,
- "scanAdd detected illegal EVNT value");
- precord->scan = menuScanPassive;
- return;
- }
+ eventname = precord->evnt;
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
- "scanAdd: illegal prio field");
- precord->scan = menuScanPassive;
+ "scanDelete detected illegal PRIO field");
return;
}
- pesl = pevent_list[prio][evnt];
- if (pesl) psl = &pesl->scan_list;
- if (!pesl || !psl)
- recGblRecordError(-1, (void *)precord,
- "scanDelete for bad evnt");
- else
+ do /* multithreading: make sure pel is consistent */
+ pel = pevent_list[0];
+ while (pel != pevent_list[0]);
+ for (; pel; pel=pel->next) {
+ if (strcmp(pel->event_name, eventname) == 0) break;
+ }
+ if (pel && (psl = &pel->scan_list[prio]))
deleteFromList(precord, psl);
} else if (scan == menuScanI_O_Intr) {
io_scan_list *piosl=NULL;
@@ -372,21 +356,22 @@ int scanppl(double period) /* print periodic list */
return 0;
}
-int scanpel(int event_number) /* print event list */
+int scanpel(char* eventname) /* print event list */
{
char message[80];
- int prio, evnt;
- event_scan_list *pesl;
-
- for (evnt = 0; evnt < MAX_EVENTS; evnt++) {
- if (event_number && evntevent_number) break;
- for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
- pesl = pevent_list[prio][evnt];
- if (!pesl) continue;
- if (ellCount(&pesl->scan_list.list) == 0) continue;
- sprintf(message, "Event %d Priority %s", evnt, priorityName[prio]);
- printList(&pesl->scan_list, message);
+ int prio;
+ event_list *pel;
+
+ do /* multithreading: make sure pel is consistent */
+ pel = pevent_list[0];
+ while (pel != pevent_list[0]);
+ for (; pel; pel = pel->next) {
+ if (!eventname || strcmp(pel->event_name, eventname) == 0) {
+ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
+ if (ellCount(&pel->scan_list[prio].list) == 0) continue;
+ sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]);
+ printList(&pel->scan_list[prio], message);
+ }
}
}
return 0;
@@ -412,39 +397,73 @@ int scanpiol(void) /* print io_event list */
static void eventCallback(CALLBACK *pcallback)
{
- event_scan_list *pesl;
+ scan_list *psl;
- callbackGetUser(pesl, pcallback);
- scanList(&pesl->scan_list);
+ callbackGetUser(psl, pcallback);
+ scanList(psl);
}
static void initEvent(void)
{
- int evnt, prio;
+}
- for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
- for (evnt = 0; evnt < MAX_EVENTS; evnt++) {
- pevent_list[prio][evnt] = NULL;
+event_list *eventNameToHandle(char *eventname)
+{
+ int prio;
+ event_list *pel;
+ static epicsMutexId lock = NULL;
+
+ if (!lock) lock = epicsMutexMustCreate();
+ if (!eventname || eventname[0] == 0) return NULL;
+ epicsMutexMustLock(lock);
+ for (pel = pevent_list[0]; pel; pel=pel->next) {
+ if (strcmp(pel->event_name, eventname) == 0) break;
+ }
+ if (pel == NULL) {
+ pel = dbCalloc(1, sizeof(event_list));
+ strcpy(pel->event_name, eventname);
+ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
+ callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]);
+ callbackSetPriority(prio, &pel->callback[prio]);
+ callbackSetCallback(eventCallback, &pel->callback[prio]);
+ pel->scan_list[prio].lock = epicsMutexMustCreate();
+ ellInit(&pel->scan_list[prio].list);
}
+ pel->next=pevent_list[0];
+ pevent_list[0]=pel;
+ { /* backward compatibility */
+ char* p;
+ long e = strtol(eventname, &p, 0);
+ if (*p == 0 && e > 0 && e <= 255)
+ pevent_list[e]=pel;
+ }
+ }
+ epicsMutexUnlock(lock);
+ return pel;
+}
+
+void postEvent(event_list *pel)
+{
+ int prio;
+
+ if (scanCtl != ctlRun) return;
+ if (!pel) return;
+ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
+ if (ellCount(&pel->scan_list[prio].list) >0)
+ callbackRequest(&pel->callback[prio]);
}
}
+/* backward compatibility */
void post_event(int event)
{
- int prio;
- event_scan_list *pesl;
-
- if (scanCtl != ctlRun) return;
- if (event < 0 || event >= MAX_EVENTS) {
- errMessage(-1, "illegal event passed to post_event");
- return;
- }
- for (prio=0; prioscan_list.list) >0)
- callbackRequest((void *)pesl);
- }
+ event_list* pel;
+
+ if (event <= 0 || event > 255) return;
+ do { /* multithreading: make sure pel is consistent */
+ pel = pevent_list[event];
+ } while (pel != pevent_list[event]);
+ postEvent(pel);
}
void scanIoInit(IOSCANPVT *ppioscanpvt)
diff --git a/src/db/dbScan.h b/src/db/dbScan.h
index e046235ca..c2d8818e1 100644
--- a/src/db/dbScan.h
+++ b/src/db/dbScan.h
@@ -19,6 +19,7 @@
#include "menuScan.h"
#include "shareLib.h"
+#include "compilerDependencies.h"
#ifdef __cplusplus
extern "C" {
@@ -36,6 +37,7 @@ extern "C" {
struct io_scan_list;
typedef struct io_scan_list *IOSCANPVT;
+typedef struct event_list *EVENTPVT;
struct dbCommon;
@@ -43,7 +45,9 @@ epicsShareFunc long scanInit(void);
epicsShareFunc void scanRun(void);
epicsShareFunc void scanPause(void);
-epicsShareFunc void post_event(int event);
+epicsShareFunc EVENTPVT eventNameToHandle(char* event);
+epicsShareFunc void postEvent(EVENTPVT epvt);
+epicsShareFunc void post_event(int event) EPICS_DEPRECATED;
epicsShareFunc void scanAdd(struct dbCommon *);
epicsShareFunc void scanDelete(struct dbCommon *);
epicsShareFunc double scanPeriod(int scan);
@@ -54,7 +58,7 @@ epicsShareFunc int scanOnceSetQueueSize(int size);
epicsShareFunc int scanppl(double rate);
/*print event lists*/
-epicsShareFunc int scanpel(int event_number);
+epicsShareFunc int scanpel(char *event_name);
/*print io_event list*/
epicsShareFunc int scanpiol(void);
diff --git a/src/dev/softDev/devEventSoft.c b/src/dev/softDev/devEventSoft.c
index e276e0b82..d7a61172a 100644
--- a/src/dev/softDev/devEventSoft.c
+++ b/src/dev/softDev/devEventSoft.c
@@ -51,7 +51,7 @@ static long init_record(eventRecord *prec)
/* INP must be CONSTANT, PV_LINK, DB_LINK or CA_LINK*/
switch (prec->inp.type) {
case CONSTANT:
- if (recGblInitConstantLink(&prec->inp, DBF_USHORT, &prec->val))
+ if (recGblInitConstantLink(&prec->inp, DBF_STRING, &prec->val))
prec->udf = FALSE;
break;
case PV_LINK:
@@ -69,13 +69,20 @@ static long init_record(eventRecord *prec)
static long read_event(eventRecord *prec)
{
long status;
+ char newEvent[MAX_STRING_SIZE];
- status = dbGetLink(&prec->inp, DBR_USHORT, &prec->val, 0, 0);
- if (!status) {
- prec->udf = FALSE;
- if (prec->tsel.type == CONSTANT &&
- prec->tse == epicsTimeEventDeviceTime)
- dbGetTimeStamp(&prec->inp, &prec->time);
+ if (prec->inp.type != CONSTANT)
+ {
+ status = dbGetLinkValue(&prec->inp, DBR_STRING, newEvent, 0, 0);
+ if (status) return status;
+ if (strcmp(newEvent, prec->val) != 0) {
+ strcpy(prec->val, newEvent);
+ prec->epvt = eventNameToHandle(prec->val);
+ }
}
- return status;
+ prec->udf = FALSE;
+ if (prec->tsel.type == CONSTANT &&
+ prec->tse == epicsTimeEventDeviceTime)
+ dbGetTimeStamp(&prec->inp, &prec->time);
+ return 0;
}
diff --git a/src/rec/calcoutRecord.c b/src/rec/calcoutRecord.c
index 062580c76..95b7c0d10 100644
--- a/src/rec/calcoutRecord.c
+++ b/src/rec/calcoutRecord.c
@@ -197,6 +197,8 @@ static long init_record(calcoutRecord *prec, int pass)
callbackSetUser(prec, &prpvt->checkLinkCb);
prpvt->cbScheduled = 0;
+ prec->epvt = eventNameToHandle(prec->oevt);
+
if (pcalcoutDSET->init_record) pcalcoutDSET->init_record(prec);
prec->pval = prec->val;
prec->mlst = prec->val;
@@ -357,6 +359,9 @@ static long special(DBADDR *paddr, int after)
}
db_post_events(prec, plinkValid, DBE_VALUE);
return 0;
+ case(calcoutRecordOEVT):
+ prec->epvt = eventNameToHandle(prec->oevt);
+ return 0;
default:
recGblDbaddrError(S_db_badChoice, paddr, "calc: special");
return(S_db_badChoice);
@@ -540,27 +545,21 @@ static void execOutput(calcoutRecord *prec)
if (prec->nsev < INVALID_ALARM ) {
/* Output the value */
status = writeValue(prec);
- /* post event if output event != 0 */
- if (prec->oevt > 0) {
- post_event((int)prec->oevt);
- }
+ /* post output event if set */
+ if (prec->epvt) postEvent(prec->epvt);
} else switch (prec->ivoa) {
case menuIvoaContinue_normally:
status = writeValue(prec);
- /* post event if output event != 0 */
- if (prec->oevt > 0) {
- post_event((int)prec->oevt);
- }
+ /* post output event if set */
+ if (prec->epvt) postEvent(prec->epvt);
break;
case menuIvoaDon_t_drive_outputs:
break;
case menuIvoaSet_output_to_IVOV:
prec->oval = prec->ivov;
status = writeValue(prec);
- /* post event if output event != 0 */
- if (prec->oevt > 0) {
- post_event((int)prec->oevt);
- }
+ /* post output event if set */
+ if (prec->epvt) postEvent(prec->epvt);
break;
default:
status = -1;
diff --git a/src/rec/calcoutRecord.dbd b/src/rec/calcoutRecord.dbd
index fc393a782..8b80094d1 100644
--- a/src/rec/calcoutRecord.dbd
+++ b/src/rec/calcoutRecord.dbd
@@ -255,10 +255,19 @@ recordtype(calcout) {
prompt("OCAL Valid")
interest(1)
}
- field(OEVT,DBF_USHORT) {
+ field(OEVT,DBF_STRING) {
prompt("Event To Issue")
promptgroup(GUI_CLOCK)
+ special(SPC_MOD)
asl(ASL0)
+ size(40)
+ }
+ %#include "dbScan.h"
+ field(EPVT, DBF_NOACCESS) {
+ prompt("Event private")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("EVENTPVT epvt")
}
field(IVOA,DBF_MENU) {
prompt("INVALID output action")
diff --git a/src/rec/eventRecord.c b/src/rec/eventRecord.c
index 01a71daa4..18b0fbcd9 100644
--- a/src/rec/eventRecord.c
+++ b/src/rec/eventRecord.c
@@ -32,6 +32,7 @@
#include "errMdef.h"
#include "recSup.h"
#include "recGbl.h"
+#include "special.h"
#include "menuYesNo.h"
#define GEN_SIZE_OFFSET
#include "eventRecord.h"
@@ -43,7 +44,7 @@
#define initialize NULL
static long init_record(eventRecord *, int);
static long process(eventRecord *);
-#define special NULL
+static long special(DBADDR *, int);
static long get_value(eventRecord *, struct valueDes *);
#define cvt_dbaddr NULL
#define get_array_info NULL
@@ -103,9 +104,11 @@ static long init_record(eventRecord *prec, int pass)
}
if (prec->siol.type == CONSTANT) {
- recGblInitConstantLink(&prec->siol,DBF_USHORT,&prec->sval);
+ recGblInitConstantLink(&prec->siol,DBF_STRING,&prec->sval);
}
+ prec->epvt = eventNameToHandle(prec->val);
+
if( (pdset=(struct eventdset *)(prec->dset)) && (pdset->init_record) )
status=(*pdset->init_record)(prec);
return(status);
@@ -123,7 +126,7 @@ static long process(eventRecord *prec)
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
- if(prec->val>0) post_event((int)prec->val);
+ postEvent(prec->epvt);
recGblGetTimeStamp(prec);
@@ -137,10 +140,21 @@ static long process(eventRecord *prec)
return(status);
}
+
+static long special(DBADDR *paddr, int after)
+{
+ eventRecord *prec = (eventRecord *)paddr->precord;
+
+ if (!after) return 0;
+ if (dbGetFieldIndex(paddr) == eventRecordVAL) {
+ prec->epvt = eventNameToHandle(prec->val);
+ }
+}
+
static long get_value(eventRecord *prec, struct valueDes *pvdes)
{
- pvdes->field_type = DBF_USHORT;
+ pvdes->field_type = DBF_STRING;
pvdes->no_elements=1;
pvdes->pvalue = (void *)(&prec->val);
return(0);
@@ -177,10 +191,13 @@ static long readValue(eventRecord *prec)
return(status);
}
if (prec->simm == menuYesNoYES){
- status=dbGetLink(&(prec->siol),DBR_USHORT,
+ status=dbGetLink(&(prec->siol),DBR_STRING,
&(prec->sval),0,0);
if (status==0) {
- prec->val=prec->sval;
+ if (strcmp(prec->sval, prec->val) != 0) {
+ strcpy(prec->val, prec->sval);
+ prec->epvt = eventNameToHandle(prec->val);
+ }
prec->udf=FALSE;
}
} else {
diff --git a/src/rec/eventRecord.dbd b/src/rec/eventRecord.dbd
index f63355900..f7bbb7ee7 100644
--- a/src/rec/eventRecord.dbd
+++ b/src/rec/eventRecord.dbd
@@ -9,10 +9,19 @@
#*************************************************************************
recordtype(event) {
include "dbCommon.dbd"
- field(VAL,DBF_USHORT) {
- prompt("Event Number To Post")
+ field(VAL,DBF_STRING) {
+ prompt("Event Name To Post")
promptgroup(GUI_INPUTS)
+ special(SPC_MOD)
asl(ASL0)
+ size(40)
+ }
+ %#include "dbScan.h"
+ field(EPVT, DBF_NOACCESS) {
+ prompt("Event private")
+ special(SPC_NOMOD)
+ interest(4)
+ extra("EVENTPVT epvt")
}
field(INP,DBF_INLINK) {
prompt("Input Specification")
@@ -24,8 +33,9 @@ recordtype(event) {
promptgroup(GUI_INPUTS)
interest(1)
}
- field(SVAL,DBF_USHORT) {
+ field(SVAL,DBF_STRING) {
prompt("Simulation Value")
+ size(40)
}
field(SIML,DBF_INLINK) {
prompt("Sim Mode Location")