Address of user supplied callback function. A null pointer uninstalls
the current handler. The following arguments are passed by value
to the supplied callback handler.
typedef struct ca_access_rights {
@@ -3929,7 +3928,7 @@ type.
Description
void ca_test_event ( struct event_handler_args );
-A built-in subscription update call back handler for debugging purposes that
+
A built-in subscription update callback handler for debugging purposes that
prints diagnostics to standard out.
Examples
@@ -4285,7 +4284,7 @@ ca_client_status() prints information about the calling threads CA context.
Description
-Returns a pointer to the current thread's CA context. If none then nill is
+
Returns a pointer to the current thread's CA context. If none then null is
returned.
See Also
diff --git a/src/ca/client/perl/CA.pm b/src/ca/client/perl/CA.pm
index 4b993d64d..a7daaf21b 100644
--- a/src/ca/client/perl/CA.pm
+++ b/src/ca/client/perl/CA.pm
@@ -95,8 +95,8 @@ CA - Perl 5 interface to EPICS Channel Access
} else {
printf " Value: %g\n", $data->{value};
printf " Severity: %s\n", $data->{severity};
- printf " Timestamp: %d.%09d\n",
- $data->{stamp}, $data->{stamp_fraction};
+ printf " Timestamp: %.6f\n",
+ $data->{stamp} + $data->{stamp_fraction};
}
}
@@ -235,7 +235,7 @@ C with an exception object in the callback and catch that using C in
the main thread are not likely to succeed and will probably result in a crash.
Callbacks should not perform any operations that would block for more than a
fraction of a second as this will hold up network communications with the
-relevent server and could cause the Perl program and/or the Channel Access
+relevant server and could cause the Perl program and/or the Channel Access
server to crash. Calling C<< CA->pend_event >> from within a callback is not
permitted by the underlying Channel Access library.
@@ -291,7 +291,7 @@ apply to the callback subroutine as described in C above.
=item put_acks( I, I )
-Applications that need to ackowledge alarms by doing a C with type
+Applications that need to acknowledge alarms by doing a C with type
C can do so using the C method. The severity argument
may be provided as an integer from zero through three or as a string containing
one of the corresponding EPICS severity names C, C, C or
@@ -338,11 +338,12 @@ The data provided to a callback function registered with either C
or C can be a scalar value or a reference to an array or a
hash, depending on the data type that was used for the data transfer. If the
request was for a single item of one of the basic data types, the data argument
-will be a perl scalar that holds the value directly. If the request was for
+will be a Perl scalar that holds the value directly. If the request was for
multiple items of one of the basic types, the data argument will be a reference
to an array holding the data. There is one exception though; if the data type
requested was for an array of C values that array will be represented
-as a single Perl string contining all the characters before the first zero byte.
+as a single Perl string containing all the characters before the first zero
+byte.
If the request was for one of the compound data types, the data argument will be
a reference to a hash with keys as described below. Keys that are not classed
@@ -368,7 +369,7 @@ widened from the original type used to request or subscribe for the data.
The number of elements in the data returned by the server. If the data type is
C the value given for C is the number of bytes (including any
trailing zeros) returned by the server, although the value field is given as a
-Perl string contining all the characters before the first zero byte.
+Perl string containing all the characters before the first zero byte.
=back
@@ -430,7 +431,7 @@ Present only when I is C or C.
=item stamp
The process variable timestamp, converted to a local C. This value is
-suitable for passing to the perl C or C functions.
+suitable for passing to the Perl C or C functions.
Present only when I is C.
@@ -633,15 +634,15 @@ passing C as the subroutine reference.
Errors in using the library will be indicated by the module throwing an
exception, i.e. calling C with an appropriate error message. These
-exceptions can be caught using the standard Parl C statement and
+exceptions can be caught using the standard Perl C statement and
testing the C<$@> variable afterwards; if not caught, they will cause the
running program to C with an appropriate error message pointing to the
program line that called the C library.
-Errors messages reported by the underlying CA client library all start with the
+Error messages reported by the underlying CA client library all start with the
string C and the remainder of the symbol for the associated CA error
number, and are followed after a space-hyphen-space by a human-readable message
-describing the error. Errors that are detected by the perl interface layer do
+describing the error. Errors that are detected by the Perl interface layer do
not follow this pattern, but are still printable strings.
diff --git a/src/ca/client/perl/Cap5.xs b/src/ca/client/perl/Cap5.xs
index 6ba538156..287c1826c 100644
--- a/src/ca/client/perl/Cap5.xs
+++ b/src/ca/client/perl/Cap5.xs
@@ -954,16 +954,18 @@ SV * CA_create_subscription(SV *ca_ref, const char *mask_str, SV *sub, ...) {
dbr_text_to_type(treq, type);
if (type < 0) {
- croak_msg = "Unknown data type";
+ croak_msg = "Unknown CA data type";
goto exit_croak;
}
if (type == DBR_PUT_ACKT ||
type == DBR_PUT_ACKS) {
croak_msg = "DBR_PUT_ACK types are write-only";
goto exit_croak;
- } else if (type == DBR_CLASS_NAME ||
+ } else if (type == DBR_GR_ENUM ||
+ type == DBR_CTRL_ENUM ||
+ type == DBR_CLASS_NAME ||
type == DBR_STSACK_STRING)
- /* These break the dbr_type_is macros */ ;
+ /* These above types are supported */ ;
else if (dbr_type_is_SHORT(type))
type += (DBR_LONG - DBR_SHORT);
else if (dbr_type_is_FLOAT(type))
diff --git a/src/ca/client/tools/tool_lib.c b/src/ca/client/tools/tool_lib.c
index b503e125a..f47cfb383 100644
--- a/src/ca/client/tools/tool_lib.c
+++ b/src/ca/client/tools/tool_lib.c
@@ -160,11 +160,21 @@ char *val2str (const void *v, unsigned type, int index)
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
+ if (dbr_type_is_GR(type) && !enumAsNr) {
+ if (val[index] >= MAX_ENUM_STATES)
+ sprintf(str, "Illegal Value (%d)", val[index]);
+ else if (val[index] >= ((struct dbr_gr_enum *)v)->no_str)
+ sprintf(str, "Enum Index Overflow (%d)", val[index]);
+ else
+ sprintf(str, "%s", ((struct dbr_gr_enum *)v)->strs[val[index]]);
+ } else if (dbr_type_is_CTRL(type) && !enumAsNr) {
+ if (val[index] >= MAX_ENUM_STATES)
+ sprintf(str, "Illegal Value (%d)", val[index]);
+ else if (val[index] >= ((struct dbr_ctrl_enum *)v)->no_str)
+ sprintf(str, "Enum Index Overflow (%d)", val[index]);
+ else
+ sprintf(str, "%s", ((struct dbr_ctrl_enum *)v)->strs[val[index]]);
+ } else
sprintf(str, "%d", val[index]);
}
}
diff --git a/src/libCom/misc/epicsString.c b/src/libCom/misc/epicsString.c
index 79be7bf22..ddf8634aa 100644
--- a/src/libCom/misc/epicsString.c
+++ b/src/libCom/misc/epicsString.c
@@ -43,6 +43,9 @@ int epicsStrnRawFromEscaped(char *to, size_t outsize, const char *from,
char c;
size_t nto = 0, nfrom = 0;
+ if (outsize == 0)
+ return 0;
+
while ((c = *pfrom++) && nto < outsize && nfrom < inlen) {
nfrom++;
if (c == '\\') {
@@ -100,7 +103,9 @@ int epicsStrnRawFromEscaped(char *to, size_t outsize, const char *from,
*pto++ = c; nto++;
}
}
- *pto = '\0'; /* NOTE that nto does not have to be incremented */
+ if (nto == outsize)
+ pto--;
+ *pto = '\0';
return nto;
}
diff --git a/src/libCom/test/epicsStringTest.c b/src/libCom/test/epicsStringTest.c
index 5a5934f20..36f8233b5 100644
--- a/src/libCom/test/epicsStringTest.c
+++ b/src/libCom/test/epicsStringTest.c
@@ -84,9 +84,11 @@ MAIN(epicsStringTest)
const char * const a = "a";
const char * const abcd = "abcd";
const char * const abcde = "abcde";
+ char result[8];
char *s;
+ int status;
- testPlan(305);
+ testPlan(323);
testChars();
@@ -123,5 +125,41 @@ MAIN(epicsStringTest)
testGlob();
+ memset(result, 'x', sizeof(result));
+ status = epicsStrnEscapedFromRaw(result, 4, ABCD, 3);
+ testOk(status == 3, "epicsStrnEscapedFromRaw returned %d (exp. 3)", status);
+ testOk(result[4] == 'x', "epicsStrnEscapedFromRaw no buffer overrun");
+ testOk(result[3] == 0, "epicsStrnEscapedFromRaw 0-terminated");
+
+ memset(result, 'x', sizeof(result));
+ status = epicsStrnEscapedFromRaw(result, 4, ABCD, 4);
+ testOk(status == 4, "epicsStrnEscapedFromRaw returned %d (exp. 4)", status);
+ testOk(result[4] == 'x', "epicsStrnEscapedFromRaw no buffer overrun");
+ testOk(result[3] == 0, "epicsStrnEscapedFromRaw 0-terminated");
+
+ memset(result, 'x', sizeof(result));
+ status = epicsStrnEscapedFromRaw(result, 4, ABCDE, 5);
+ testOk(status == 5, "epicsStrnEscapedFromRaw returned %d (exp. 5)", status);
+ testOk(result[4] == 'x', "epicsStrnEscapedFromRaw no buffer overrun");
+ testOk(result[3] == 0, "epicsStrnEscapedFromRaw 0-terminated");
+
+ memset(result, 'x', sizeof(result));
+ status = epicsStrnRawFromEscaped(result, 4, ABCD, 3);
+ testOk(status == 3, "epicsStrnRawFromEscaped returned %d (exp. 3)", status);
+ testOk(result[4] == 'x', "epicsStrnRawFromEscaped no buffer overrun");
+ testOk(result[3] == 0, "epicsStrnRawFromEscaped 0-terminated");
+
+ memset(result, 'x', sizeof(result));
+ status = epicsStrnRawFromEscaped(result, 4, ABCD, 4);
+ testOk(status == 4, "epicsStrnRawFromEscaped returned %d (exp. 4)", status);
+ testOk(result[4] == 'x', "epicsStrnRawFromEscaped no buffer overrun");
+ testOk(result[3] == 0, "epicsStrnRawFromEscaped 0-terminated");
+
+ memset(result, 'x', sizeof(result));
+ status = epicsStrnRawFromEscaped(result, 4, ABCDE, 5);
+ testOk(status == 4, "epicsStrnRawFromEscaped returned %d (exp. 4)", status);
+ testOk(result[4] == 'x', "epicsStrnRawFromEscaped no buffer overrun");
+ testOk(result[3] == 0, "epicsStrnRawFromEscaped 0-terminated");
+
return testDone();
}
diff --git a/src/template/base/Makefile b/src/template/base/Makefile
index 3cb048b0f..865d95c4a 100644
--- a/src/template/base/Makefile
+++ b/src/template/base/Makefile
@@ -52,6 +52,8 @@ TEMPLATES += top/exampleBoot/nfsCommands@RTEMS
TEMPLATES += top/exampleBoot/ioc/Makefile@Common
TEMPLATES += top/exampleBoot/ioc/Makefile@vxWorks
TEMPLATES += top/exampleBoot/ioc/Makefile@win32
+TEMPLATES += top/exampleBoot/ioc/Makefile@windows
+TEMPLATES += top/exampleBoot/ioc/Makefile@cygwin
TEMPLATES += top/exampleBoot/ioc/st.cmd@Common
TEMPLATES += top/exampleBoot/ioc/st.cmd@vxWorks
TEMPLATES += top/exampleBoot/ioc/st.cmd@RTEMS
@@ -81,6 +83,8 @@ TEMPLATES += top/iocBoot/nfsCommands@RTEMS
TEMPLATES += top/iocBoot/ioc/Makefile@Common
TEMPLATES += top/iocBoot/ioc/Makefile@vxWorks
TEMPLATES += top/iocBoot/ioc/Makefile@win32
+TEMPLATES += top/iocBoot/ioc/Makefile@windows
+TEMPLATES += top/iocBoot/ioc/Makefile@cygwin
TEMPLATES += top/iocBoot/ioc/st.cmd@Common
TEMPLATES += top/iocBoot/ioc/st.cmd@Cross
TEMPLATES += top/iocBoot/ioc/st.cmd@vxWorks
diff --git a/src/template/base/top/exampleBoot/ioc/Makefile@cygwin b/src/template/base/top/exampleBoot/ioc/Makefile@cygwin
new file mode 100644
index 000000000..77c3215d7
--- /dev/null
+++ b/src/template/base/top/exampleBoot/ioc/Makefile@cygwin
@@ -0,0 +1,5 @@
+TOP = ../..
+include $(TOP)/configure/CONFIG
+ARCH = _ARCH_
+TARGETS = envPaths relPaths.sh
+include $(TOP)/configure/RULES.ioc
diff --git a/src/template/base/top/exampleBoot/ioc/Makefile@windows b/src/template/base/top/exampleBoot/ioc/Makefile@windows
new file mode 100644
index 000000000..59b32d734
--- /dev/null
+++ b/src/template/base/top/exampleBoot/ioc/Makefile@windows
@@ -0,0 +1,5 @@
+TOP = ../..
+include $(TOP)/configure/CONFIG
+ARCH = _ARCH_
+TARGETS = envPaths dllPath.bat
+include $(TOP)/configure/RULES.ioc
diff --git a/src/template/base/top/iocBoot/ioc/Makefile@cygwin b/src/template/base/top/iocBoot/ioc/Makefile@cygwin
new file mode 100644
index 000000000..77c3215d7
--- /dev/null
+++ b/src/template/base/top/iocBoot/ioc/Makefile@cygwin
@@ -0,0 +1,5 @@
+TOP = ../..
+include $(TOP)/configure/CONFIG
+ARCH = _ARCH_
+TARGETS = envPaths relPaths.sh
+include $(TOP)/configure/RULES.ioc
diff --git a/src/template/base/top/iocBoot/ioc/Makefile@windows b/src/template/base/top/iocBoot/ioc/Makefile@windows
new file mode 100644
index 000000000..59b32d734
--- /dev/null
+++ b/src/template/base/top/iocBoot/ioc/Makefile@windows
@@ -0,0 +1,5 @@
+TOP = ../..
+include $(TOP)/configure/CONFIG
+ARCH = _ARCH_
+TARGETS = envPaths dllPath.bat
+include $(TOP)/configure/RULES.ioc
diff --git a/src/tools/convertRelease.pl b/src/tools/convertRelease.pl
index 5b0890425..abf63c3ec 100644
--- a/src/tools/convertRelease.pl
+++ b/src/tools/convertRelease.pl
@@ -82,6 +82,7 @@ expandRelease(\%macros, \@apps);
for ($outfile) {
m/releaseTops/ and do { &releaseTops; last; };
m/dllPath\.bat/ and do { &dllPath; last; };
+ m/relPaths\.sh/ and do { &relPaths; last; };
m/cdCommands/ and do { &cdCommands; last; };
m/envPaths/ and do { &envPaths; last; };
m/checkRelease/ and do { &checkRelease; last; };
@@ -96,7 +97,8 @@ sub HELP_MESSAGE {
Usage: convertRelease.pl [-a arch] [-T top] [-t ioctop] outfile
where outfile is one of:
releaseTops - lists the module names defined in RELEASE*s
- dllPath.bat - path changes for cmd.exe to find WIN32 DLLs
+ dllPath.bat - path changes for cmd.exe to find Windows DLLs
+ relPaths.sh - path changes for bash to add RELEASE bin dir's
cdCommands - generate cd path strings for vxWorks IOCs
envPaths - generate epicsEnvSet commands for other IOCs
checkRelease - checks consistency with support modules
@@ -113,13 +115,21 @@ sub releaseTops {
}
#
-# Generate Path files so Windows can find our DLLs
+# Generate Path files so Windows/Cygwin can find our DLLs
#
sub dllPath {
unlink $outfile;
open(OUT, ">$outfile") or die "$! creating $outfile";
print OUT "\@ECHO OFF\n";
- print OUT "PATH %PATH%;", join(';', binDirs()), "\n";
+ print OUT "PATH \%PATH\%;", join(';', binDirs()), "\n";
+ close OUT;
+}
+
+sub relPaths {
+ unlink $outfile;
+ open(OUT, ">$outfile") or die "$! creating $outfile";
+ print OUT "export PATH=\$PATH:",
+ join(':', map {m/\s/ ? "\"$_\"" : $_ } binDirs()), "\n";
close OUT;
}