コード例 #1
0
ファイル: dbLexRoutines.c プロジェクト: zlxmsu/TestEpics
static void dbBreakItem(char *value)
{
    double dummy;
    if (duplicate) return;
    if (epicsScanDouble(value, &dummy) != 1) {
	yyerrorAbort("Non-numeric value in breaktable");
    }
    allocTemp(epicsStrDup(value));
}
コード例 #2
0
ファイル: dbFastLinkConv.c プロジェクト: ukaea/epics
/* Convert String to Double */
static long cvt_st_d(
    char *from,
    epicsFloat64 *to,
    const dbAddr *paddr)
{
    double value;

    if (*from == 0) {
        *to = 0.0;
        return 0;
    }
    if (epicsScanDouble(from, &value) == 1) {
        *to = value;
        return 0;
    }
    return -1;
}
コード例 #3
0
ファイル: dbFastLinkConv.c プロジェクト: ukaea/epics
/* Convert String to Unsigned Long */
static long cvt_st_ul(
    char *from,
    epicsUInt32 *to,
    const dbAddr *paddr)
{
    double value;

    if (*from == 0) {
        *to = 0;
        return 0;
    }
    /*Convert via double so that numbers like 1.0e3 convert properly*/
    /*Problem was old database access said to get unsigned long as double*/
    if (epicsScanDouble(from, &value) == 1) {
        *to = (epicsUInt32)value;
        return 0;
    }
    return -1;
}
コード例 #4
0
ファイル: envSubr.c プロジェクト: epicsdeb/epics-base
/*+/subr**********************************************************************
* NAME	envGetDoubleConfigParam - get value of a double configuration parameter
*
* DESCRIPTION
*	Gets the value of a configuration parameter and copies it into the
*	caller's real (double) buffer.  If the configuration parameter isn't
*	found in the environment, then the default value for the parameter
*	is copied.  
*
*	If no parameter is found and there is no default, then -1 is 
*	returned and the caller's buffer is unmodified.
*
* RETURNS
*	0, or
*	-1 if an error is encountered
*
* EXAMPLE
* 1.	Get the value for the real environment parameter EPICS_THRESHOLD.
*
*	#include "envDefs.h"
*	double	threshold;
*	long	status;
*
*	status = envGetDoubleConfigParam(&EPICS_THRESHOLD, &threshold);
*	if (status == 0) {
*	    printf("the threshold is: %lf\n", threshold);
*	}
*	else {
*	    printf("%s could not be found or was not a real number\n",
*			EPICS_THRESHOLD.name);
*	}
*
*-*/
long epicsShareAPI envGetDoubleConfigParam(
const ENV_PARAM *pParam,/* I pointer to config param structure */
double	*pDouble	/* O pointer to place to store value */
)
{
    char	text[128];
    char	*ptext;
    int		count;

    ptext = envGetConfigParam(pParam, sizeof text, text);
    if (ptext != NULL) {
	count = epicsScanDouble(text, pDouble);
	if (count == 1) {
	    return 0;
	}
        (void)fprintf(stderr,"Unable to find a real number in %s=%s\n", 
		pParam->name, text);
    }

    return -1;
}
コード例 #5
0
ファイル: camonitor.c プロジェクト: emayssat/epics-opis
int main (int argc, char *argv[])
{
    int returncode = 0;
    int n = 0;
    int result;                 /* CA result */

    int opt;                    /* getopt() current option */
    int digits = 0;             /* getopt() no. of float digits */

    int nPvs;                   /* Number of PVs */
    pv* pvs = 0;                /* Array of PV structures */

    setvbuf(stdout,NULL,_IOLBF,BUFSIZ);   /* Set stdout to line buffering */

    while ((opt = getopt(argc, argv, ":nhm:se:f:g:#:d:0:w:t:")) != -1) {
        switch (opt) {
        case 'h':               /* Print usage */
            usage();
            return 0;
        case 'n':               /* Print ENUM as index numbers */
            enumAsNr=1;
            break;
        case 't':               /* Select timestamp source(s) and type */
            tsSrcServer = 0;
            tsSrcClient = 0;
            {
                int i = 0;
                char c;
                while ((c = optarg[i++]))
                    switch (c) {
                    case 's': tsSrcServer = 1; break;
                    case 'c': tsSrcClient = 1; break;
                    case 'n': break;
                    case 'r': tsType = relative; break;
                    case 'i': tsType = incremental; break;
                    case 'I': tsType = incrementalByChan; break;
                    default :
                        fprintf(stderr, "Invalid argument '%c' "
                                "for option '-t' - ignored.\n", c);
                    }
            }
            break;
        case 'w':               /* Set CA timeout value */
            if(epicsScanDouble(optarg, &caTimeout) != 1)
            {
                fprintf(stderr, "'%s' is not a valid timeout value "
                        "- ignored. ('caget -h' for help.)\n", optarg);
                caTimeout = DEFAULT_TIMEOUT;
            }
            break;
        case '#':               /* Array count */
            if (sscanf(optarg,"%ld", &reqElems) != 1)
            {
                fprintf(stderr, "'%s' is not a valid array element count "
                        "- ignored. ('caget -h' for help.)\n", optarg);
                reqElems = 0;
            }
            break;
        case 'm':               /* Select CA event mask */
            eventMask = 0;
            {
                int i = 0;
                char c, err = 0;
                while ((c = optarg[i++]) && !err)
                    switch (c) {
                    case 'v': eventMask |= DBE_VALUE; break;
                    case 'a': eventMask |= DBE_ALARM; break;
                    case 'l': eventMask |= DBE_LOG; break;
                    default :
                        fprintf(stderr, "Invalid argument '%s' "
                                "for option '-m' - ignored.\n", optarg);
                        eventMask = DBE_VALUE | DBE_ALARM;
                        err = 1;
                    }
            }
            break;
        case 's':               /* Select string dbr for floating type data */
            floatAsString = 1;
            break;
        case 'e':               /* Select %e/%f/%g format, using <arg> digits */
        case 'f':
        case 'g':
            if (sscanf(optarg, "%d", &digits) != 1)
                fprintf(stderr, 
                        "Invalid precision argument '%s' "
                        "for option '-%c' - ignored.\n", optarg, opt);
            else
            {
                if (digits>=0 && digits<=VALID_DOUBLE_DIGITS)
                    sprintf(dblFormatStr, "%%-.%d%c", digits, opt);
                else
                    fprintf(stderr, "Precision %d for option '-%c' "
                            "out of range - ignored.\n", digits, opt);
            }
            break;
        case '0':               /* Select integer format */
            switch ((char) *optarg) {
            case 'x': outType = hex; break;    /* 0x print Hex */
            case 'b': outType = bin; break;    /* 0b print Binary */
            case 'o': outType = oct; break;    /* 0o print Octal */
            default :
                fprintf(stderr, "Invalid argument '%s' "
                        "for option '-0' - ignored.\n", optarg);
            }
            break;
        case '?':
            fprintf(stderr,
                    "Unrecognized option: '-%c'. ('caget -h' for help.)\n",
                    optopt);
            return 1;
        case ':':
            fprintf(stderr,
                    "Option '-%c' requires an argument. ('caget -h' for help.)\n",
                    optopt);
            return 1;
        default :
            usage();
            return 1;
        }
    }

    nPvs = argc - optind;       /* Remaining arg list are PV names */

    if (nPvs < 1)
    {
        fprintf(stderr, "No pv name specified. ('camonitor -h' for help.)\n");
        return 1;
    }
                                /* Start up Channel Access */

    result = ca_context_create(ca_disable_preemptive_callback);
    if (result != ECA_NORMAL) {
        fprintf(stderr, "CA error %s occurred while trying "
                "to start channel access '%s'.\n", ca_message(result), pvs[n].name);
        return 1;
    }
                                /* Allocate PV structure array */

    pvs = calloc (nPvs, sizeof(pv));
    if (!pvs)
    {
        fprintf(stderr, "Memory allocation for channel structures failed.\n");
        return 1;
    }
                                /* Connect channels */

                                      /* Copy PV names from command line */
    for (n = 0; optind < argc; n++, optind++)
    {
        pvs[n].name   = argv[optind];
    }
                                      /* Create CA connections */
    returncode = create_pvs(pvs, nPvs, connection_handler);
    if ( returncode ) {
        return returncode;
    }
                                      /* Check for channels that didn't connect */
    ca_pend_event(caTimeout);
    for (n = 0; n < nPvs; n++)
    {
        if (!pvs[n].onceConnected)
            print_time_val_sts(&pvs[n], pvs[n].reqElems);
    }

                                /* Read and print data forever */
    ca_pend_event(0);

                                /* Shut down Channel Access */
    ca_context_destroy();

    return result;
}
コード例 #6
0
ファイル: ca_test.c プロジェクト: ukaea/epics
/*
 *	capft
 *
 *	test ca_put() over a range of data types
 *	
 */
