diff --git a/asApp/src/dbrestore.c b/asApp/src/dbrestore.c index 10d81649..ea56e582 100644 --- a/asApp/src/dbrestore.c +++ b/asApp/src/dbrestore.c @@ -317,6 +317,100 @@ STATIC long scalar_restore(int pass, DBENTRY *pdbentry, char *PVname, char *valu return(status); } +/* enum_restore +** +** Parse *value_string to extract an integer value and its equivalent ENUM string. +** Expect the following syntax: +** @enum@""[] +*/ +static long enum_restore(int pass, DBENTRY *pdbentry, char *PVname, char *value_string) +{ + long status = 0; + int enumVal, nn; + char enumStr[64], *s; + dbfType field_type = pdbentry->pflddes->field_type; + + if (save_restoreDebug >= 5) { + errlogPrintf ("enum_restore:entry:field type '%s' '%s:\n", pamapdbfType[field_type].strvalue, value_string); + } + if (strncmp (value_string, ENUM_MARKER, ENUM_MARKER_LEN)) { + errlogPrintf("enum_restore:A: value_string parse failed: '%s'\n", value_string); + return (-1); + } + value_string += ENUM_MARKER_LEN; + if (sscanf (value_string, "%u %n", &enumVal, &nn) != 1) { + errlogPrintf("enum_restore:B: value_string parse failed: '%s'\n", value_string); + return (-1); + } + value_string += nn; + if (save_restoreDebug >= 5) { + errlogPrintf ("enum_restore:enum value = %u '%s'\n", enumVal, value_string); + } + if (value_string[0] != '"') { + errlogPrintf("enum_restore:C: value_string parse failed: '%s'\n", value_string); + return (-1); + } + strncpy (enumStr, &value_string[1], sizeof (enumStr)); + if (strlen (enumStr) >= sizeof (enumStr)) { + errlogPrintf("enum_restore:D: value_string parse failed: '%s'\n", value_string); + return (-1); + } + s = strchr (enumStr, '"'); + if (s == NULL) { + errlogPrintf("enum_restore:E: value_string parse failed: '%s'\n", value_string); + return (-1); + } + *s = '\0'; + if (save_restoreDebug >= 5) { + errlogPrintf("enum_restore:enum string = '%s'\n", enumStr); + } + switch (field_type) { + case DBF_ENUM: case DBF_MENU: case DCT_MENU: + if (strlen (enumStr) > 0) { + s = dbVerify(pdbentry, enumStr); + if (s == NULL) { + status = dbPutString(pdbentry, enumStr); + if (save_restoreDebug >= 5) { + errlogPrintf("enum_restore:A: dbPutString() returns %ld:", status); + } + } else { + sprintf (enumStr, "%u", enumVal); + status = dbPutString(pdbentry, enumStr); + if (save_restoreDebug >= 5) { + errlogPrintf("enum_restore:B: dbPutString() returns %ld:", status); + } + } + } else { + sprintf (enumStr, "%u", enumVal); + status = dbPutString(pdbentry, enumStr); + if (save_restoreDebug >= 5) { + errlogPrintf("enum_restore:C: dbPutString() returns %ld:", status); + } + } + if (save_restoreDebug >= 15) errMessage(status, " "); + if ((s = dbVerify(pdbentry, enumStr))) { + errlogPrintf("enum_restore: for '%s', dbVerify() says '%s'\n", PVname, s); + status = -1; + } + break; + + default: + status = -1; + if (save_restoreDebug >= 1) { + errlogPrintf ("enum_restore: field_type '%d' not handled\n", field_type); + } + break; + } + if (status) { + errlogPrintf("enum_restore: dbPutString of '%s' for '%s' failed\n", enumStr, PVname); + errMessage(status," "); + } + if (save_restoreDebug >= 5) { + errlogPrintf ("enum_restore: dbGetString() returns '%s'\n",dbGetString(pdbentry)); + } + return(status); +} + static void *p_data = NULL; static long p_data_size = 0; @@ -791,6 +885,8 @@ long SR_array_restore(int pass, FILE *inp_fd, char *PVname, char *value_string, * e.g., "1.2" * OR * @array@ { "" "" } + * OR + * @enum@ "" */ int reboot_restore(char *filename, initHookState init_state) { @@ -806,7 +902,7 @@ int reboot_restore(char *filename, initHookState init_state) DBENTRY dbentry; DBENTRY *pdbentry = &dbentry; long status; - int n, write_backup, num_errors, is_scalar; + int n, write_backup, num_errors, is_scalar, is_not_enum;; long *pStatusVal = 0; char *statusStr = 0; char realName[64]; /* name without trailing '$' */ @@ -945,6 +1041,7 @@ int reboot_restore(char *filename, initHookState init_state) if (isalpha((int)PVname[0]) || isdigit((int)PVname[0])) { if (strchr(PVname,'.') == 0) strcat(PVname,".VAL"); /* if no field name, add default */ is_scalar = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN); + is_not_enum = strncmp(value_string, ENUM_MARKER, ENUM_MARKER_LEN); if (save_restoreDebug > 9) errlogPrintf("\n"); if (is_scalar) { long num_elements, field_size, field_type; @@ -1002,7 +1099,11 @@ int reboot_restore(char *filename, initHookState init_state) } if (found_field) { if (is_scalar || is_long_string) { - status = scalar_restore(pass, pdbentry, PVname, value_string); + if (is_not_enum) { + status = scalar_restore(pass, pdbentry, PVname, value_string); + } else { + status = enum_restore(pass, pdbentry, PVname, value_string); + } } else { status = SR_array_restore(pass, inp_fd, PVname, value_string, 0); } diff --git a/asApp/src/save_restore.c b/asApp/src/save_restore.c index 4de4405b..bbb73ad6 100644 --- a/asApp/src/save_restore.c +++ b/asApp/src/save_restore.c @@ -1782,7 +1782,15 @@ STATIC int write_it(char *filename, struct chlist *plist) if (pchannel->curr_elements <= 1) { /* treat as scalar */ if (pchannel->enum_val >= 0) { - n = fprintf(out_fd, "%d\n",pchannel->enum_val); + /* + ** The channel would appear to be of type ENUM. Save the + ** equivalent string too, if it is non-blank. + */ + if (strlen (pchannel->value) > 0) { + n = fprintf(out_fd, "%s %d \"%s\"\n", ENUM_MARKER, pchannel->enum_val, pchannel->value); + } else { + n = fprintf(out_fd, "%d\n",pchannel->enum_val); + } } else { n = fprintf(out_fd, "%-s\n", pchannel->value); } diff --git a/asApp/src/save_restore.h b/asApp/src/save_restore.h index 8f25e82d..415f351e 100644 --- a/asApp/src/save_restore.h +++ b/asApp/src/save_restore.h @@ -54,6 +54,8 @@ static char SR_STATUS_STR[5][10] = #define ESCAPE '\\' #define ARRAY_MARKER "@array@" #define ARRAY_MARKER_LEN 7 +#define ENUM_MARKER "@enum@" +#define ENUM_MARKER_LEN 6 #define FN_LEN 80 /* filename length */ #define STRING_LEN MAX_STRING_SIZE /* EPICS max length for string PV */