From e484093493569beed9fcef26bab28cbcbd3f7f17 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 2 Apr 2009 02:14:33 +0000 Subject: [PATCH] Bugfixes plus added support for escaping non-printables and field separator to CA commandline tools. --- documentation/RELEASE_NOTES.html | 28 ++++++++++- src/catools/caget.c | 77 +++++++++++++++++++---------- src/catools/cainfo.c | 38 ++++++++------- src/catools/camonitor.c | 48 +++++++++++------- src/catools/caput.c | 84 +++++++++++++++++++------------- src/catools/tool_lib.c | 66 ++++++++++++++++--------- src/catools/tool_lib.h | 10 +++- 7 files changed, 232 insertions(+), 119 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 9877a2db9..fc15ddd2c 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -12,9 +12,35 @@

Changes between 3.14.10 and 3.14.11

+

Channel Access command line tool changes

+ +

The caget/caput/camonitor programs in src/catools now use '\' escape +sequences for non-printable characters.

+ +

They provide a new option -F to set an output field separator +to be used instead of the default space character.

+ +

New functions for escaping non-printables in epicsString.h

+ +

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:

+ +
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);
+ +

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.

+ +

The existing function interfaces will be kept for compatibility, but their +further use is deprecated.

+

epicsRingBytes

-

Partial puts are not supported. An attempt to put more bytes than currently free will be rejected.

+

Partial puts are not supported. +An attempt to put more bytes than currently free will be rejected.

Long string support

diff --git a/src/catools/caget.c b/src/catools/caget.c index 789de7321..82c9301c1 100644 --- a/src/catools/caget.c +++ b/src/catools/caget.c @@ -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 -#include #include +#include +#include #include #include @@ -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] ...\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 : Use 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 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 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 */ diff --git a/src/catools/camonitor.c b/src/catools/camonitor.c index 4cefc3459..24f00e138 100644 --- a/src/catools/camonitor.c +++ b/src/catools/camonitor.c @@ -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 : Use 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 : diff --git a/src/catools/caput.c b/src/catools/caput.c index a1fde247f..825ba860d 100644 --- a/src/catools/caput.c +++ b/src/catools/caput.c @@ -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 #include #include +#include #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 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) { diff --git a/src/catools/tool_lib.c b/src/catools/tool_lib.c index d2c314228..4b327de64 100644 --- a/src/catools/tool_lib.c +++ b/src/catools/tool_lib.c @@ -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 @@ -24,6 +34,7 @@ #include #undef epicsAlarmGLOBAL #include +#include #include #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; ireqElems; ++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) diff --git a/src/catools/tool_lib.h b/src/catools/tool_lib.h index a4c98f802..b53e66111 100644 --- a/src/catools/tool_lib.h +++ b/src/catools/tool_lib.h @@ -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);