static int capft(
char		*pname,
char		*pvalue
)
{
	dbr_short_t			shortvalue;
	dbr_long_t			longvalue;
	dbr_float_t			floatvalue;
	dbr_char_t			charvalue;
	dbr_double_t		doublevalue;
	unsigned long		ntries = 10ul;
	int					status;
	chid				chan_id;

	if (((*pname < ' ') || (*pname > 'z'))
	  || ((*pvalue < ' ') || (*pvalue > 'z'))){
		printf("\nusage \"pv name\",\"value\"\n");
		return -1;
	}

	/* 
	 *	convert name to chan id 
	 */
	status = ca_search(pname, &chan_id);
	SEVCHK(status,NULL);
	status = ca_pend_io(5.0);
	if(status != ECA_NORMAL){
        SEVCHK(ca_clear_channel(chan_id),NULL);
		printf("Not Found %s\n", pname);
		return -1;
	}

	printf("name:\t%s\n", ca_name(chan_id));
	printf("native type:\t%d\n", ca_field_type(chan_id));
	printf("native count:\t%lu\n", ca_element_count(chan_id));

	/*
	 *  string value ca_put
	 */
	status = ca_put(
			DBR_STRING, 
			chan_id, 
			pvalue);
	SEVCHK(status, NULL);
	verify_value(chan_id, DBR_STRING);

	if(ca_field_type(chan_id)==0)goto skip_rest;

	if(sscanf(pvalue,"%hd",&shortvalue)==1) {
		/*
		 * short integer ca_put
		 */
		status = ca_put(
				DBR_SHORT, 
				chan_id, 
				&shortvalue);
		SEVCHK(status, NULL);
		verify_value(chan_id, DBR_SHORT);
		status = ca_put(
				DBR_ENUM, 
				chan_id, 
				&shortvalue);
		SEVCHK(status, NULL);
		verify_value(chan_id, DBR_ENUM);
		charvalue=(dbr_char_t)shortvalue;
		status = ca_put(
				DBR_CHAR, 
				chan_id, 
				&charvalue);
		SEVCHK(status, NULL);
		verify_value(chan_id, DBR_CHAR);
	}
	if(sscanf(pvalue,"%d",&longvalue)==1) {
		/*
		 * long integer ca_put
		 */
		status = ca_put(
				DBR_LONG, 
				chan_id, 
				&longvalue);
		SEVCHK(status, NULL);
		verify_value(chan_id, DBR_LONG);
	}
	if(epicsScanFloat(pvalue, &floatvalue)==1) {
		/*
		 * single precision float ca_put
		 */
		status = ca_put(
				DBR_FLOAT, 
				chan_id, 
				&floatvalue);
		SEVCHK(status, NULL);
		verify_value(chan_id, DBR_FLOAT);
	}
	if(epicsScanDouble(pvalue, &doublevalue)==1) {
		/*
		 * double precision float ca_put
		 */
		status = ca_put(
				DBR_DOUBLE, 
				chan_id, 
				&doublevalue);
		SEVCHK(status, NULL);
		verify_value(chan_id, DBR_DOUBLE);
	}

skip_rest:

	/*
	 * wait for the operation to complete
	 * (outstabnding decrements to zero)
	 */
	while(ntries){
		ca_pend_event(1.0);

		if(!outstanding){
            SEVCHK(ca_clear_channel(chan_id),NULL);
			printf("\n\n");
			return 0;
		}

		ntries--;
	}

    SEVCHK(ca_clear_channel(chan_id),NULL);
	return -1;
}
コード例 #7
0
long epicsShareAPI dbtpf(const char *pname, const char *pvalue)
{
    /* declare buffer long just to ensure correct alignment */
    long buffer[100];
    long *pbuffer = buffer;
    DBADDR addr;
    long status = 0;
    long options, no_elements;
    char *pend;
    long val_long;
    int validLong;
    unsigned long val_ulong;
    int validULong;
    int valid = 1;
    int put_type;
    epicsFloat32 fvalue;
    epicsFloat64 dvalue;
    static TAB_BUFFER msg_Buff;
    TAB_BUFFER *pMsgBuff = &msg_Buff;
    char *pmsg = pMsgBuff->message;
    int tab_size = 10;

    if (!pname || !*pname || !pvalue) {
        printf("Usage: dbtpf \"pv name\", \"value\"\n");
        return 1;
    }

    if (nameToAddr(pname, &addr))
        return -1;

    val_long = strtol(pvalue, &pend, 10);
    validLong = (*pend == 0);

    val_ulong = strtoul(pvalue, &pend, 10);
    validULong = (*pend == 0);

    for (put_type = DBR_STRING; put_type <= DBF_ENUM; put_type++) {
        switch (put_type) {
        case DBR_STRING:
            status = dbPutField(&addr, put_type, pvalue, 1L);
            break;
        case DBR_CHAR:
            if ((valid = validLong)) {
                epicsInt8 val_i8 = (epicsInt8)val_long;
                status = dbPutField(&addr, put_type, &val_i8, 1L);
            }
            break;
        case DBR_UCHAR:
            if ((valid = validULong)) {
                epicsUInt8 val_u8 = (epicsUInt8)val_ulong;
                status = dbPutField(&addr, put_type, &val_u8, 1L);
            }
            break;
        case DBR_SHORT:
            if ((valid = validLong)) {
                epicsInt16 val_i16 = val_long;
                status = dbPutField(&addr, put_type, &val_i16,1L);
            }
            break;
        case DBR_USHORT:
            if ((valid = validULong)) {
                epicsUInt16 val_u16 = val_ulong;
                status = dbPutField(&addr, put_type, &val_u16, 1L);
            }
            break;
        case DBR_LONG:
            if ((valid = validLong)) {
                epicsInt32 val_i32 = val_long;
                status = dbPutField(&addr, put_type,&val_i32,1L);
            }
            break;
        case DBR_ULONG:
            if ((valid = validULong)) {
                epicsUInt32 val_u32 = val_ulong;
                status = dbPutField(&addr, put_type, &val_u32, 1L);
            }
            break;
        case DBR_FLOAT:
            if ((valid = epicsScanFloat(pvalue, &fvalue) == 1))
                status = dbPutField(&addr, put_type, &fvalue, 1L);
            break;
        case DBR_DOUBLE:
            if ((valid = epicsScanDouble(pvalue, &dvalue) == 1))
                status = dbPutField(&addr, put_type, &dvalue, 1L);
            break;
        case DBR_ENUM:
            if ((valid = validULong)) {
                epicsEnum16 val_e16 = val_ulong;
                status = dbPutField(&addr, put_type, &val_e16, 1L);
            }
            break;
        }
        if (valid) {
            if (status) {
                printf("Put as DBR_%s Failed.\n", dbr[put_type]);
            } else {
                printf("Put as DBR_%-6s Ok, result as ", dbr[put_type]);
                no_elements = MIN(addr.no_elements,
                    ((sizeof(buffer))/addr.field_size));
                options = 0;
                status = dbGetField(&addr, addr.dbr_field_type, pbuffer,
                    &options, &no_elements, NULL);
                printBuffer(status, addr.dbr_field_type, pbuffer, 0L, 0L,
                    no_elements, pMsgBuff, tab_size);
            }
        }
    }

    pmsg[0] = '\0';
    dbpr_msgOut(pMsgBuff, tab_size);
    return(0);
}
コード例 #8
0
ファイル: dbLexRoutines.c プロジェクト: zlxmsu/TestEpics
static void dbBreakBody(void)
{
    brkTable		*pnewbrkTable;
    brkInt		*paBrkInt;
    brkTable		*pbrkTable;
    int			number, down=0;
    int			i;
    GPHENTRY		*pgphentry;

    if (duplicate) {
	duplicate = FALSE;
	return;
    }
    pnewbrkTable = (brkTable *)popFirstTemp();
    number = ellCount(&tempList);
    if (number % 2) {
	yyerrorAbort("breaktable: Raw value missing");
	return;
    }
    number /= 2;
    if (number < 2) {
	yyerrorAbort("breaktable: Must have at least two points!");
	return;
    }
    pnewbrkTable->number = number;
    pnewbrkTable->paBrkInt = paBrkInt = dbCalloc(number, sizeof(brkInt));
    for (i=0; i<number; i++) {
	char	*str;
	
	str = (char *)popFirstTemp();
	epicsScanDouble(str, &paBrkInt[i].raw);
	free(str);
	
	str = (char *)popFirstTemp();
	epicsScanDouble(str, &paBrkInt[i].eng);
	free(str);
    }
    /* Compute slopes */
    for (i=0; i<number-1; i++) {
	double slope =
	  (paBrkInt[i+1].eng - paBrkInt[i].eng)/
	  (paBrkInt[i+1].raw - paBrkInt[i].raw);
	if (!dbBptNotMonotonic && slope == 0) {
	    yyerrorAbort("breaktable slope is zero");
	    return;
	}
	if (i == 0) {
	    down = (slope < 0);
	} else if (!dbBptNotMonotonic && down != (slope < 0)) {
	    yyerrorAbort("breaktable slope changes sign");
	    return;
	}
	paBrkInt[i].slope = slope;
    }
    /* Continue with last slope beyond the final point */
    paBrkInt[number-1].slope = paBrkInt[number-2].slope;
    /* Add brkTable in sorted order */
    pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
    while (pbrkTable) {
	if (strcmp(pbrkTable->name, pnewbrkTable->name) > 0) {
	    ellInsert(&pdbbase->bptList, ellPrevious((ELLNODE *)pbrkTable),
		(ELLNODE *)pnewbrkTable);
	    break;
	}
	pbrkTable = (brkTable *)ellNext(&pbrkTable->node);
    }
    if (!pbrkTable) ellAdd(&pdbbase->bptList, &pnewbrkTable->node);
    pgphentry = gphAdd(pdbbase->pgpHash,pnewbrkTable->name,&pdbbase->bptList);
    if (!pgphentry) {
	yyerrorAbort("dbBreakBody: gphAdd failed");
	return;
    }
    pgphentry->userPvt = pnewbrkTable;
}
コード例 #9
0
ファイル: caput.c プロジェクト: ISISComputingGroup/EPICS-base
int main (int argc, char *argv[])
{
    int i;
    int result;                 /* CA result */
    OutputT format = plain;     /* User specified format */
    RequestT request = get;     /* User specified request type */
    int isArray = 0;            /* Flag for array operation */
    int enumAsString = 0;       /* Force ENUM values to be strings */

    int count = 1;
    int opt;                    /* getopt() current option */
    chtype dbrType = DBR_STRING;
    char *pend;
    EpicsStr *sbuf;
    double *dbuf;
    char *cbuf = 0;
    char *ebuf = 0;
    void *pbuf;
    int len = 0;
    int waitStatus;
    struct dbr_gr_enum bufGrEnum;

    int nPvs;                   /* Number of PVs */
    pv* pvs;                /* Array of PV structures */

    LINE_BUFFER(stdout);        /* Configure stdout buffering */
    putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */

    while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:F:")) != -1) {
        switch (opt) {
        case 'h':               /* Print usage */
            usage();
            return 0;
        case 'n':               /* Force interpret ENUM as index number */
            enumAsNr = 1;
            enumAsString = 0;
            break;
        case 's':               /* Force interpret ENUM as menu string */
            enumAsString = 1;
            enumAsNr = 0;
            break;
        case 'S':               /* Treat char array as (long) string */
            charArrAsStr = 1;
            isArray = 0;
            break;
        case 't':               /* Select terse output format */
            format = terse;
            break;
        case 'l':               /* Select long output format */
            format = all;
            break;
        case 'a':               /* Select array mode */
            isArray = 1;
            charArrAsStr = 0;
            break;
        case 'c':               /* Select put_callback mode */
            request = callback;
            break;
        case 'w':               /* Set CA timeout value */
            if(epicsScanDouble(optarg, &caTimeout) != 1)
            {
                fprintf(stderr, "'%s' is not a valid timeout value "
                        "- ignored. ('caput -h' for help.)\n", optarg);
                caTimeout = DEFAULT_TIMEOUT;
            }
            break;
        case '#':               /* Array count */
            if (sscanf(optarg,"%d", &count) != 1)
            {
                fprintf(stderr, "'%s' is not a valid array element count "
                        "- ignored. ('caput -h' for help.)\n", optarg);
                count = 0;
            }
            break;
        case 'p':               /* CA priority */
            if (sscanf(optarg,"%u", &caPriority) != 1)
            {
                fprintf(stderr, "'%s' is not a valid CA priority "
                        "- ignored. ('caget -h' for help.)\n", optarg);
                caPriority = DEFAULT_CA_PRIORITY;
            }
            if (caPriority > CA_PRIORITY_MAX) caPriority = CA_PRIORITY_MAX;
            break;
        case 'F':               /* Store this for output and tool_lib formatting */
            fieldSeparator = (char) *optarg;
            break;
        case '?':
            fprintf(stderr,
                    "Unrecognized option: '-%c'. ('caput -h' for help.)\n",
                    optopt);
            return 1;
        case ':':
            fprintf(stderr,
                    "Option '-%c' requires an argument. ('caput -h' for help.)\n",
                    optopt);
            return 1;
        default :
            usage();
            return 1;
        }
    }

    nPvs = argc - optind;       /* Remaining arg list are PV names and values */

    if (nPvs < 1) {
        fprintf(stderr, "No pv name specified. ('caput -h' for help.)\n");
        return 1;
    }
    if (nPvs == 1) {
        fprintf(stderr, "No value specified. ('caput -h' for help.)\n");
        return 1;
    }

    nPvs = 1;                   /* One PV - the rest is value(s) */

    epId = epicsEventCreate(epicsEventEmpty);  /* Create empty EPICS event (semaphore) */

                                /* Start up Channel Access */

    result = ca_context_create(ca_enable_preemptive_callback);
    if (result != ECA_NORMAL) {
        fprintf(stderr, "CA error %s occurred while trying "
                "to start channel access.\n", ca_message(result));
        return 1;
    }
                                /* Allocate PV structure array */

    pvs = calloc (nPvs, sizeof(pv));
    if (!pvs) {
        fprintf(stderr, "Memory allocation for channel structure failed.\n");
        return 1;
    }
                                /* Connect channels */

    pvs[0].name = argv[optind] ;   /* Copy PV name from command line */

    result = connect_pvs(pvs, nPvs); /* If the connection fails, we're done */
    if (result) {
        ca_context_destroy();
        return result;
    }

                                /* Get values from command line */
    optind++;

    if (isArray) {
        optind++;               /* In case of array skip first value (nr
                                 * of elements) - actual number of values is used */
        count = argc - optind;

    } else {                    /* Concatenate the remaining line to one string
                                 * (sucks but is compatible to the former version) */
        for (i = optind; i < argc; i++) {
            len += strlen(argv[i]);
            len++;
        }
        cbuf = calloc(len, sizeof(char));
        if (!cbuf) {
            fprintf(stderr, "Memory allocation failed.\n");
            return 1;
        }
        strcpy(cbuf, argv[optind]);

        if (argc > optind+1) {
            for (i = optind + 1; i < argc; i++) {
                strcat(cbuf, " ");
                strcat(cbuf, argv[i]); 
            }
        }

        if ((argc - optind) >= 1)
            count = 1;
        argv[optind] = cbuf;
    }

    sbuf = calloc (count, sizeof(EpicsStr));
    dbuf = calloc (count, sizeof(double));
    if(!sbuf || !dbuf) {
        fprintf(stderr, "Memory allocation failed\n");
        return 1;
    }

                                /*  ENUM? Special treatment */

    if (ca_field_type(pvs[0].chid) == DBR_ENUM) {

                                /* Get the ENUM strings */

        result = ca_array_get (DBR_GR_ENUM, 1, pvs[0].chid, &bufGrEnum);
        result = ca_pend_io(caTimeout);
        if (result == ECA_TIMEOUT) {
            fprintf(stderr, "Read operation timed out: ENUM data was not read.\n");
            return 1;
        }

        if (enumAsNr) {         /* Interpret values as numbers */

            for (i = 0; i < count; ++i) {
                dbuf[i] = epicsStrtod(*(argv+optind+i), &pend);
                if (*(argv+optind+i) == pend) { /* Conversion didn't work */
                    fprintf(stderr, "Enum index value '%s' is not a number.\n",
                            *(argv+optind+i));
                    return 1;
                }
                if (dbuf[i] >= bufGrEnum.no_str) {
                    fprintf(stderr, "Warning: enum index value '%s' may be too large.\n",
                            *(argv+optind+i));
                }
            }
            dbrType = DBR_DOUBLE;

        } else {                /* Interpret values as strings */

            for (i = 0; i < count; ++i) {
                epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr));
                *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0';
                dbrType = DBR_STRING;

                                /* Compare to ENUM strings */
                for (len = 0; len < bufGrEnum.no_str; len++)
                    if (!strcmp(sbuf[i], bufGrEnum.strs[len]))
                        break;

                if (len >= bufGrEnum.no_str) {
                                         /* Not a string? Try as number */
                    dbuf[i] = epicsStrtod(sbuf[i], &pend);
                    if (sbuf[i] == pend || enumAsString) {
                        fprintf(stderr, "Enum string value '%s' invalid.\n", sbuf[i]);
                        return 1;
                    }
                    if (dbuf[i] >= bufGrEnum.no_str) {
                        fprintf(stderr, "Warning: enum index value '%s' may be too large.\n", sbuf[i]);
                    }
                    dbrType = DBR_DOUBLE;
                }
            }
        }

    } else {                    /* Not an ENUM */

        if (charArrAsStr) {
            dbrType = DBR_CHAR;
            ebuf = calloc(len, sizeof(char));
            if(!ebuf) {
                fprintf(stderr, "Memory allocation failed\n");
                return 1;
            }
            count = epicsStrnRawFromEscaped(ebuf, len, cbuf, len-1) + 1;
        } else {
            for (i = 0; i < count; ++i) {
                epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr));
                *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0';
            }
            dbrType = DBR_STRING;
        }
    }

                                /* Read and print old data */
    if (format != terse) {
        printf("Old : ");
        result = caget(pvs, nPvs, format, 0, 0);
    }

                                /* Write new data */
    if (dbrType == DBR_STRING) pbuf = sbuf;
    else if (dbrType == DBR_CHAR) pbuf = ebuf;
    else pbuf = dbuf;

    if (request == callback) {
        /* Use callback version of put */
        pvs[0].status = ECA_NORMAL;   /* All ok at the moment */
        result = ca_array_put_callback (
            dbrType, count, pvs[0].chid, pbuf, put_event_handler, (void *) pvs);
    } else {
        /* Use standard put with defined timeout */
        result = ca_array_put (dbrType, count, pvs[0].chid, pbuf);
    }
    result = ca_pend_io(caTimeout);
    if (result == ECA_TIMEOUT) {
        fprintf(stderr, "Write operation timed out: Data was not written.\n");
        return 1;
    }
    if (request == callback) {   /* Also wait for callbacks */
        waitStatus = epicsEventWaitWithTimeout( epId, caTimeout );
        if (waitStatus)
            fprintf(stderr, "Write callback operation timed out\n");

        /* retrieve status from callback */
        result = pvs[0].status;
    }

    if (result != ECA_NORMAL) {
        fprintf(stderr, "Error occured writing data.\n");
        return 1;
    }

                                /* Read and print new data */
    if (format != terse)
        printf("New : ");

    result = caget(pvs, nPvs, format, 0, 0);

                                /* Shut down Channel Access */
    ca_context_destroy();

    return result;
}