Bugfixes plus added support for escaping non-printables and field separator to CA commandline tools.

This commit is contained in:
Ralph Lange
2009-04-02 02:14:33 +00:00
parent 73470d5f4c
commit e484093493
7 changed files with 232 additions and 119 deletions

View File

@@ -12,9 +12,35 @@
<h2 align="center">Changes between 3.14.10 and 3.14.11</h2>
<!-- Insert new items below here ... -->
<h4>Channel Access command line tool changes</h4>
<p>The caget/caput/camonitor programs in src/catools now use '\' escape
sequences for non-printable characters.</p>
<p>They provide a new option <tt>-F</tt> to set an output field separator
to be used instead of the default space character.</p>
<h4>New functions for escaping non-printables in epicsString.h</h4>
<p>The existing routines used to escape non-printable characters have been replaced
by a new set of functions that are prototyped in the epicsString.h header file:</p>
<pre>int epicsStrnRawFromEscaped(char *outbuf, size_t outsize, const char *inbuf, size_t inlen);
epicsShareFunc int epicsStrnEscapedFromRaw(char *outbuf, size_t outsize, const char *inbuf, size_t inlen);
epicsShareFunc size_t epicsStrnEscapedFromRawSize(const char *inbuf, size_t inlen);</pre>
<p>Both conversion functions take the output buffer (and its size), and the input
buffer (and its size) as argument. They will convert non-printable characters
from/to their '\'-escaped versions. The third function scans a raw input string
and returns the number of characters needed for the escaped version.</p>
<p>The existing function interfaces will be kept for compatibility, but their
further use is deprecated.</p>
<h4>epicsRingBytes</h4>
<p>Partial puts are not supported. An attempt to put more bytes than currently free will be rejected.</p>
<p>Partial puts are not supported.
An attempt to put more bytes than currently free will be rejected.</p>
<h4>Long string support</h4>

View File

@@ -1,16 +1,20 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Copyright (c) 2009 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie.
* Copyright (c) 2006 Diamond Light Source Ltd.
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
* Author: Ralph Lange (BESSY)
*
* Modification History
@@ -18,12 +22,17 @@
* Fixed problem with "-c -w 0" hanging forever
* 2008/04/16 Ralph Lange (BESSY)
* Updated usage info
* 2009/03/31 Larry Hoff (BNL)
* Added field separators
* 2009/04/01 Ralph Lange (HZB/BESSY)
* Added support for long strings (array of char) and quoting of nonprintable characters
*
*/
#include <stdio.h>
#include <epicsStdlib.h>
#include <string.h>
#include <epicsStdlib.h>
#include <epicsString.h>
#include <alarm.h>
#include <cadef.h>
@@ -45,7 +54,7 @@ static int nRead = 0; /* Number of channels that were read */
static int floatAsString = 0; /* Flag: fetch floats as string */
void usage (void)
static void usage (void)
{
fprintf (stderr, "\nUsage: caget [options] <PV name> ...\n\n"
" -h: Help: Print this message\n"
@@ -87,6 +96,8 @@ void usage (void)
" -0x: Print as hex number\n"
" -0o: Print as octal number\n"
" -0b: Print as binary number\n"
"Alternate output field separator:\n"
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
"\nExample: caget -a -f8 my_channel another_channel\n"
" (uses wide output format, doubles are printed as %%f with precision of 8)\n\n"
, DEFAULT_TIMEOUT, CA_PRIORITY_MAX);
@@ -105,7 +116,7 @@ void usage (void)
*
**************************************************************************-*/
void event_handler (evargs args)
static void event_handler (evargs args)
{
pv* ppv = args.usr;
@@ -140,7 +151,7 @@ void event_handler (evargs args)
*
**************************************************************************-*/
int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
chtype dbrType, unsigned long reqElems)
{
unsigned int i;
@@ -154,6 +165,7 @@ int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
/* Get natural type and array count */
pvs[n].nElems = ca_element_count(pvs[n].chid);
pvs[n].dbfType = ca_field_type(pvs[n].chid);
pvs[n].dbrType = dbrType;
/* Set up value structures */
if (format != specifiedDbr)
@@ -240,8 +252,9 @@ int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
switch (format) {
case plain: /* Emulate old caget behaviour */
if (pvs[n].reqElems <= 1) printf("%-30s ", pvs[n].name);
else printf("%s", pvs[n].name);
if (pvs[n].reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name);
else printf("%s", pvs[n].name);
printf("%c", fieldSeparator);
case terse:
if (pvs[n].status == ECA_DISCONN)
printf("*** not connected\n");
@@ -254,11 +267,16 @@ int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
else
{
if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) {
printf(" %s", (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType));
dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);
int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));
char *d = calloc(dlen+1, sizeof(char));
epicsStrnEscapedFromRaw(d, dlen+1, (char*)s, strlen((char*)s));
printf("%s", d);
free(d);
} else {
if (reqElems || pvs[n].nElems > 1) printf(" %lu", pvs[n].reqElems);
if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].reqElems, fieldSeparator);
for (i=0; i<pvs[n].reqElems; ++i) {
if (i) printf (" ");
if (i) printf ("%c", fieldSeparator);
printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));
}
}
@@ -278,8 +296,9 @@ int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
printf(" *** CA error %s\n", ca_message(pvs[n].status));
else
{
printf(" Native data type: %s (CA uses %s)\n",
dbf_type_to_text(pvs[n].dbfType),
printf(" Native data type: %s\n",
dbf_type_to_text(pvs[n].dbfType));
printf(" Request type: %s\n",
dbr_type_to_text(pvs[n].dbrType));
if (pvs[n].dbrType == DBR_CLASS_NAME)
printf(" Class Name: %s\n",
@@ -290,10 +309,15 @@ int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
" Value: ",
pvs[n].reqElems);
if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) {
printf(" %s", (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType));
dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);
int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));
char *d = calloc(dlen+1, sizeof(char));
epicsStrnEscapedFromRaw(d, dlen+1, (char*)s, strlen((char*)s));
printf("%s", d);
free(d);
} else {
for (i=0; i<pvs[n].reqElems; ++i) {
if (i) printf (" ");
if (i) printf ("%c", fieldSeparator);
printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));
}
}
@@ -328,7 +352,7 @@ int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
*
**************************************************************************-*/
void complainIfNotPlainAndSet (OutputT *current, const OutputT requested)
static void complainIfNotPlainAndSet (OutputT *current, const OutputT requested)
{
if (*current != plain)
fprintf(stderr,
@@ -354,7 +378,7 @@ int main (int argc, char *argv[])
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
while ((opt = getopt(argc, argv, ":taicnhsSe:f:g:#:d:0:w:p:")) != -1) {
while ((opt = getopt(argc, argv, ":taicnhsSe:f:g:#:d:0:w:p:F:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
@@ -450,6 +474,9 @@ int main (int argc, char *argv[])
"for option '-0' - ignored.\n", optarg);
}
break;
case 'F': /* Store this for output and tool_lib formatting */
fieldSeparator = (char) *optarg;
break;
case '?':
fprintf(stderr,
"Unrecognized option: '-%c'. ('caget -h' for help.)\n",

View File

@@ -1,21 +1,24 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie.
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
* Author: Ralph Lange (BESSY)
*
* Modification History
* 2008/04/16 Ralph Lange (BESSY)
* Updated usage info
* 2009/04/01 Ralph Lange (HZB/BESSY)
* Clarified output for native data type
*
*/
@@ -87,7 +90,8 @@ int cainfo (pv *pvs, int nPvs)
" State: %s\n"
" Host: %s\n"
" Access: %sread, %swrite\n"
" Native data type: %s (CA uses %s)\n"
" Native data type: %s\n"
" Request type: %s\n"
" Element count: %lu\n"
, pvs[n].name,
stateStrings[state],
@@ -143,7 +147,7 @@ int main (int argc, char *argv[])
if(epicsScanDouble(optarg, &caTimeout) != 1)
{
fprintf(stderr, "'%s' is not a valid timeout value "
"- ignored. ('caget -h' for help.)\n", optarg);
"- ignored. ('cainfo -h' for help.)\n", optarg);
caTimeout = DEFAULT_TIMEOUT;
}
break;
@@ -151,7 +155,7 @@ int main (int argc, char *argv[])
if (sscanf(optarg,"%du", &statLevel) != 1)
{
fprintf(stderr, "'%s' is not a valid interest level "
"- ignored. ('caget -h' for help.)\n", optarg);
"- ignored. ('cainfo -h' for help.)\n", optarg);
statLevel = 0;
}
break;
@@ -159,19 +163,19 @@ int main (int argc, char *argv[])
if (sscanf(optarg,"%u", &caPriority) != 1)
{
fprintf(stderr, "'%s' is not a valid CA priority "
"- ignored. ('caget -h' for help.)\n", optarg);
"- ignored. ('cainfo -h' for help.)\n", optarg);
caPriority = DEFAULT_CA_PRIORITY;
}
if (caPriority > CA_PRIORITY_MAX) caPriority = CA_PRIORITY_MAX;
break;
case '?':
fprintf(stderr,
"Unrecognized option: '-%c'. ('caget -h' for help.)\n",
"Unrecognized option: '-%c'. ('cainfo -h' for help.)\n",
optopt);
return 1;
case ':':
fprintf(stderr,
"Option '-%c' requires an argument. ('caget -h' for help.)\n",
"Option '-%c' requires an argument. ('cainfo -h' for help.)\n",
optopt);
return 1;
default :
@@ -184,7 +188,7 @@ int main (int argc, char *argv[])
if (!statLevel && nPvs < 1)
{
fprintf(stderr, "No pv name specified. ('caget -h' for help.)\n");
fprintf(stderr, "No pv name specified. ('cainfo -h' for help.)\n");
return 1;
}
/* Start up Channel Access */

View File

@@ -1,21 +1,28 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Copyright (c) 2009 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie.
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
* Author: Ralph Lange (BESSY)
*
* Modification History
* 2008/04/16 Ralph Lange (BESSY)
* Updated usage info
* 2009/03/31 Larry Hoff (BNL)
* Added field separators
* 2009/04/01 Ralph Lange (HZB/BESSY)
* Added support for long strings (array of char) and quoting of nonprintable characters
*
*/
@@ -71,6 +78,8 @@ void usage (void)
" -0x: Print as hex number\n"
" -0o: Print as octal number\n"
" -0b: Print as binary number\n"
"Alternate output field separator:\n"
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
"\nExample: camonitor -f8 my_channel another_channel\n"
" (doubles are printed as %%f with precision of 8)\n\n"
, DEFAULT_TIMEOUT, CA_PRIORITY_MAX);
@@ -89,7 +98,7 @@ void usage (void)
*
**************************************************************************-*/
void event_handler (evargs args)
static void event_handler (evargs args)
{
pv* pv = args.usr;
@@ -115,7 +124,7 @@ void event_handler (evargs args)
*
**************************************************************************-*/
void connection_handler ( struct connection_handler_args args )
static void connection_handler ( struct connection_handler_args args )
{
pv *ppv = ( pv * ) ca_puser ( args.chid );
if ( args.op == CA_OP_CONN_UP ) {
@@ -206,7 +215,7 @@ int main (int argc, char *argv[])
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
while ((opt = getopt(argc, argv, ":nhm:sSe:f:g:#:d:0:w:t:p:")) != -1) {
while ((opt = getopt(argc, argv, ":nhm:sSe:f:g:#:d:0:w:t:p:F:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
@@ -238,7 +247,7 @@ int main (int argc, char *argv[])
if(epicsScanDouble(optarg, &caTimeout) != 1)
{
fprintf(stderr, "'%s' is not a valid timeout value "
"- ignored. ('caget -h' for help.)\n", optarg);
"- ignored. ('camonitor -h' for help.)\n", optarg);
caTimeout = DEFAULT_TIMEOUT;
}
break;
@@ -246,7 +255,7 @@ int main (int argc, char *argv[])
if (sscanf(optarg,"%ld", &reqElems) != 1)
{
fprintf(stderr, "'%s' is not a valid array element count "
"- ignored. ('caget -h' for help.)\n", optarg);
"- ignored. ('camonitor -h' for help.)\n", optarg);
reqElems = 0;
}
break;
@@ -254,7 +263,7 @@ int main (int argc, char *argv[])
if (sscanf(optarg,"%u", &caPriority) != 1)
{
fprintf(stderr, "'%s' is not a valid CA priority "
"- ignored. ('caget -h' for help.)\n", optarg);
"- ignored. ('camonitor -h' for help.)\n", optarg);
caPriority = DEFAULT_CA_PRIORITY;
}
if (caPriority > CA_PRIORITY_MAX) caPriority = CA_PRIORITY_MAX;
@@ -309,14 +318,17 @@ int main (int argc, char *argv[])
"for option '-0' - ignored.\n", optarg);
}
break;
case 'F': /* Store this for output and tool_lib formatting */
fieldSeparator = (char) *optarg;
break;
case '?':
fprintf(stderr,
"Unrecognized option: '-%c'. ('caget -h' for help.)\n",
"Unrecognized option: '-%c'. ('camonitor -h' for help.)\n",
optopt);
return 1;
case ':':
fprintf(stderr,
"Option '-%c' requires an argument. ('caget -h' for help.)\n",
"Option '-%c' requires an argument. ('camonitor -h' for help.)\n",
optopt);
return 1;
default :

View File

@@ -1,17 +1,20 @@
/*************************************************************************\
* Copyright (c) 2006 Diamond Light Source Ltd.
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* Copyright (c) 2009 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie.
* Copyright (c) 2006 Diamond Light Source Ltd.
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
* Author: Ralph Lange (BESSY)
*
* Modification History
@@ -22,6 +25,10 @@
* (semaphore), i.e. remove ca_pend_event time slicing.
* 2008/04/16 Ralph Lange (BESSY)
* Updated usage info
* 2009/03/31 Larry Hoff (BNL)
* Added field separators
* 2009/04/01 Ralph Lange (HZB/BESSY)
* Added support for long strings (array of char) and quoting of nonprintable characters
*
*/
@@ -32,6 +39,7 @@
#include <cadef.h>
#include <epicsGetopt.h>
#include <epicsEvent.h>
#include <epicsString.h>
#include "tool_lib.h"
@@ -128,6 +136,7 @@ int caget (pv *pvs, int nPvs, OutputT format,
/* Get natural type and array count */
pvs[n].nElems = ca_element_count(pvs[n].chid);
pvs[n].dbfType = ca_field_type(pvs[n].chid);
pvs[n].dbrType = dbrType;
/* Set up value structures */
pvs[n].dbrType = dbf_type_to_DBR_TIME(pvs[n].dbfType); /* Use native type */
@@ -176,8 +185,9 @@ int caget (pv *pvs, int nPvs, OutputT format,
switch (format) {
case plain: /* Emulate old caput behaviour */
if (pvs[n].reqElems <= 1) printf("%-30s ", pvs[n].name);
else printf("%s", pvs[n].name);
if (pvs[n].reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name);
else printf("%s", pvs[n].name);
printf("%c", fieldSeparator);
case terse:
if (pvs[n].status == ECA_DISCONN)
printf("*** not connected\n");
@@ -190,11 +200,16 @@ int caget (pv *pvs, int nPvs, OutputT format,
else
{
if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) {
printf(" %s", (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType));
dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);
int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));
char *d = calloc(dlen+1, sizeof(char));
epicsStrnEscapedFromRaw(d, dlen+1, (char*)s, strlen((char*)s));
printf("%s", d);
free(d);
} else {
if (reqElems || pvs[n].nElems > 1) printf(" %lu", pvs[n].reqElems);
if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].reqElems, fieldSeparator);
for (i=0; i<pvs[n].reqElems; ++i) {
if (i) printf (" ");
if (i) printf ("%c", fieldSeparator);
printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));
}
}
@@ -246,6 +261,7 @@ int main (int argc, char *argv[])
EpicsStr *sbuf;
double *dbuf;
char *cbuf = 0;
char *ebuf = 0;
void *pbuf;
int len = 0;
int waitStatus;
@@ -257,7 +273,7 @@ int main (int argc, char *argv[])
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */
while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:")) != -1) {
while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:F:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
@@ -312,6 +328,9 @@ int main (int argc, char *argv[])
}
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",
@@ -429,32 +448,27 @@ int main (int argc, char *argv[])
} else { /* Interpret values as strings */
for (i = 0; i < count; ++i) {
len = strlen(*(argv+optind+i));
if (len >= sizeof(EpicsStr)) /* Too long? Cut at max length */
*( *(argv+optind+i)+sizeof(EpicsStr)-1 ) = 0;
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(*(argv+optind+i), bufGrEnum.strs[len]))
if (!strcmp(sbuf[i], bufGrEnum.strs[len]))
break;
if (len >= bufGrEnum.no_str) {
/* Not a string? Try as number */
dbuf[i] = epicsStrtod(*(argv+optind+i), &pend);
if (*(argv+optind+i) == pend || enumAsString) {
fprintf(stderr, "Enum string value '%s' invalid.\n",
*(argv+optind+i));
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, "Enum index value '%s' too large.\n",
*(argv+optind+i));
fprintf(stderr, "Enum index value '%s' too large.\n", sbuf[i]);
return 1;
}
dbrType = DBR_DOUBLE;
} else {
strcpy (sbuf[i], *(argv+optind+i));
dbrType = DBR_STRING;
}
}
}
@@ -464,12 +478,12 @@ int main (int argc, char *argv[])
if (charArrAsStr) {
count = len;
dbrType = DBR_CHAR;
ebuf = calloc(strlen(cbuf), sizeof(char));
epicsStrnRawFromEscaped(ebuf, strlen(cbuf), cbuf, strlen(cbuf));
} else {
for (i = 0; i < count; ++i) {
len=strlen(*(argv+optind+i));
if (len >= sizeof(EpicsStr)) /* Too long? Cut at max length */
*( *(argv+optind+i)+sizeof(EpicsStr)-1 ) = 0;
strcpy (sbuf[i], *(argv+optind+i));
epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr));
*( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0';
}
dbrType = DBR_STRING;
}
@@ -483,7 +497,7 @@ int main (int argc, char *argv[])
/* Write new data */
if (dbrType == DBR_STRING) pbuf = sbuf;
else if (dbrType == DBR_CHAR) pbuf = cbuf;
else if (dbrType == DBR_CHAR) pbuf = ebuf;
else pbuf = dbuf;
if (request == callback) {

View File

@@ -1,4 +1,7 @@
/*************************************************************************\
* Copyright (c) 2009 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie.
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
@@ -9,11 +12,18 @@
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
* $Id$
*
* Author: Ralph Lange (BESSY)
*
* Modification History
* 2009/03/31 Larry Hoff (BNL)
* Added field separators
* 2009/04/01 Ralph Lange (HZB/BESSY)
* Added support for long strings (array of char) and quoting of nonprintable characters
*
*/
#include <stdio.h>
@@ -24,6 +34,7 @@
#include <alarm.h>
#undef epicsAlarmGLOBAL
#include <epicsTime.h>
#include <epicsString.h>
#include <cadef.h>
#include "tool_lib.h"
@@ -43,6 +54,7 @@ IntFormatT outType = dec; /* For -0.. output format option */
char dblFormatStr[30] = "%g"; /* Format string to print doubles (-efg options) */
char timeFormatStr[30] = "%Y-%m-%d %H:%M:%S.%06f"; /* Time format string */
char fieldSeparator = ' '; /* OFS default is whitespace */
int enumAsNr = 0; /* used for -n option - get DBF_ENUM as number */
int charArrAsStr = 0; /* used for -S option - treat char array as (long) string */
@@ -96,7 +108,8 @@ void sprint_long (char *ret, long val)
char *val2str (const void *v, unsigned type, int index)
{
static char str[500];
#define STR 500
static char str[STR];
char ch;
void *val_ptr;
unsigned base_type;
@@ -115,7 +128,7 @@ char *val2str (const void *v, unsigned type, int index)
switch (base_type) {
case DBR_STRING:
sprintf(str, "%s", ((dbr_string_t*) val_ptr)[index]);
epicsStrnEscapedFromRaw(str, STR, ((dbr_string_t*) val_ptr)[index], strlen(((dbr_string_t*) val_ptr)[index]));
break;
case DBR_FLOAT:
sprintf(str, dblFormatStr, ((dbr_float_t*) val_ptr)[index]);
@@ -125,7 +138,7 @@ char *val2str (const void *v, unsigned type, int index)
break;
case DBR_CHAR:
ch = ((dbr_char_t*) val_ptr)[index];
sprintf(str, "%d",ch);
sprintf(str, "%d", ch);
break;
case DBR_INT:
sprint_long(str, ((dbr_int_t*) val_ptr)[index]);
@@ -134,15 +147,15 @@ char *val2str (const void *v, unsigned type, int index)
sprint_long(str, ((dbr_long_t*) val_ptr)[index]);
break;
case DBR_ENUM:
{
dbr_enum_t *val = (dbr_enum_t *)val_ptr;
if (dbr_type_is_GR(type) && !enumAsNr)
sprintf(str, "%s", ((struct dbr_gr_enum *)v)->strs[val[index]]);
else if (dbr_type_is_CTRL(type) && !enumAsNr)
sprintf(str, "%s", ((struct dbr_ctrl_enum *)v)->strs[val[index]]);
else
sprintf(str, "%d", val[index]);
}
{
dbr_enum_t *val = (dbr_enum_t *)val_ptr;
if (dbr_type_is_GR(type) && !enumAsNr)
sprintf(str, "%s", ((struct dbr_gr_enum *)v)->strs[val[index]]);
else if (dbr_type_is_CTRL(type) && !enumAsNr)
sprintf(str, "%s", ((struct dbr_ctrl_enum *)v)->strs[val[index]]);
else
sprintf(str, "%d", val[index]);
}
}
return str;
}
@@ -393,19 +406,19 @@ char *dbr2str (const void *value, unsigned type)
if (printAbs) { \
if (tsSrcServer) { \
epicsTimeToStrftime(timeText, TIMETEXTLEN, timeFormatStr, ptsNewS); \
printf("%s ", timeText); \
printf("%s", timeText); \
} \
if (tsSrcClient) { \
epicsTimeToStrftime(timeText, TIMETEXTLEN, timeFormatStr, ptsNewC); \
printf("(%s) ", timeText); \
printf("(%s)", timeText); \
} \
pv->firstStampPrinted = 1; \
} else { \
if (tsSrcServer) { \
printf(" %+12.6f ", epicsTimeDiffInSeconds(ptsNewS, ptsRefS) ); \
printf(" %+12.6f", epicsTimeDiffInSeconds(ptsNewS, ptsRefS) ); \
} \
if (tsSrcClient) { \
printf(" (%+12.6f) ", epicsTimeDiffInSeconds(ptsNewC, ptsRefC) ); \
printf(" (%+12.6f)", epicsTimeDiffInSeconds(ptsNewC, ptsRefC) ); \
} \
} \
\
@@ -418,18 +431,25 @@ char *dbr2str (const void *value, unsigned type)
tsPreviousS = *ptsNewS; \
\
if (charArrAsStr && dbr_type_is_CHAR(TYPE_ENUM) && (reqElems || pv->nElems > 1)) { \
printf("%s ", (dbr_char_t*) dbr_value_ptr(value, pv->dbrType)); \
dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pv->value, pv->dbrType); \
int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s)); \
char *d = calloc(dlen+1, sizeof(char)); \
epicsStrnEscapedFromRaw(d, dlen+1, (char*)s, strlen((char*)s)); \
printf("%c%s", fieldSeparator, d); \
free(d); \
} else { \
if (reqElems || pv->nElems > 1) printf("%lu ", pv->reqElems); \
if (reqElems || pv->nElems > 1) printf("%c%lu", fieldSeparator, pv->reqElems); \
for (i=0; i<pv->reqElems; ++i) { \
printf("%s ", val2str(value, TYPE_ENUM, i)); \
printf("%c%s", fieldSeparator, val2str(value, TYPE_ENUM, i)); \
} \
} \
/* Print Status, Severity - if not NO_ALARM */ \
if ( ((struct TYPE *)value)->status || ((struct TYPE *)value)->severity ) \
{ \
printf("%s %s\n", \
printf("%c%s%c%s\n", \
fieldSeparator, \
stat_to_str(((struct TYPE *)value)->status), \
fieldSeparator, \
sevr_to_str(((struct TYPE *)value)->severity)); \
} else { \
printf("\n"); \
@@ -454,7 +474,9 @@ void print_time_val_sts (pv* pv, unsigned long reqElems)
tsInitS = 1;
}
printf("%-30s ", pv->name);
if (pv->reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name);
else printf("%s", pv->name);
printf("%c", fieldSeparator);
if (!pv->onceConnected)
printf("*** Not connected (PV not found)\n");
else if (pv->status == ECA_DISCONN)

View File

@@ -1,4 +1,6 @@
/*************************************************************************\
* Copyright (c) 2009 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
@@ -9,11 +11,16 @@
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
* $Id$
*
* Author: Ralph Lange (BESSY)
*
* Modification History
* 2009/03/31 Larry Hoff (BNL)
* Added field separators
*
*/
#ifndef INCLtool_libh
@@ -80,6 +87,7 @@ extern int enumAsNr; /* Used for -n option (get DBF_ENUM as number) */
extern int charArrAsStr; /* used for -S option - treat char array as (long) string */
extern double caTimeout; /* Wait time default (see -w option) */
extern char dblFormatStr[]; /* Format string to print doubles (see -e -f option) */
extern char fieldSeparator; /* Output field separator */
extern capri caPriority; /* CA priority */
extern char *val2str (const void *v, unsigned type, int index);