Compare commits

...

162 Commits

Author SHA1 Message Date
Ralph Lange
ce7943fb44 Update version to 3.15.6, remove "not released" from release notes 2018-10-11 15:24:36 +02:00
Ralph Lange
4e865a03d8 libCom/osi: fix epicsEnvUnset for WIN32 and solaris 2018-10-11 15:12:10 +02:00
Ralph Lange
9a4febd3bc Merge Dirk Zimoch's 'epicsEnvUnset' branch into 3.15 2018-10-11 11:42:19 +02:00
Andrew Johnson
dc5d373b57 Revert "configure: add vpath for CONFIG* and RULES* (look in SRC_DIRS)"
Unfortunately this causes really bad things to happen; the
configure/RULES file is getting overwritten by the contents of
src/libCom/as/RULES, so we need a different approach.

This reverts commit 47c361f135.
2018-10-10 13:04:54 -05:00
Ralph Lange
47c361f135 configure: add vpath for CONFIG* and RULES* (look in SRC_DIRS) 2018-10-10 17:10:14 +02:00
Ralph Lange
9943796f7f libCom/osi: fix recent epicsStdio.h change for gcc 2.x 2018-10-08 15:46:50 +02:00
3cb72ec209 Merge branch '3.15' into epicsEnvUnset
Conflicts:
	documentation/RELEASE_NOTES.html
2018-10-08 11:02:03 +02:00
701ef5b936 mention epicsEnvUnset in RELEASE_NOTES.html 2018-10-08 10:49:25 +02:00
c3995a9d63 added simple test case for epicsEnvUnset 2018-10-08 10:48:09 +02:00
ce3eadde34 add missing epicsEnvUnset to header 2018-10-08 10:37:34 +02:00
Andrew Johnson
62929fcbd1 Adjust the 'git archive' commands in Release Checklist
The tarfile should not include any files that were added to
support our development process and CI build agents. I have
even excluded .gitignore from previous releases.

I had already done this in 3.16, and 7.0 has a script for
generating the tarfile.
2018-10-05 17:43:33 -05:00
Ralph Lange
456a68eb96 Version number update to 3.15.6-rc1-DEV 2018-10-05 17:05:23 +02:00
Ralph Lange
b319b4722f Update version to 3.15.6-rc1 2018-10-05 15:21:58 +02:00
Ralph Lange
b4cc5fdf4b doc: update release checklist 2018-10-05 15:21:57 +02:00
Ralph Lange
d35835659c libCom/osi: Add epicsStdio functions to std namespace; allow to skip macro magic
(fixes lp:1786927)
2018-10-05 10:54:10 +02:00
65714033ea remove compiler warning 2018-10-03 15:29:30 +02:00
7151fbe498 implement epicsEnvUnset 2018-10-03 15:18:59 +02:00
Andrew Johnson
cbb13bf6b1 Darwin: Don't link using -flat_namespace 2018-09-18 10:22:29 -05:00
Andrew Johnson
150d764d28 Merge 3.14.12.8 (+ the Travis fix) into 3.15 2018-09-17 16:15:55 -05:00
Andrew Johnson
7dd1ea4cab GNU Make 3.81 (as used on Travis) doesn't have 'undefine' 2018-09-17 10:24:51 -05:00
Andrew Johnson
922ed30136 Set EPICS_DEV_SNAPSHOT for the final 3.14.12.8 release 2018-09-14 13:44:05 -05:00
Andrew Johnson
9f9f119e7e Release notes about iocLogServer 2018-09-14 13:21:06 -05:00
Andrew Johnson
d8214a4531 Merge Martin Konrad's fix-logserver-file-limit branch into 3.14 2018-09-14 12:24:14 -05:00
Andrew Johnson
120b100e7e startup: Fix EHA argument quoting per J. Lewis Muir 2018-09-14 12:15:29 -05:00
Andrew Johnson
949e9d788a Make startup/EpicsHostArch script executable 2018-09-14 11:23:14 -05:00
Martin Konrad
27c6e6a385 Make EpicsHostArch compatible with sh 2018-09-14 09:12:10 -04:00
Andrew Johnson
4b59476170 Merge branch 'tidy-startup' into 3.14 2018-09-13 16:49:21 -05:00
Andrew Johnson
526b565c6b configure/CONFIG: Undefine EHA after use 2018-09-10 18:19:03 -05:00
Andrew Johnson
1b7b2bcceb Update README's list of files 2018-09-10 18:16:16 -05:00
Andrew Johnson
49c925d064 Fix shebang line in makeInstallDir.pl 2018-09-10 16:08:19 -05:00
Ralph Lange
6a2ed4b333 libcom/osi/windows: log errors using fprintf() instead of pop-up
(fixes lp:1785712)
2018-09-05 21:47:25 +02:00
Andrew Johnson
d3bcf5737f Latest Xcode also doesn't like compiling system() for iOS 2018-08-17 14:57:22 -05:00
Andrew Johnson
6c5505ad3e osiClockTime again: Don't compile ClockTimeSync() on iOS either 2018-08-17 13:48:00 -05:00
Andrew Johnson
4247d98b08 Add fix to Release Notes 2018-08-17 13:25:18 -05:00
Andrew Johnson
13735a8088 Fix for lp: #1786320
A dbCa link that reads an enum as a string subscribes to the link target
twice, once as DBR_TIME_ENUM and again as DBR_TIME_STRING. This change
prevents ENUM updates from triggering CP/CPP record processing if there
is also a STRING subscription for this link.
2018-08-17 13:18:47 -05:00
Andrew Johnson
58d4242b68 osiClockTime: Only call clock_setting() on embedded OSs
An update to Apple's XCode broke the iOS build because they have
added Posix CLOCK_REALTIME support since this code was written and
now if you compile a call to clock_settime() it stops the build.
2018-08-17 13:09:33 -05:00
Martin Konrad
8e42f516b0 iocLogserver: allow log file limit to be disabled
According to the Application Developer's Guide setting the environment
variable EPICS_IOC_LOG_FILE_LIMIT=0 should disable the limit on the
file size.
2018-08-13 18:16:26 -04:00
Andrew Johnson
9051cdbb34 Added a simpler startup/EpicsHostArch for backwards-compatibility
Many downstream modules seem to be using the EpicsHostArch script in
their CI build scripts and would break if we remove that. I created
a new version that finds and execs the Perl script directly.

Also reworded and expanded the Release Notes about the EpicsHostArch
scripts.
2018-08-10 15:20:29 -05:00
Andrew Johnson
8ffea9de27 Remove macLib warning indicators
Only add ',undefined' tags to macLib output when we aren't
suppressing warnings, e.g. using msi's -V flag.
2018-08-10 14:12:19 -05:00
Andrew Johnson
2548a37267 Update/clean up EpicsHostArch.pl 2018-08-08 16:53:32 -05:00
Andrew Johnson
1dc1b25aaa caget.pl: Add missing acks and ackt metadata to display output 2018-07-31 17:58:38 -05:00
Andrew Johnson
fb31dd784b recGbl: Prevent record alarm severities > INVALID_ALARM 2018-07-31 16:30:11 -05:00
Andrew Johnson
fe7260e263 msi: Source code reformatting, typo fixes, unify messages
Added lots of debug tracing macros.
Release notes.
2018-07-25 00:47:18 -05:00
Andrew Johnson
67e2b74758 Fix for lp: #1503661
Delete output file if parse errors found in substitution file
2018-07-25 00:31:48 -05:00
Andrew Johnson
c09b6e2f1b libCom: Add and use a -o<filename> option to e_flex
Note that like the -S option the filename must follow immediately in
the same command-line argument with no space.
2018-07-21 01:47:33 -05:00
Andrew Johnson
45be2306bd Add missing includes for db_post_events() 2018-07-21 01:04:05 -05:00
Andrew Johnson
6027f906c3 Merge documentation changes from 3.14 into 3.15 2018-07-20 23:29:47 -05:00
Andrew Johnson
ec351c5e2f Fix for lp: #1730727
Post monitors on all array-length record fields (often NORD)
when their values get changed.
2018-07-20 23:10:34 -05:00
89870e2817 Remove trailing space in license of startup/unix.* 2018-07-20 17:47:39 -05:00
4e9cf72d71 Remove execute file mode bit on EpicsHostArch.pl 2018-07-20 17:45:47 -05:00
80869a0868 Rewrite startup/windows.bat
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:43:01 -05:00
998fa984ba Rewrite startup/win32.bat
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:39:29 -05:00
31844af88e Rewrite startup/unix.csh
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:29:47 -05:00
8f161f9463 Rewrite startup/unix.sh
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:18:22 -05:00
e0399478ad Remove startup/cygwin.bat
Cygwin is no longer supported for Microsoft API builds, so remove it.
2018-07-20 17:14:43 -05:00
Andrew Johnson
2a2a1e54ac Post-tag version number update 2018-07-19 12:35:40 -05:00
Andrew Johnson
20d2cff501 Update version number to 3.14.12.8-rc1 2018-07-19 12:31:52 -05:00
Andrew Johnson
860ce156a2 Documentation updates for 3.14.12.8 2018-07-19 12:20:41 -05:00
Andrew Johnson
0f21196670 Merge 3.14 branch into 3.15 2018-07-13 13:23:11 -05:00
Andrew Johnson
31fc35fbe8 dbCa: Fix for lp: #541221
I'd looked at this a few times since it was reported, but never
actually fixed the bug I described in the comments. Apparently
the only thing left to do was to store the eventId and use it to
clear the subscription when we saw a type-change to a PV.
2018-07-13 13:05:54 -05:00
Andrew Johnson
f892731b3f Fix epicsCalcTest for gcc 7.1.0 on minGW
Another case where the compile-time evaluation returns +1
but at run-time isnan() returns -1.
2018-06-29 15:03:45 -05:00
ab493264b2 Make EpicsHostArch.pl print newline
Print a newline after the EPICS host architecture spec.  This is typical
for a UNIX-like program (e.g., date).
2018-06-26 17:56:58 -05:00
68779943eb Remove execute file mode bit 2018-06-26 16:34:04 -05:00
7a5ff26984 Remove EpicsHostArch 2018-06-26 16:20:07 -05:00
eae59183cc Rename Site.{cshrc,profile} to unix.{csh,sh} 2018-06-26 16:09:04 -05:00
Andrew Johnson
8144d2ea01 Add HOWTO: Converting Wiki Record Reference to POD 2018-06-26 14:47:59 -05:00
Andrew Johnson
b32629c3bf Start release notes for tidy-startup branch. 2018-06-26 11:23:35 -05:00
Andrew Johnson
220e404203 Move EpicsHostArch.pl into src/tools, install to lib/perl 2018-06-26 11:23:15 -05:00
Andrew Johnson
8f55a1307d startup: Update win*.bat files 2018-06-22 14:54:06 -05:00
Ralph Lange
e459e8bdd4 cas: don't spin on zero-length search requests
(fix lp:1743321)
2018-06-07 11:32:16 +02:00
Ralph Lange
b558bd9b16 Cherry-picking e794639e from 3.15
(lp:1730982 lp:1762543)
2018-06-07 11:21:04 +02:00
Michael Davidsaver
3c16c3c0da Cherry-picking d2b0e920 from 3.15
(closes lp:1773373)
2018-06-07 11:07:29 +02:00
Andrew Johnson
a9d7f7be13 Template iocBoot/ioc Makefile fix for Unix-like OSs
Fixes lp: #1766349
2018-06-04 23:14:45 -05:00
Andrew Johnson
23c4eb42a3 Perl s/use vars/our/ 2018-05-28 17:31:16 -05:00
Andrew Johnson
6d7f70f200 Merge changes from 3.14 branch into 3.15 2018-05-28 17:00:35 -05:00
Andrew Johnson
67844bacc3 Perl s/use vars/our/ 2018-05-28 16:13:14 -05:00
Ralph Lange
7e7d230d8c templates: fix warnings for xxxRecord.c in exampleApp
(fixes #1772833)
2018-05-23 09:24:56 +02:00
Andrew Johnson
c1ece40f41 Updated Release Notes for Base-3.14.12.8 2018-05-19 22:42:23 -05:00
Andrew Johnson
a732539eee epicsMath.h defines 'finite()' not 'isfinite()' 2018-05-19 21:14:36 -05:00
Ralph Lange
3bc0805a89 rec: fix missing includes in longin/longout 2018-05-18 09:54:42 +02:00
Ralph Lange
c72e35c769 Merge Ralph's fix-1770292 branch into 3.14 2018-05-17 17:16:07 +02:00
Ralph Lange
2d9c5e99a1 db: correctly convert NaN alarm levels to integers
(fixes lp #1771298)
2018-05-15 11:18:11 +02:00
Ralph Lange
ca22d50831 rec: consistent get_alarm_double() for longin/longout
(fixes lp #1770292)
2018-05-15 11:18:10 +02:00
Michael Davidsaver
4972803ce2 scanEventTest: use testSyncCallback() 2018-05-14 10:49:49 -07:00
Michael Davidsaver
3b7e348a8c dbUnitTest.h add callback sync. and global mutex
Add testSyncCallback() to wait for in queued and
in-progress callbacks to complete.

Also add testGlobalLock() to help tests avoid
use after free when destroying sync. primitives.
2018-05-14 10:49:49 -07:00
Michael Davidsaver
00a974ce52 callback.h: add epicsCallback alternative to CALLBACK
Add epicsCallback as an IDE friendly alternative to CALLBACK.

IDEs like qtcreator have long been confused by the use
of CALLBACK, a name which has long been used by other libraries,
which prevents code using it from being parsed correctly.
2018-05-14 10:49:49 -07:00
Michael Davidsaver
490c504736 scanEventTest: use dbUnitTest.h for IOC lifecycle 2018-05-14 10:49:49 -07:00
Andrew Johnson
49371cfe00 Fix RTEMS build in src/std/rec/test
Also back-ported Michael's change from commit b9b8cde5f6 to avoid
using callocMustSucceed() in eventNameToHandle()
2018-05-12 22:25:15 -05:00
Andrew Johnson
06ad4a0d70 Merge Bruce Hill's pv-name-in-ca-error-msgs branch into 3.15
Actually this is fixing CAS error messages.
I added the additional changes suggested by Ralph in his code-review.
2018-05-12 21:37:44 -05:00
Andrew Johnson
a2ae07dfcd Merge Dirk Zimoch's named-events-backward-compatibility branch into 3.15 2018-05-12 21:15:26 -05:00
Andrew Johnson
b539ced6d5 Merge J. Lewis Muir's doc-filters-typo branch into 3.15 2018-05-12 20:54:20 -05:00
Andrew Johnson
1b332361e7 Merge changes from 3.14 into 3.15 2018-05-12 20:47:54 -05:00
Andrew Johnson
5cb91d9f6d Merge Ben Franksen's deadlock_warning branch into 3.14 2018-05-12 20:20:30 -05:00
Andrew Johnson
116c90c2ea Reformatting, no code changes 2018-05-03 14:40:12 -05:00
Andrew Johnson
3f3696fb91 dbStatic: Prevent modifying a NAME field using a DB file
Fixes LP: #1597809
2018-05-03 14:28:44 -05:00
Benjamin Franksen
91ce807e8b Fix for lp: #1751380
Add warnings about possible deadlock to the docs for ca_clear_channel,
ca_clear_subscription, and ca_context_destroy.
2018-04-11 12:58:28 +02:00
Andrew Johnson
3d88316eab Merge 3.14 into 3.15 (MSVC absolute filenames fix) 2018-03-26 16:49:28 -05:00
Andrew Johnson
b9443f8813 Tell MSVC to use absolute filenames in diagnostics (-FC flag) 2018-03-23 11:39:53 -05:00
Andrew Johnson
d8802c8b24 Merge 3.14 into 3.15 2018-03-15 17:46:48 -05:00
Andrew Johnson
b7d4609e57 Merge Bruce Hill's camonitor-server-relative-ts-bug-3.14 branch 2018-03-15 17:33:32 -05:00
Andrew Johnson
7b5b23f6d3 Merge 3.14 into 3.15 2018-03-15 17:11:20 -05:00
Andrew Johnson
c8a7e1597d VxWorks Timezone updates
Remove 2017; fix hour in MET settings
2018-03-15 10:57:55 -05:00
Andrew Johnson
8333338f99 Merge 3.14 into 3.15 2018-03-14 16:08:07 -05:00
Andrew Johnson
ceaff61c09 Pull in the podToHtml.pl script and rules from 3.15
This lets src/cap5 build with Perl installations that lack Perl's
podchecker and pod2html scripts (e.g. Fedora 27).
2018-03-14 14:12:12 -05:00
Andrew Johnson
2307e94d1c Rules for building bootable TESTPROD_RTEMS targets
Previously if you wanted a .boot file it had to be installed.
2018-03-12 16:34:54 -05:00
Bruce Hill
05a3699b49 Update pcas CA error msgs to include the pv name for easier debugging. 2018-03-09 21:23:43 -08:00
Andrew Johnson
be8f35d782 Fix for lp: #1754298
Cleaned up and reformatted since Dirk's original.
2018-03-09 12:46:46 -06:00
Bruce Hill
6cc623a7b4 Fixed camonitor server side relative timestamps bug
tsFirst needs to get initialized from the first server side
timestamp instead of the client side tsNow.
2018-03-08 01:40:11 -08:00
2b4a9632b7 update RELEASE_NOTES for named event fix 2018-03-07 14:51:38 +01:00
396cf4ee3f remove special handling for inf and nan events 2018-03-07 14:49:12 +01:00
Andrew Johnson
a9764c8f62 tools/caput: Report errors from ca_array_put*()
Fixes LP: #1747983
2018-03-04 15:51:39 -06:00
Andrew Johnson
98d9ea4545 ca/client: Catch by reference, missing '&' 2018-03-04 15:45:15 -06:00
Andrew Johnson
8eb4eec7d2 Corrected fix from Bruce Hill's Github PR#19 2018-03-03 17:17:34 -06:00
Andrew Johnson
98930eebc4 strcpy() -> strncpy() changes from Bruce Hill
Also added some additional static assertions for string field sizes.
2018-03-03 00:12:59 -06:00
e50c468512 moved scanEventTest from src/ioc/db/test to src/std/rec/test 2018-02-26 11:41:54 +01:00
Andrew Johnson
c18b6f2ccf Deny use of dbgf, dbpf, dbtr, dbtgf and dbtpf before iocInit
Can't use locking dbAccess routines until lock-sets have been calculated.
Fixes LP: #1725248
2018-02-24 20:15:08 -06:00
Andrew Johnson
e41f8bf518 Translate and escape chars in info tag strings
Fixes LP: #1716998
2018-02-24 19:11:54 -06:00
Andrew Johnson
ae548d3400 Remove cantProceed() from dbGetLink() and dbPutLink()
Fixes LP: #1528314
Affects 3.15 branch only.
2018-02-24 17:40:45 -06:00
428a8f57e9 Fix typos in Channel Filters doc 2018-02-20 10:20:37 -06:00
29795656e6 bugfix for soft events >= 256 2018-02-20 09:53:06 +01:00
b2d6b67b06 removed obsolete code in scanpel 2018-02-16 11:03:12 +01:00
1e9826d187 add tests for calculated numeric soft events 2018-02-13 15:36:21 +01:00
0691fc5f57 fix scanEvent test 2018-02-13 14:10:29 +01:00
8a3080c16f added test for named soft events 2018-02-13 13:50:19 +01:00
d19afc73af Updated RELEASE_NOTES.html with soft event fix. 2018-02-12 12:06:12 +01:00
adf5375616 fix scanpel glob matching 2018-02-12 09:01:05 +01:00
Andrew Johnson
550beeab9f More clang warning clean-ups
The short => int change is a UB issue, the second argument to va_start()
must be of a type that does not undergo promotion. See
https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP58-CPP.+Pass+an+object+of+the+correct+type+to+va_start
2018-02-09 11:29:16 -06:00
Andrew Johnson
bf91275200 Merge clang fixes from 3.14 into 3.15 2018-02-09 11:16:26 -06:00
Andrew Johnson
ac4d5c95ac Clean up some compiler warnings from clang 2018-02-09 10:56:52 -06:00
7d836d9554 some cleanup and scanpel improvement 2018-02-09 16:58:36 +01:00
51e492fbb1 Fix numeric events: any number from 0 up to less than 256 is theated as an integer event. Event 0 is no event. 2018-02-09 14:37:45 +01:00
Andrew Johnson
61296b8cff Merge 3.14 into 3.15
Fix for LP: #1743076
2018-02-05 12:03:28 -06:00
Andrew Johnson
de442e9584 Fix for LP: #1743076
Never zero the CA client context private ID.
2018-02-05 12:02:13 -06:00
Andrew Johnson
ac367398b3 Merge fix for lp: #1747091 from 3.14 into 3.15 2018-02-02 17:49:00 -06:00
Andrew Johnson
713c2d5080 Fix for lp: #1747091
generalTimeGetEvent()
2018-02-02 17:47:35 -06:00
Andrew Johnson
af07016464 Merge 3.14 branch into 3.15
Actually a different fix to Michael's 3.14 commit due to divergent code.
2018-02-01 14:20:47 -06:00
Michael Davidsaver
734d16291f rsrv: buffer for IP too small
An IPv4 address and port number
has 21 characters max.
2018-02-01 09:42:51 -08:00
Andrew Johnson
f1e5e9689b Merge 3.14 branch into 3.15 2018-02-01 11:23:29 -06:00
Andrew Johnson
1454f42a27 Config fix for parallel builds with MSVC 2015 and later
From Mark Rivers and Freddie Akeroyd.
2018-02-01 11:19:08 -06:00
Andrew Johnson
ddbdcf9462 rec/test: Add missing filename to DBDDEPENDS_FILES 2018-01-21 00:44:10 -06:00
Andrew Johnson
729e6fda4d tools: Add some context to the 'Undefined macro' warning
Mark Rivers saw this warning when he forgot to configure and build a
dependent module properly. The additional information given by this
change would have helped him track down the problem faster.
2018-01-19 13:14:13 -06:00
Andrew Johnson
0315e90e6e Revert "tools: Use Carp"
This reverts commit f207b00b05.

None of these warn/die messages request a stack dump since they all
end with \n, but carp & croak ignore that.
2018-01-19 11:06:23 -06:00
Andrew Johnson
66c6aaa44f Merge URL updates from 3.14 branch into 3.15 2018-01-18 23:46:42 -06:00
Andrew Johnson
c830a3a4ee Updated links to new EPICS website at Argonne
Only done for documents that are still present in EPICS 7.
2018-01-18 23:35:09 -06:00
Andrew Johnson
8766ce05aa Fix slow callback test failures.
Slow callbacks no longer cause test failures, now they just emit a
diagnostic. Jenkins on MacOS frequently failed those tests.

We should never test for something that we can't fix.
2018-01-04 11:41:38 -06:00
Ralph Lange
8f62940265 Merge appveyor change from 3.14 2018-01-04 09:03:50 +01:00
Ralph Lange
8a1477ecab appveyor-ci: update APS download URL 2018-01-04 09:00:18 +01:00
Ralph Lange
89cbb95c2c Merge appveyor changes from 3.14 2017-12-19 09:52:15 +01:00
Ralph Lange
006ce1a240 appveyor-ci: remove VS 2008, add VS 2017 2017-12-19 09:39:57 +01:00
Ralph Lange
276dee2c3e appveyor-ci: use curl for download of make.zip 2017-12-19 09:39:10 +01:00
Andrew Johnson
98a2871727 Reset SNAPSHOT to -DEV after tagging 3.14.12.7 2017-12-15 16:09:21 -06:00
Andrew Johnson
5ca1bb3bd5 Set SNAPSHOT for 3.14.12.7 final release 2017-12-15 16:06:08 -06:00
Andrew Johnson
f6be3c7f70 Set snapshot to -rc1-DEV 2017-12-08 16:40:08 -06:00
Andrew Johnson
00924dcba0 About to tag 3.14.12.7-rc1 2017-12-08 16:37:03 -06:00
Andrew Johnson
3b0f34e0be Fix recursive check in Release.pm 2017-12-06 16:29:31 -06:00
Andrew Johnson
db005ac3fe RULES_TARGET: Define $(lib)_DIR before it is needed
TESTLIBRARY products were being installed, because an executable
that was linked to one added a dependency assuming it would be in
the INSTALL_LIB directory. The $(lib)_DIR was being set too late
for test libraries, so the fallback location was used instead.
This fix sets $(lib)_DIR for test libraries before any rules use it.
2017-11-17 14:55:50 -06:00
Andrew Johnson
0f0deb8903 Merge fixups/db_close_events into 3.15 2017-11-15 21:23:28 -06:00
Andrew Johnson
baf997193e Merge aSubRecord fixes from 3.14 into 3.15 2017-11-15 21:15:51 -06:00
Andrew Johnson
5278799575 aSubRecord: Copy the right amount of data
Initialize OVLx from VALx with NEVx elements, size from FTVx
2017-11-15 20:59:06 -06:00
Andrew Johnson
031e755303 installEpics.pl: Make temporary install filename more different
A parallel build was seen matching the temporary name in a wildcard.
Now the temporary name both starts and ends differently.
2017-11-11 18:00:57 -06:00
Michael Davidsaver
e794639e31 ioc/db: avoid possible race in db_close_events()
lp:1730982
2017-11-08 14:42:08 -06:00
Michael Davidsaver
2af98c33c9 std/rec: aSub handle INAM changing outputs
Allow EFLG="On Change" to work with INAM.
2017-11-08 14:29:30 -06:00
128 changed files with 2766 additions and 1449 deletions

2
README
View File

@@ -20,5 +20,5 @@ Additional information about EPICS including mailing list
archives and subscription instructions, documentation and
training materials, additional components, links to other
websites etc. is available on the EPICS home page at
http://www.aps.anl.gov/epics/
https://epics.anl.gov/

View File

@@ -40,11 +40,12 @@ configuration:
# Environment variables: compiler toolchain
environment:
matrix:
- TOOLCHAIN: 9.0
- TOOLCHAIN: 10.0
- TOOLCHAIN: 11.0
- TOOLCHAIN: 12.0
- TOOLCHAIN: 14.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLCHAIN: 2017
- TOOLCHAIN: cygwin
- TOOLCHAIN: mingw
@@ -57,8 +58,6 @@ platform:
matrix:
exclude:
# VS Express installs don't have the 64 bit compiler
- platform: x64
TOOLCHAIN: 9.0
- platform: x64
TOOLCHAIN: 10.0

View File

@@ -1,6 +1,6 @@
:: Universal build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - toolchain version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static]
:: PLATFORM - architecture [x86/x64]
::
@@ -57,10 +57,22 @@ if "%TOOLCHAIN%"=="mingw" (
)
set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio %TOOLCHAIN%"
if not exist "%VSINSTALL%\" set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio\%TOOLCHAIN%\Community"
if not exist "%VSINSTALL%\" goto MSMissing
set "MAKE=C:\tools\make"
echo [INFO] APPVEYOR_BUILD_WORKER_IMAGE=%APPVEYOR_BUILD_WORKER_IMAGE%
if "%OS%"=="64BIT" (
set EPICS_HOST_ARCH=windows-x64%ST%
:: VS 2017
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat" (
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" amd64
where cl
@@ -79,12 +91,19 @@ if "%OS%"=="64BIT" (
)
) else (
set EPICS_HOST_ARCH=win32-x86%ST%
:: VS 2017
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat" (
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" x86
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
)
if exist "%VSINSTALL%\VC\bin\vcvars32.bat" (
call "%VSINSTALL%\VC\bin\vcvars32.bat"
where cl

View File

@@ -65,6 +65,6 @@ if "%TOOLCHAIN%"=="mingw" (
)
echo [INFO] Installing Make 4.1
@powershell -Command "(new-object net.webclient).DownloadFile('https://www.aps.anl.gov/epics/download/tools/make-4.1-win64.zip', 'C:\tools\make-4.1.zip')"
curl -fsS --retry 3 -o C:\tools\make-4.1.zip https://epics.anl.gov/download/tools/make-4.1-win64.zip
cd \tools
"C:\Program Files\7-Zip\7z" e make-4.1.zip

View File

@@ -17,7 +17,7 @@ ticker() {
CACHEKEY=1
EPICS_HOST_ARCH=`sh startup/EpicsHostArch`
EPICS_HOST_ARCH=`perl src/tools/EpicsHostArch.pl`
[ -e configure/os/CONFIG_SITE.Common.linux-x86 ] || die "Wrong location: $PWD"

View File

@@ -20,11 +20,15 @@ else
endif
# Provide a default if the user hasn't set EPICS_HOST_ARCH
ifeq ($(origin EPICS_HOST_ARCH), undefined)
# NB: We use a simply expanded variable here for performance:
EPICS_HOST_ARCH := $(shell $(CONFIG)/../startup/EpicsHostArch.pl)
endif
#
ifeq ($(origin EPICS_HOST_ARCH), undefined)
# Bootstrapping ...
EHA := $(firstword $(wildcard $(EPICS_BASE)/lib/perl/EpicsHostArch.pl \
$(TOP)/src/tools/EpicsHostArch.pl))
# NB: We use a simply expanded variable here for performance:
export EPICS_HOST_ARCH := $(shell perl $(EHA))
EHA :=
endif
-include $(CONFIG)/RELEASE
-include $(CONFIG)/RELEASE.$(EPICS_HOST_ARCH)

View File

@@ -27,14 +27,14 @@ EPICS_VERSION = 3
EPICS_REVISION = 15
# EPICS_MODIFICATION must be a number >=0 and <256
EPICS_MODIFICATION = 5
EPICS_MODIFICATION = 6
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# Not included if zero
EPICS_PATCH_LEVEL = 0
# This will end in -DEV between official releases
EPICS_DEV_SNAPSHOT=-DEV
#EPICS_DEV_SNAPSHOT=-DEV
#EPICS_DEV_SNAPSHOT=-pre1
#EPICS_DEV_SNAPSHOT=-pre1-DEV
#EPICS_DEV_SNAPSHOT=-pre2
@@ -43,7 +43,7 @@ EPICS_DEV_SNAPSHOT=-DEV
#EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc2
#EPICS_DEV_SNAPSHOT=-rc2-DEV
#EPICS_DEV_SNAPSHOT=
EPICS_DEV_SNAPSHOT=
# No changes should be needed below here

View File

@@ -34,35 +34,30 @@
# The future dates below assume the rules don't get changed;
# see http://www.timeanddate.com/time/dst/2018.html to check.
#
# DST for 2017 US: Mar 12 - Nov 05
# EU: Mar 26 - Oct 29
EPICS_TIMEZONE = CUS::360:031202:110502
#EPICS_TIMEZONE = MET::-60:032602:102902
#
# DST for 2018 US: Mar 11 - Nov 04
# EU: Mar 25 - Oct 28
#EPICS_TIMEZONE = CUS::360:031102:110402
#EPICS_TIMEZONE = MET::-60:032502:102802
EPICS_TIMEZONE = CUS::360:031102:110402
#EPICS_TIMEZONE = MET::-60:032502:102803
#
# DST for 2019 US: Mar 10 - Nov 03
# EU: Mar 31 - Oct 27
#EPICS_TIMEZONE = CUS::360:031002:110302
#EPICS_TIMEZONE = MET::-60:033102:102702
#EPICS_TIMEZONE = MET::-60:033102:102703
#
# DST for 2020 US: Mar 08 - Nov 01
# EU: Mar 29 - Oct 25
#EPICS_TIMEZONE = CUS::360:030802:110102
#EPICS_TIMEZONE = MET::-60:032902:102502
#EPICS_TIMEZONE = MET::-60:032902:102503
#
# DST for 2021 US: Mar 14 - Nov 07
# EU: Mar 28 - Oct 31
#EPICS_TIMEZONE = CUS::360:031402:110702
#EPICS_TIMEZONE = MET::-60:032802:103102
#EPICS_TIMEZONE = MET::-60:032802:103103
#
# DST for 2022 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
#EPICS_TIMEZONE = CUS::360:031302:110602
#EPICS_TIMEZONE = MET::-60:032702:103002
#EPICS_TIMEZONE = MET::-60:032702:103003
# EPICS_TS_NTP_INET
# NTP time server ip address for VxWorks and RTEMS.

View File

@@ -102,6 +102,7 @@ endif
# Products and Object libraries
#
PRODTARGETS += $(PRODNAME) $(MUNCHNAME) $(CTDT_SRCS) $(CTDT_OBJS) $(NMS)
TESTPRODTARGETS += $(TESTPRODNAME) $(TESTMUNCHNAME)
#---------------------------------------------------------------
# Test specifications and test result files
@@ -140,7 +141,7 @@ rebuild: clean install
build: inc
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODNAME) \
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODTARGETS) \
$(TARGETS) $(TESTSCRIPTS) $(INSTALL_LIB_INSTALLS)
inc : $(COMMON_INC) $(INSTALL_INC) $(INSTALL_CONFIGS)
@@ -158,20 +159,21 @@ clean: build_clean
build_clean:
$(ECHO) "Cleaning"
@$(RM) *.i *$(OBJ) *.a $(TESTPRODNAME) \
@$(RM) *.i *$(OBJ) *.a \
$(LIBNAME) $(TESTLIBNAME) $(SHRLIBNAME) $(TESTSHRLIBNAME) \
$(DLLSTUB_LIBNAME) $(TESTDLLSTUB_LIBNAME) \
$(LOADABLE_SHRLIBNAME) \
$(INC) $(TARGETS) $(TDS) $(CLEANS) \
*.out MakefileInclude *.manifest *.exp \
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) \
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) $(TESTPRODTARGETS) \
$(TESTSCRIPTS) $(TAPFILES) $(JUNITFILES)
ifdef RES
@$(RM) *$(RES)
endif
$(DIRECTORY_TARGETS) :
$(MKDIR) -p $@
# Sort mkdir targets to remove duplicates & make parents first
$(DIRECTORY_TARGETS):
$(MKDIR) $(sort $@)
# Install LIB_INSTALLS libraries before linking executables
$(TESTPRODNAME) $(PRODNAME): | $(INSTALL_LIB_INSTALLS)
@@ -254,15 +256,13 @@ YACCOPT ?= $($*_YACCOPT)
$(MV) $*.tab.c $*.c
$(if $(findstring -d, $(YACCOPT)),$(MV) $*.tab.h $*.h,)
# must be a seperate rule since when not using '-d' the
# must be a separate rule since when not using '-d' the
# prefix for .h will be different then .c
%.h : %.c %.y
%.c: %.l
@$(RM) $*.yy.c
$(LEX) $(LEXOPT) -t $< > $*.yy.c
@$(RM) $@
$(MV) $*.yy.c $@
$(LEX) $(LEXOPT) -o$@ $<
#---------------------------------------------------------------
# Libraries, shared/DLL and stubs
@@ -321,6 +321,10 @@ $(MUNCHNAME): %$(MUNCH_SUFFIX): $(MUNCH_DEPENDS) %$(EXE)
@$(RM) $@
$(MUNCH_CMD)
$(TESTMUNCHNAME): %$(MUNCH_SUFFIX): $(MUNCH_DEPENDS) %$(EXE)
@$(RM) $@
$(MUNCH_CMD)
#---------------------------------------------------------------
# GeSys modules for RTEMS
$(MODNAME): %$(MODEXT): %$(EXE)

View File

@@ -38,6 +38,17 @@ $(foreach target, $(PROD) $(TESTPROD), \
#-----------------------------------------------------------------------
# These must be done before PROD2_template
define TESTLIBRARY_template
$(1)_DIR = .
TESTBUILD_LIBRARY += $$(if $$(strip $$($(1)_OBJSNAME) $$(LIBRARY_OBJS)),$(1),)
endef
$(foreach target, $(TESTLIBRARY), \
$(eval $(call TESTLIBRARY_template,$(strip $(target)))))
#-----------------------------------------------------------------------
define TARGET2_template
$(1)_LDLIBS += $$($(1)_LIBS)
$(1)_LDLIBS += $$(if $$(strip $$($(1)_LIBS_$(OS_CLASS))), \
@@ -123,16 +134,6 @@ $(foreach target, $(LIBRARY), \
#-----------------------------------------------------------------------
define LIBRARY3_template
$(1)_DIR = .
TESTBUILD_LIBRARY += $$(if $$(strip $$($(1)_OBJSNAME) $$(LIBRARY_OBJS)),$(1),)
endef
$(foreach target, $(TESTLIBRARY), \
$(eval $(call LIBRARY3_template,$(strip $(target)))))
#-----------------------------------------------------------------------
define LOADABLE_LIBRARY_template
LOADABLE_BUILD_LIBRARY += $$(if $$(strip $$($(1)_OBJSNAME) $$(LIBRARY_OBJS)),$(1),)

View File

@@ -136,6 +136,13 @@ MOD_LDFLAGS = $(OPT_LDFLAGS) $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(POSIX_LDFLAGS) \
LINK.mod = $(CCC) -o $@ $(PRODDIR_LDFLAGS) $(MOD_LDFLAGS)
LINK.mod += $(PROD_LDFLAGS) $(PROD_LD_OBJS) $(PROD_LD_RESS) $(MOD_LDLIBS)
#--------------------------------------------------
# Here munching means creating a bootable object binary
ifdef MUNCH_SUFFIX
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
TESTMUNCHNAME = $(TESTPRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
endif
#--------------------------------------------------
# RTEMS has neither shared libraries nor dynamic loading
STATIC_BUILD=YES

View File

@@ -15,7 +15,6 @@ ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@
endef

View File

@@ -13,7 +13,6 @@ ARCH_DEP_CFLAGS += -DHAVE_PPCBUG
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< rtems
gzip -f9 rtems

View File

@@ -7,7 +7,6 @@ ARCH_DEP_CFLAGS += -DHAVE_PPCBUG
ARCH_DEP_CFLAGS += -DNVRAM_INDIRECT
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< rtems
gzip -f9 rtems

View File

@@ -15,7 +15,6 @@ ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@
endef

View File

@@ -16,7 +16,6 @@ ARCH_DEP_CFLAGS += -DBSP_NVRAM_BASE_ADDR=0xf1110000
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@
endef

View File

@@ -8,7 +8,6 @@
RTEMS_TARGET_CPU=i386
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< temp.bin
$(BIN2BOOT) $@ 0x00097E00 \

View File

@@ -9,7 +9,6 @@ RTEMS_TARGET_CPU = m68k
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $@
endef

View File

@@ -65,14 +65,14 @@ GNU = NO
#
# Darwin shared libraries
#
SHRLIB_LDFLAGS = -dynamiclib -flat_namespace -undefined suppress \
SHRLIB_LDFLAGS = -dynamiclib -undefined dynamic_lookup \
-install_name $(shell $(FULLPATHNAME) $(INSTALL_LIB))/$@ \
$(addprefix -compatibility_version , $(SHRLIB_VERSION)) \
$(addprefix -current_version , $(SHRLIB_VERSION))
SHRLIB_SUFFIX_BASE = .dylib
SHRLIB_SUFFIX = $(addprefix ., $(SHRLIB_VERSION))$(SHRLIB_SUFFIX_BASE)
LOADABLE_SHRLIB_LDFLAGS = -bundle -flat_namespace -undefined suppress
LOADABLE_SHRLIB_LDFLAGS = -bundle -undefined dynamic_lookup
#
# Position-independent code is the default on Darwin.

View File

@@ -79,16 +79,20 @@ CPP = cl -nologo -C -E
# Configure OS vendor C++ compiler
#
# __STDC__=0 gives us both:
# 1) define STDC for code (pretend ANSI conformance)
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
# because MS uses: if __STDC__ ... disable many nice things
#
# -EHsc - generate code for exceptions
# -GR - generate code for run time type identification
#
CCC = cl -EHsc -GR
CODE_CPPFLAGS += -nologo -D__STDC__=0
# Other compiler flags, used for CPP, C and C++
#
# -FC - Show absolute path of source file in diagnostics
# -D__STDC__=0 gives us both:
# 1) define STDC for code (pretend ANSI conformance)
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
# because MS uses: if __STDC__ ... disable many nice things
#
CODE_CPPFLAGS += -nologo -FC -D__STDC__=0
CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
@@ -136,6 +140,16 @@ STATIC_LDLIBS_NO=
STATIC_LDFLAGS=
RANLIB=
#
# option needed for parallel builds with Visual Studio 2015 onward
#
# -FS Force Synchronous PDB Writes
ifneq ($(VisualStudioVersion),)
OPT_CXXFLAGS_NO += -FS
OPT_CFLAGS_NO += -FS
endif
#
# add -profile here to run the ms profiler
# -LTCG whole program optimization

View File

@@ -15,7 +15,7 @@ base-3.15.6 tree. Download them, then use the GNU Patch program as
follows:</p>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.6</b>
% <b>patch -p0 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
% <b>patch -p1 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
<p>The following significant problems have been reported with this
version of EPICS Base:</p>

View File

@@ -6,19 +6,19 @@
Table of Contents
* What is EPICS base?
* What is new in this release?
* Copyright
* Supported platforms
* Supported compilers
* Software requirements
* Host system storage requirements
* Documentation
* Directory Structure
* Build related components
* Building EPICS base (Unix and Win32)
* Example application and extension
* Multiple host platforms
* What is EPICS base?
* What is new in this release?
* Copyright
* Supported platforms
* Supported compilers
* Software requirements
* Host system storage requirements
* Documentation
* Directory Structure
* Build related components
* Building EPICS base (Unix and Win32)
* Example application and extension
* Multiple host platforms
--------------------------------------------------------------------------
@@ -166,12 +166,11 @@
base/startup directory - contains scripts to set environment and path
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
Site.profile bourne shell script to set path and env variables
Site.cshrc c shell script to set path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
win32.bat WIN32 bat file to set path and env variables
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
unix.csh C shell script to set path and env variables
unix.sh Bourne shell script to set path and env variables
win32.bat Bat file example to configure win32-x86 target
windows.bat Bat file example to configure windows-x64 target
base/configure directory - contains build definitions and rules

View File

@@ -21,7 +21,7 @@ of my Bash login script (~/.bash_login):
#
EPICS_BASE="${HOME}/src/EPICS/base"
EPICS_EXTENSIONS="${HOME}/src/EPICS/extensions"
<strong>.</strong> "${EPICS_BASE}"/startup/Site.profile
<strong>.</strong> "${EPICS_BASE}"/startup/unix.sh
</pre>
</li>
<li>

View File

@@ -98,8 +98,8 @@
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
target-specific overrides.</P>
<P>Consult the <a href="http://www.aps.anl.gov/epics/base/tornado.php">vxWorks
5.x</a> or <a href="http://www.aps.anl.gov/epics/base/vxWorks6.php">vxWorks
<P>Consult the <a href="https://epics.anl.gov/base/tornado.php">vxWorks
5.x</a> or <a href="https://epics.anl.gov/base/vxWorks6.php">vxWorks
6.x</a> EPICS web pages about and the vxWorks documentation for information
about configuring your vxWorks operating system for use with EPICS.</P>
@@ -129,7 +129,7 @@
<H3><A NAME="0_0_8"> Documentation</A></H3>
<BLOCKQUOTE>EPICS documentation is available through the
<a href="http://www.aps.anl.gov/epics/">EPICS website</a> at Argonne.
<a href="https://epics.anl.gov/">EPICS website</a> at Argonne.
<P>Release specific documentation can also be found in the base/documentation
directory of the distribution.</BLOCKQUOTE>
@@ -177,12 +177,11 @@
<H4>base/startup directory - contains scripts to set environment and path</H4>
<PRE>
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
Site.profile bourne shell script to set path and env variables
Site.cshrc c shell script to set path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
win32.bat WIN32 bat file to set path and env variables
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
unix.csh C shell script to set path and env variables
unix.sh Bourne shell script to set path and env variables
win32.bat Bat file example to configure win32-x86 target
windows.bat Bat file example to configure windows-x64 target
</PRE>
<H4>base/configure directory - contains build definitions and rules</H4>

View File

@@ -9,13 +9,59 @@
<body lang="en">
<h1 align="center">EPICS Base Release 3.15.6</h1>
<p style="color:red">This version of EPICS Base has not been released yet.</p>
<h2 align="center">Changes made on the 3.15 branch since 3.15.5</h2>
<!-- Insert new items immediately below here ... -->
<h3>Unsetting environment variables</h3>
<p>The new command <code>epicsEnvUnset <i>varname</i></code> can be used to
unset an environment variable.</p>
<h3>Warning indicators in msi (and macLib) output</h3>
<p>The libCom macro expansion library has been modified so that when the
SUPPRESS_WARNINGS flag is set it will no longer include any <tt>,undefined</tt>
or <tt>,recursive</tt> indicators in its output when undefined or recursive
macros are encountered. These indicators were harmless when the output was fed
into an IOC along with a definition for the macro, but when the <tt>msi</tt>
tool was used to generate other kinds of files they caused problems. If the
<tt>msi -V</tt> flag is used the markers will still be present in the output
whenever the appropriate condition is seen.</p>
<h3>Improvements to msi</h3>
<p>In addition to fixing its response to discovering parsing errors in its
substitution input file (reported as Launchpad
<a href="https://bugs.launchpad.net/epics-base/+bug/1503661">bug #1503661</a>)
so it now deletes the incomplete output file, the msi program has been cleaned
up a little bit internally.</p>
<h3>All array records now post monitors on their array-length fields</h3>
<p>The waveform record has been posting monitors on its NORD field since Base
3.15.0.1; we finally got around to doing the equivalent in all the other
built-in record types, which even required modifying device support in some
cases. This fixes <a href="https://bugs.launchpad.net/epics-base/+bug/1730727">
Launchpad bug #1730727</a>.</p>
<h3>HOWTO: Converting Wiki Record Reference to POD</h3>
<p>Some documentation has been added to the <tt>dbdToHtml.pl</tt> script
explaining how Perl POD (Plain Old Documentation) markup can be added to
<tt>.dbd</tt> files to generate HTML documentation for the record types. To see
these instructions, run <tt>perl&nbsp;bin/&lt;host&gt;/dbdToHtml.pl&nbsp;-H</tt>
or <tt>perldoc&nbsp;bin/&lt;host&gt;/dbdToHtml.pl</tt>.</p>
<h3>Fix problem with numeric soft events</h3>
<p>Changing from numeric to named soft events introduced an incompatibility
when a numeric event 1-255 is converted from a DOUBLE, e.g. from a calc record.
The <tt>post_event()</tt> API is not marked deprecated any more.
<p>Also <code>scanpel</code> has been modified to accept a glob pattern for
event name filtering and to show events with no connected records as well.</p>
<h3>Add osiSockOptMcastLoop_t and osiSockTest</h3>
<p>Added a new OS-independent typedef for multicast socket options, and a test
@@ -34,6 +80,114 @@ tells git to ignore all configure/*.local files.</p>
<!-- Insert inherited items immediately below here ... -->
<h3>Fix broken <tt>EPICS_IOC_LOG_FILE_LIMIT=0</tt> setting</h3>
<p>The Application Developers' Guide says this is allowed and disables the
limit on the log-file, but it hasn't actually worked for some time (if ever).
Note that the iocLogServer will be removed from newer Base release sometime
soon as its functionality can be implemented by other dedicated log servers
such as logstash or syslog-ng.</p>
<p>Fixes <a href="https://bugs.launchpad.net/bugs/1786858">lp:1786858</a>
and part of <a href="https://bugs.launchpad.net/bugs/1786966">lp:1786966</a>.
</p>
<h3>Cleanup of startup directory</h3>
<p>The files in the startup directory have not been maintained in recent years
and have grown crufty (technical term). This release includes the following
updates to these files:</p>
<ul>
<li>The Perl <tt>EpicsHostArch.pl</tt> script has been rewritten, and support
for a few previously missing host architectures has been added to it.</li>
<li>The <tt>EpicsHostArch.pl</tt> script has also been moved into the standard
<tt>src/tools</tt> directory, from where it will be installed into
<tt>lib/perl</tt>. In this new location it is no longer executable, so it must
be run by the <tt>perl</tt> executable.</li>
<li>The build system has been adjusted to look for <tt>EpicsHostArch.pl</tt> in
both places if the <tt>EPICS_HOST_ARCH</tt> environment variable has not been
set at build-time.</li>
<li>Sites that used the original Perl script to set <tt>EPICS_HOST_ARCH</tt> as
part of their standard environment will need to adjust their scripts when they
upgrade to this release.</li>
<li>The <tt>EpicsHostArch</tt> shell script has been replaced with a wrapper
routine that calls the Perl <tt>EpicsHostArch.pl</tt> script. Sites that rely on
this script to set <tt>EPICS_HOST_ARCH</tt> should consider switching to the
Perl script instead.</li>
<li>The <tt>Site.cshrc</tt> and <tt>Site.profile</tt> files have been renamed to
<tt>unix.csh</tt> and <tt>unix.sh</tt>, respectively.</li>
<li>The existing <tt>win32.bat</tt> file has been cleaned up and a new
<tt>windows.bat</tt> file added for 64-bit targets. The contents of these files
should be seen as examples, don't uncomment or install parts for software that
you don't explicitly know that you need.</li>
</ul>
<h3>Recent Apple XCode Build Issues</h3>
<p>The latest version of XCode will not compile calls to <tt>system()</tt> or
<tt>clock_settime()</tt> for iOS targets. There were several places in Base
where these were being compiled, although there were probably never called. The
code has now been modified to permit iOS builds to complete again.</p>
<h3>Prevent illegal alarm severities</h3>
<p>A check has been added to <tt>recGblResetAlarms()</tt> that prevents records
from getting an alarm severity higher than INVALID_ALARM. It is still possible
for a field like HSV to get set to a value that is not a legal alarm severity,
but the core IOC code should never copy such a value into a record's SEVR or
ACKS fields. With this fix the record's alarm severity will be limited to
INVALID_ALARM.</p>
<h3>Fixes for Launchpad bugs</h3>
<p>The following launchpad bugs have fixes included:</p>
<ul>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1786320">
lp: #1786320</a>, dbCa subscribes twice to ENUM</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/541221">
lp: #541221</a>, 'assert (pca->pgetNative)' failed in ../dbCa.c</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1747091">
lp: #1747091</a>, epicsTimeGetEvent() / generalTime bug</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1743076">
lp: #1743076</a>, Segfault in ca_attach_context() during exits</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1751380">
lp: #1751380</a>, Deadlock in ca_clear_subscription()</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1597809">
lp: #1597809</a>, Setting NAME field in DB file may break IOC</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1770292">
lp: #1770292</a>, get_alarm_double() inconsistent across record types</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1771298">
lp: #1771298</a>, Conversion of NaN to integer relies on undefined
behavior</li>
</ul>
<h3>Updated VxWorks Timezone settings</h3>
<p>Removed the settings for 2017; fixed the hour of the change for MET.</p>
<h3>Fixed camonitor server side relative timestamps bug</h3>
<p>Initialize the first time-stamp from the first monitor, not the client-side
current time in this configuration.</p>
<h3>Build changes for MSVC</h3>
<p>Windows builds using Visual Studio 2015 and later now use the <tt>-FS</tt>
compiler option to allow parallel builds to work properly.</p>
<p>We now give the <tt>-FC</tt> option to tell the compiler to print absolute
paths for source files in diagnostic messages.</p>
<h3>Extend maximum Posix epicsEventWaitWithTimeout() delay</h3>
<p>The Posix implementation of epicsEventWaitWithTimeout() was limiting the

View File

@@ -91,7 +91,7 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Set the Feature Freeze date, by which time all Bazaar commits for
<td>Set the Feature Freeze date, by which time all Git commits for
enhancements and new functionality should have been completed. After
this date, commits should only be made to fix problems that show up
during testing.</td>
@@ -133,7 +133,7 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the module in Bazaar, using these tag conventions:
<td>Tag the module in Git, using these tag conventions:
<ul>
<li>
<tt>R3.15.6-pre1</tt>
@@ -145,23 +145,20 @@ relevent roles unless the Release Manager designates otherwise:</p>
</li>
</ul>
<blockquote><tt>
cd ~/base/mirror-3.15<br />
bzr tag R3.15.6-rc1
cd base-3.15<br />
git tag -m 'RL: Tagged for 3.15.6-rc1' R3.15.6-rc1
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Export the tagged version into a tarfile. Note that this command
generates a gzipped tarfile directly from the repository:
<td>Export the tagged version into a tarfile. The <tt>make-tar.sh</tt>
script generates a gzipped tarfile directly from the tag, excluding the
files and directories that are only used for continuous integration:
<blockquote><tt>
cd ~/base<br />
bzr export
--root=base-3.15.6-rc1
-r tag:R3.15.6-rc1
base-3.15.6-rc1.tar.gz
mirror-3.15
cd base-3.15<br />
git archive --prefix=base-3.15.6-rc1/ --output=base-3.15.6-rc1.tar.gz R3.15.6-rc1 configure documentation LICENSE Makefile README src startup
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
@@ -274,10 +271,10 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the module in Bazaar:
<td>Tag the module in Git:
<blockquote><tt>
cd ~/base/mirror-3.15<br />
bzr tag R3.15.6</i>
cd base-3.15<br />
git tag -m 'RL: Tagged for 3.15.6' R3.15.6
</tt></blockquote>
</td>
</tr>
@@ -287,12 +284,8 @@ relevent roles unless the Release Manager designates otherwise:</p>
<td>Export the tagged version into a tarfile. Note that this command
generates a gzipped tarfile directly from the repository:
<blockquote><tt>
cd ~/base<br />
bzr export
--root=base-3.15.6
-r tag:R3.15.6
base-3.15.6.tar.gz
mirror-3.15
cd base-3.15<br />
git archive --prefix=base-3.15.6/ --output=base-3.15.6.tar.gz R3.15.6 configure documentation LICENSE Makefile README src startup
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>

View File

@@ -1009,7 +1009,7 @@ d:/user/epics/base-3.15/lib/win32-x86/Com.lib</code></p>
<h2><a name="CommandUtils">Command Line Utilities</a></h2>
<h3><a name="acctst">acctst</a></h3>
<pre>acctst &lt;PV name&gt; [progress logging level] [channel duplication count]
<pre>acctst &lt;PV name&gt; [progress logging level] [channel duplication count]
[test repetition count] [enable preemptive callback]</pre>
<h4>Description</h4>
@@ -2079,7 +2079,7 @@ example, be beneficial when tuning an archiver installation.</p>
<p>Significant performance gains can be realized when the CA client library
doesn't wait for a response to return from the server after each request. All
requests which require interaction with a CA server are accumulated (buffered)
and not forwarded to the IOC until one of <code>ca_flush_io()</code>,
and not forwarded to the IOC until one of <code>ca_flush_io()</code>,
<code>ca_pend_io()</code>, <code>ca_pend_event()</code>, or
<code>ca_sg_block()</code> are called allowing several operations to be
efficiently sent over the network together. Any process variable values written
@@ -2103,16 +2103,16 @@ shouldn't test the success of a CA function call by checking to see if the
returned value is zero as is the UNIX convention. Below are several methods to
test CA function returns. See <a href="#ca_signal"><code>ca_signal()</code> and
<code>SEVCHK()</code></a> for more information on this topic.</p>
<pre>status = ca_XXXX();
SEVCHK( status, "ca_XXXX() returned failure status");
<pre>status = ca_XXXX();
SEVCHK( status, "ca_XXXX() returned failure status");
if ( status &amp; CA_M_SUCCESS ) {
printf ( "The requested ca_XXXX() operation didn't complete successfully");
}
if ( status &amp; CA_M_SUCCESS ) {
printf ( "The requested ca_XXXX() operation didn't complete successfully");
}
if ( status != ECA_NORMAL ) {
if ( status != ECA_NORMAL ) {
printf("The requested ca_XXXX() operation didn't complete successfully because \"%s\"\n",
ca_message ( status ) );
ca_message ( status ) );
}</pre>
<h3><a name="Channel">Channel Access Data Types</a></h3>
@@ -2285,7 +2285,7 @@ int main ( int argc, char ** argv )
unsigned nBytes;
unsigned elementCount;
char timeString[32];
unsigned i;
unsigned i;
chid chan;
double sum;
int status;
@@ -2328,7 +2328,7 @@ int main ( int argc, char ** argv )
epicsTimeToStrftime ( timeString, sizeof ( timeString ),
"%a %b %d %Y %H:%M:%S.%f", &amp; pTD-&gt;stamp );
printf ( "The sum of elements in %s at %s was %f\n",
printf ( "The sum of elements in %s at %s was %f\n",
argv[1], timeString, sum );
ca_clear_channel ( chan );
@@ -2359,7 +2359,7 @@ executing within the user's callback function.</p>
<pre>typedef struct event_handler_args {
void *usr; /* user argument supplied with request */
chanId chid; /* channel id */
long type; /* the type of the item returned */
long type; /* the type of the item returned */
long count; /* the element count of the item returned */
const void *dbr; /* a pointer to the item returned */
int status; /* ECA_XXX status of the requested op from the server */
@@ -2382,7 +2382,7 @@ attached to the request, an exception handler is executed in the client. The
default exception handler prints a message on the console and exits if the
exception condition is severe. Certain internal exceptions within the CA client
library, and failures detected by the SEVCHK macro may also cause the exception
handler to be invoked. To modify this behavior see
handler to be invoked. To modify this behavior see
<code><a href="#ca_add_exception_event">ca_add_exception_event</a>()</code>.</p>
<h3><a name="Server">Server and Client Share the Same Address Space on The Same
@@ -2674,6 +2674,14 @@ automatically released by the system when the process exits and
vxWorks or RTEMS no cleanup occurs unless the application calls
<code>ca_context_destroy()</code>.</p>
<p>Note: This operation blocks until any user callbacks for any channel
created in the current context have run to completion. If callbacks take a
lock (mutex) then it is the user's responsibility to ensure that this lock
is not held when <code>ca_clear_context()</code> is called, otherwise a
deadlock may ensue. (See also
<code><a href="#ca_clear_channel">ca_clear_channel</a>()</code> and
<code><a href="#ca_clear_event">ca_clear_subscription</a>()</code>.)</p>
<h4>Returns</h4>
<p>ECA_NORMAL - Normal successful completion</p>
@@ -2819,6 +2827,12 @@ efficiently sent over the network in one message.</p>
clearing a channel does shutdown and reclaim any channel state change event
subscriptions (monitors) registered with the channel.</p>
<p>Note: This operation blocks until any user callbacks for this channel
have run to completion. If callbacks take a lock (mutex) then it is the
user's responsibility to ensure that this lock is not held when
<code>ca_clear_channel()</code> is called, otherwise a deadlock may ensue.
(See also <code><a href="#ca_clear_event">ca_clear_subscription</a>()</code>.)</p>
<h4>Arguments</h4>
<dl>
<dt><code>CHID</code></dt>
@@ -2833,16 +2847,16 @@ subscriptions (monitors) registered with the channel.</p>
<h3><code><a name="ca_put">ca_put()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
int ca_put ( chtype TYPE,
chid CHID, void *PVALUE );
int ca_array_put ( chtype TYPE, unsigned long COUNT,
int ca_put ( chtype TYPE,
chid CHID, void *PVALUE );
int ca_array_put ( chtype TYPE, unsigned long COUNT,
chid CHID, const void *PVALUE);
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
int ca_put_callback ( chtype TYPE,
chid CHID, const void *PVALUE,
caEventCallBackFunc PFUNC, void *USERARG );
int ca_array_put_callback ( chtype TYPE, unsigned long COUNT,
chid CHID, const void *PVALUE,
int ca_put_callback ( chtype TYPE,
chid CHID, const void *PVALUE,
caEventCallBackFunc PFUNC, void *USERARG );
int ca_array_put_callback ( chtype TYPE, unsigned long COUNT,
chid CHID, const void *PVALUE,
caEventCallBackFunc PFUNC, void *USERARG );</pre>
<h4>Description</h4>
@@ -3069,7 +3083,7 @@ when a CA get request is initiated.</p>
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
int ca_create_subscription ( chtype TYPE, unsigned long COUNT,
chid CHID, unsigned long MASK,
caEventCallBackFunc USERFUNC, void *USERARG,
caEventCallBackFunc USERFUNC, void *USERARG,
evid *PEVID );</pre>
<h4>Description</h4>
@@ -3153,7 +3167,7 @@ indicating the current state of the channel.</p>
<dt><code>MASK</code></dt>
<dd>A mask with bits set for each of the event trigger types requested. The
event trigger mask must be a <em>bitwise or</em> of one or more of the
following constants.
following constants.
<ul>
<li>DBE_VALUE - Trigger events when the channel value exceeds the
monitor dead band</li>
@@ -3200,6 +3214,13 @@ and not forwarded to the server until one of <code>ca_flush_io()</code>, <code>c
<code>ca_pend_event()</code>, or <code>ca_sg_block()</code> are called. This allows several requests to be
efficiently sent together in one message.</p>
<p>Note: This operation blocks until any user callbacks for this channel
have run to completion. If callbacks take a lock (mutex) then it is the
user's responsibility to ensure that this lock is not held when
<code>ca_clear_subscription()</code> is called, otherwise a deadlock may
ensue. (See also <code><a
href="#ca_clear_channel">ca_clear_channel</a>()</code>.)</p>
<h4>Arguments</h4>
<dl>
<dt>EVID</dt>
@@ -3364,7 +3385,7 @@ becomes full.</p>
<h3><code><a name="ca_signal">ca_signal()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
int ca_signal ( long CA_STATUS, const char * CONTEXT_STRING );
int ca_signal ( long CA_STATUS, const char * CONTEXT_STRING );
void SEVCHK( CA_STATUS, CONTEXT_STRING );</pre>
<h4>Description</h4>
@@ -3381,7 +3402,7 @@ recommended error handler for simple applications which do not wish to write
code testing the status returned from each channel access call.</p>
<h4>Examples</h4>
<pre>status = ca_context_create (...);
<pre>status = ca_context_create (...);
SEVCHK ( status, "Unable to create a CA client context" );</pre>
<p>If the application only wishes to print the message associated with an error
@@ -3405,7 +3426,7 @@ this purpose.</p>
<h3><code><a
name="ca_add_exception_event">ca_add_exception_event()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
<pre>#include &lt;cadef.h&gt;
typedef void (*pCallback) ( struct exception_handler_args HANDLERARGS );
int ca_add_exception_event ( pCallback USERFUNC, void *USERARG );</pre>
@@ -3614,7 +3635,7 @@ specified channel.</p>
<dt><code>PFUNC</code></dt>
<dd>Pointer to a user supplied callback function. A null pointer uninstalls
the current handler. The following arguments are passed <em>by value</em>
to the supplied callback handler.
to the supplied callback handler.
<pre>typedef struct ca_access_rights {
unsigned read_access:1;
unsigned write_access:1;
@@ -3954,8 +3975,8 @@ type.</p>
prints diagnostics to standard out.</p>
<h4>Examples</h4>
<pre>void ca_test_event ();
status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL );
<pre>void ca_test_event ();
status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL );
SEVCHK ( status, .... );</pre>
<h4>See Also</h4>
@@ -3989,8 +4010,8 @@ outstanding within them at any given time.</p>
</dl>
<h4>Examples</h4>
<pre>CA_SYNC_GID gid;
status = ca_sg_create ( &amp;gid );
<pre>CA_SYNC_GID gid;
status = ca_sg_create ( &amp;gid );
SEVCHK ( status, Sync group create failed );</pre>
<h4>Returns</h4>
@@ -4028,8 +4049,8 @@ int ca_sg_delete ( CA_SYNC_GID GID );</pre>
</dl>
<h4>Examples</h4>
<pre>CA_SYNC_GID gid;
status = ca_sg_delete ( gid );
<pre>CA_SYNC_GID gid;
status = ca_sg_delete ( gid );
SEVCHK ( status, Sync group delete failed );</pre>
<h4>Returns</h4>
@@ -4140,7 +4161,7 @@ will not block unless additional subsequent requests are made.</p>
</dl>
<h4>Examples</h4>
<pre>CA_SYNC_GID gid;
<pre>CA_SYNC_GID gid;
status = ca_sg_reset(gid);</pre>
<h4>Returns</h4>
@@ -4153,7 +4174,7 @@ status = ca_sg_reset(gid);</pre>
<pre>#include &lt;cadef.h&gt;
int ca_sg_put ( CA_SYNC_GID GID, chtype TYPE,
chid CHID, void *PVALUE );
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
unsigned long COUNT, chid CHID, void *PVALUE );</pre>
<p>Write a value, or array of values, to a channel and increment the outstanding
@@ -4294,7 +4315,7 @@ reissued.</p>
<h3><code><a name="ca_client_status">ca_client_status()</a></code></h3>
<pre>int ca_client_status ( unsigned level );
int ca_context_status ( struct ca_client_context *CONTEXT,
int ca_context_status ( struct ca_client_context *CONTEXT,
unsigned LEVEL );</pre>
<h4>Description</h4>

View File

@@ -127,21 +127,10 @@ const char * ca_message_text []
static epicsThreadOnceId caClientContextIdOnce = EPICS_THREAD_ONCE_INIT;
extern "C" void ca_client_exit_handler (void *)
{
if ( caClientContextId ) {
epicsThreadPrivateDelete ( caClientContextId );
caClientContextId = 0;
}
}
// runs once only for each process
extern "C" void ca_init_client_context ( void * )
{
caClientContextId = epicsThreadPrivateCreate ();
if ( caClientContextId ) {
epicsAtExit ( ca_client_exit_handler,0 );
}
}
/*

View File

@@ -390,7 +390,7 @@ int epicsShareAPI ca_array_get_callback ( chtype type,
{
caStatus = ECA_ALLOCMEM;
}
catch ( cacChannel::msgBodyCacheTooSmall ) {
catch ( cacChannel::msgBodyCacheTooSmall & ) {
caStatus = ECA_TOLARGE;
}
catch ( ... )

View File

@@ -652,7 +652,7 @@ not follow this pattern, but are still printable strings.
=item [1] R3.15 Channel Access Reference Manual by Jeffrey O. Hill
L<http://www.aps.anl.gov/epics/base/R3-15/2-docs/CAref.html>
L<https://epics.anl.gov/base/R3-15/5-docs/CAref.html>
=back

View File

@@ -58,7 +58,7 @@ Cap5_LIBS = ca Com
Cap5_INCLUDES = -I$(shell $(PERL) ../perlConfig.pl archlib)/CORE
Cap5_CFLAGS = $(shell $(PERL) ../perlConfig.pl ccflags)
CLEANS += Cap5.c pod2htmd.tmp pod2htmi.tmp
CLEANS += Cap5.c
include $(TOP)/configure/RULES

View File

@@ -140,6 +140,10 @@ sub display {
printf " Lo ctrl limit: %g\n", $data->{lower_ctrl_limit};
printf " Hi ctrl limit: %g\n", $data->{upper_ctrl_limit};
}
if (exists $data->{ackt}) {
printf " Ack transients: %s\n", $data->{ackt} ? 'YES' : 'NO';
printf " Ack severity: %s\n", $data->{acks};
}
} else {
my $value = format_number($data, $type);
if ($opt_t) {

View File

@@ -8,7 +8,7 @@
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -419,7 +419,7 @@ int main (int argc, char *argv[])
if (argc > optind+1) {
for (i = optind + 1; i < argc; i++) {
strcat(cbuf, " ");
strcat(cbuf, argv[i]);
strcat(cbuf, argv[i]);
}
}
@@ -530,6 +530,11 @@ int main (int argc, char *argv[])
/* Use standard put with defined timeout */
result = ca_array_put (dbrType, count, pvs[0].chid, pbuf);
}
if (result != ECA_NORMAL) {
fprintf(stderr, "Error from put operation: %s\n", ca_message(result));
return 1;
}
result = ca_pend_io(caTimeout);
if (result == ECA_TIMEOUT) {
fprintf(stderr, "Write operation timed out: Data was not written.\n");
@@ -545,7 +550,7 @@ int main (int argc, char *argv[])
}
if (result != ECA_NORMAL) {
fprintf(stderr, "Error occured writing data.\n");
fprintf(stderr, "Error occured writing data: %s\n", ca_message(result));
return 1;
}

View File

@@ -414,6 +414,12 @@ char *dbr2str (const void *value, unsigned type)
ptsNewS = &((struct TYPE *)value)->stamp; \
ptsNewC = &tsNow; \
\
if (!tsInitS) \
{ \
tsFirst = *ptsNewS; \
tsInitS = 1; \
} \
\
switch (tsType) { \
case relative: \
ptsRefC = &tsStart; \
@@ -506,12 +512,6 @@ void print_time_val_sts (pv* pv, unsigned long reqElems)
epicsTimeGetCurrent(&tsNow);
epicsTimeToStrftime(timeText, TIMETEXTLEN, timeFormatStr, &tsNow);
if (!tsInitS)
{
tsFirst = tsNow;
tsInitS = 1;
}
if (pv->nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name);
else printf("%s", pv->name);
printf("%c", fieldSeparator);

View File

@@ -644,6 +644,11 @@ caStatus casDGClient::processDG ()
if ( status != S_cas_success ) {
break;
}
if ( this->in.bytesPresent () > 0 && dgInBytesConsumed == 0 && status == S_cas_success ) {
this->in.removeMsg ( this->in.bytesPresent() );
}
}
return status;
}

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
@@ -26,33 +26,39 @@
#include "casAsyncIOI.h"
#include "casMonitor.h"
casPVI::casPVI ( casPV & intf ) :
pCAS ( NULL ), pPV ( & intf ), nMonAttached ( 0u ),
// Use casErrMessage instead of errMessage to show PV name
#define casErrMessage(S, PM) \
errPrintf(S, __FILE__, __LINE__, ", %s, %s", getName(), PM)
casPVI::casPVI ( casPV & intf ) :
pCAS ( NULL ), pPV ( & intf ), nMonAttached ( 0u ),
nIOAttached ( 0u ), deletePending ( false ) {}
casPVI::~casPVI ()
{
//
// all channels should have been destroyed
// (otherwise the server tool is yanking the
//
// all channels should have been destroyed
// (otherwise the server tool is yanking the
// PV out from under the server)
//
casVerify ( this->chanList.count() == 0u );
//
casVerify ( this->chanList.count() == 0u );
//
// all outstanding IO should have been deleted
// when we destroyed the channels
//
casVerify ( this->nIOAttached == 0u );
//
// all outstanding IO should have been deleted
// when we destroyed the channels
//
casVerify ( this->nIOAttached == 0u );
if ( this->nIOAttached ) {
errlogPrintf ( "The number of IO objected attached is %u\n", this->nIOAttached );
errlogPrintf ( "%u IO objects still attached in destructor\n",
this->nIOAttached );
}
//
// all monitors should have been deleted
// when we destroyed the channels
//
casVerify ( this->nMonAttached == 0u );
//
// all monitors should have been deleted
// when we destroyed the channels
//
casVerify ( this->nMonAttached == 0u );
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -139,26 +145,26 @@ caStatus casPVI::attachToServer ( caServerI & cas )
caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn )
{
epicsGuard < epicsMutex > guard ( this->mutex );
//
// create a gdd with the "enum string table" application type
//
// gddArray(int app, aitEnum prim, int dimen, ...);
gdd * pTmp = new gddScalar ( gddAppType_enums );
if ( pTmp == NULL ) {
errMessage ( S_cas_noMemory,
casErrMessage ( S_cas_noMemory,
"unable to create gdd for read of application type \"enums\" string"
" conversion table for enumerated PV" );
return S_cas_noMemory;
}
caStatus status = convertContainerMemberToAtomic ( *pTmp,
caStatus status = convertContainerMemberToAtomic ( *pTmp,
gddAppType_enums, MAX_ENUM_STATES );
if ( status != S_cas_success ) {
pTmp->unreference ();
errMessage ( status,
"unable to to config gdd for read of application type \"enums\" string"
" conversion table for enumerated PV");
casErrMessage ( status,
"unable to config gdd for read of application type \"enums\" string"
" conversion table for enumerated PV" );
return status;
}
@@ -169,12 +175,11 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn )
if ( status == S_cas_success ) {
updateEnumStringTableAsyncCompletion ( *pTmp );
}
else if ( status != S_casApp_asyncCompletion &&
else if ( status != S_casApp_asyncCompletion &&
status != S_casApp_postponeAsyncIO ) {
errPrintf ( status, __FILE__, __LINE__,
"- unable to read application type \"enums\" "
" (string conversion table) from enumerated native type PV \"%s\"",
this->getName() );
casErrMessage ( status,
"unable to read application type \"enums\" "
" (string conversion table) from enumerated native type PV" );
}
pTmp->unreference ();
@@ -185,40 +190,39 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn )
void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
{
epicsGuard < epicsMutex > guard ( this->mutex );
if ( resp.isContainer() ) {
errMessage ( S_cas_badType,
"application type \"enums\" string conversion table for"
" enumerated PV was a container (expected vector of strings)" );
casErrMessage ( S_cas_badType,
"Invalid \"enums\" string conversion table for"
" enumerated PV (container instead of vector of strings)" );
return;
}
if ( resp.dimension() == 0 ) {
if ( resp.primitiveType() == aitEnumString ) {
aitString *pStr = (aitString *) resp.dataVoid ();
if ( ! this->enumStrTbl.setString ( 0, pStr->string() ) ) {
errMessage ( S_cas_noMemory,
casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
else if ( resp.primitiveType() == aitEnumFixedString ) {
aitFixedString *pStr = (aitFixedString *) resp.dataVoid ();
if ( ! this->enumStrTbl.setString ( 0, pStr->fixed_string ) ) {
errMessage ( S_cas_noMemory,
casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
else {
errPrintf ( S_cas_badType, __FILE__, __LINE__,
casErrMessage ( S_cas_badType,
"application type \"enums\" string conversion"
" table for enumerated PV \"%s\" isnt a string type?",
getName() );
" table for enumerated PV isnt a string type?" );
}
}
else if ( resp.dimension() == 1 ) {
gddStatus gdd_status;
aitIndex index, first, count;
gdd_status = resp.getBound ( 0, first, count );
assert ( gdd_status == 0 );
@@ -232,7 +236,7 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
aitString *pStr = (aitString *) resp.dataVoid ();
for ( index = 0; index<count; index++ ) {
if ( ! this->enumStrTbl.setString ( index, pStr[index].string() ) ) {
errMessage ( S_cas_noMemory,
casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
@@ -241,19 +245,18 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
aitFixedString *pStr = (aitFixedString *) resp.dataVoid ();
for ( index = 0; index < count; index++ ) {
if ( ! this->enumStrTbl.setString ( index, pStr[index].fixed_string ) ) {
errMessage ( S_cas_noMemory,
casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
}
else {
errMessage ( S_cas_badType,
"application type \"enums\" string conversion"
" table for enumerated PV isnt a string type?" );
casErrMessage( S_cas_badType,
"bad \"enums\" string conversion table for enumerated PV" );
}
}
else {
errMessage ( S_cas_badType,
casErrMessage ( S_cas_badType,
"application type \"enums\" string conversion table"
" for enumerated PV was multi-dimensional"
" (expected vector of strings)" );
@@ -287,7 +290,7 @@ void casPVI::postEvent ( const casEventMask & select, const gdd & event )
}
}
caStatus casPVI::installMonitor (
caStatus casPVI::installMonitor (
casMonitor & mon, tsDLList < casMonitor > & monitorList )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -303,14 +306,14 @@ caStatus casPVI::installMonitor (
}
}
casMonitor * casPVI::removeMonitor (
casMonitor * casPVI::removeMonitor (
tsDLList < casMonitor > & list, ca_uint32_t clientIdIn )
{
epicsGuard < epicsMutex > guard ( this->mutex );
casMonitor * pMon = 0;
//
// (it is reasonable to do a linear search here because
// sane clients will require only one or two monitors
// sane clients will require only one or two monitors
// per channel)
//
tsDLIter < casMonitor > iter = list.firstIter ();
@@ -359,9 +362,9 @@ void casPVI::installChannel ( chanIntfForPV & chan )
epicsGuard < epicsMutex > guard ( this->mutex );
this->chanList.add ( chan );
}
void casPVI::removeChannel (
chanIntfForPV & chan, tsDLList < casMonitor > & src,
void casPVI::removeChannel (
chanIntfForPV & chan, tsDLList < casMonitor > & src,
tsDLList < casMonitor > & dest )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -380,8 +383,8 @@ void casPVI::clearOutstandingReads ( tsDLList < casAsyncIOI > & ioList )
{
epicsGuard < epicsMutex > guard ( this->mutex );
// cancel any pending asynchronous IO
tsDLIter < casAsyncIOI > iterIO =
// cancel any pending asynchronous IO
tsDLIter < casAsyncIOI > iterIO =
ioList.firstIter ();
while ( iterIO.valid () ) {
tsDLIter < casAsyncIOI > tmp = iterIO;
@@ -407,7 +410,7 @@ void casPVI::destroyAllIO ( tsDLList < casAsyncIOI > & ioList )
}
}
void casPVI::installIO (
void casPVI::installIO (
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -416,7 +419,7 @@ void casPVI::installIO (
this->nIOAttached++;
}
void casPVI::uninstallIO (
void casPVI::uninstallIO (
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
{
{
@@ -517,8 +520,8 @@ aitEnum casPVI::bestExternalType () const
}
}
// CA only does 1D arrays for now
aitIndex casPVI::nativeCount ()
// CA only does 1D arrays for now
aitIndex casPVI::nativeCount ()
{
epicsGuard < epicsMutex > guard ( this->mutex );
if ( this->pPV ) {
@@ -542,4 +545,3 @@ const char * casPVI::getName () const
return "<disconnected>";
}
}

View File

@@ -46,6 +46,7 @@
#include "epicsExport.h"
#include "link.h"
#include "recSup.h"
#include "dbUnitTest.h" /* for testSyncCallback() */
static int callbackQueueSize = 2000;
@@ -353,3 +354,86 @@ void callbackRequestProcessCallbackDelayed(CALLBACK *pcallback,
callbackSetProcess(pcallback, Priority, pRec);
callbackRequestDelayed(pcallback, seconds);
}
/* Sync. process of testSyncCallback()
*
* 1. For each priority, make a call to callbackRequest() for each worker.
* 2. Wait until all callbacks are concurrently being executed
* 3. Last worker to begin executing signals success and begins waking up other workers
* 4. Last worker to wake signals testSyncCallback() to complete
*/
typedef struct {
epicsEventId wait_phase2, wait_phase4;
int nphase2, nphase3;
epicsCallback cb;
} sync_helper;
static void sync_callback(epicsCallback *cb)
{
sync_helper *helper;
callbackGetUser(helper, cb);
testGlobalLock();
assert(helper->nphase2 > 0);
if(--helper->nphase2!=0) {
/* we are _not_ the last to start. */
testGlobalUnlock();
epicsEventMustWait(helper->wait_phase2);
testGlobalLock();
}
/* we are either the last to start, or have been
* woken by the same and must pass the wakeup along
*/
epicsEventMustTrigger(helper->wait_phase2);
assert(helper->nphase2 == 0);
assert(helper->nphase3 > 0);
if(--helper->nphase3==0) {
/* we are the last to wake up. wake up testSyncCallback() */
epicsEventMustTrigger(helper->wait_phase4);
}
testGlobalUnlock();
}
void testSyncCallback(void)
{
sync_helper helper[NUM_CALLBACK_PRIORITIES];
unsigned i;
testDiag("Begin testSyncCallback()");
for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) {
helper[i].wait_phase2 = epicsEventMustCreate(epicsEventEmpty);
helper[i].wait_phase4 = epicsEventMustCreate(epicsEventEmpty);
/* no real need to lock here, but do so anyway so that valgrind can establish
* the locking requirements for sync_helper.
*/
testGlobalLock();
helper[i].nphase2 = helper[i].nphase3 = callbackQueue[i].threadsRunning;
testGlobalUnlock();
callbackSetUser(&helper[i], &helper[i].cb);
callbackSetPriority(i, &helper[i].cb);
callbackSetCallback(sync_callback, &helper[i].cb);
callbackRequest(&helper[i].cb);
}
for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) {
epicsEventMustWait(helper[i].wait_phase4);
}
for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) {
testGlobalLock();
epicsEventDestroy(helper[i].wait_phase2);
epicsEventDestroy(helper[i].wait_phase4);
testGlobalUnlock();
}
testDiag("Complete testSyncCallback()");
}

View File

@@ -42,7 +42,9 @@ typedef struct callbackPvt {
int priority;
void *user; /*for use by callback user*/
void *timer; /*for use by callback itself*/
}CALLBACK;
}epicsCallback;
typedef epicsCallback CALLBACK;
typedef void (*CALLBACKFUNC)(struct callbackPvt*);

View File

@@ -291,10 +291,14 @@ static void get_alarm(DBADDR *paddr, char **ppbuffer,
if (*options & DBR_AL_LONG) {
struct dbr_alLong *pal = (struct dbr_alLong*) pbuffer;
pal->upper_alarm_limit = (epicsInt32) ald.upper_alarm_limit;
pal->upper_warning_limit = (epicsInt32) ald.upper_warning_limit;
pal->lower_warning_limit = (epicsInt32) ald.lower_warning_limit;
pal->lower_alarm_limit = (epicsInt32) ald.lower_alarm_limit;
pal->upper_alarm_limit = finite(ald.upper_alarm_limit) ?
(epicsInt32) ald.upper_alarm_limit : 0;
pal->upper_warning_limit = finite(ald.upper_warning_limit) ?
(epicsInt32) ald.upper_warning_limit : 0;
pal->lower_warning_limit = finite(ald.lower_warning_limit) ?
(epicsInt32) ald.lower_warning_limit : 0;
pal->lower_alarm_limit = finite(ald.lower_alarm_limit) ?
(epicsInt32) ald.lower_alarm_limit : 0;
if (no_data)
*options ^= DBR_AL_LONG; /*Turn off option*/

View File

@@ -410,7 +410,7 @@ long dbd(const char *record_name)
precord = addr.precord;
if (! precord->bkpt & BKPT_ON_MASK) {
if (!(precord->bkpt & BKPT_ON_MASK)) {
printf(" BKPT> No breakpoint set in this record\n");
return(S_db_bkptNotSet);
}

View File

@@ -649,11 +649,16 @@ static void connectionCallback(struct connection_handler_args arg)
if (pca->gotFirstConnection) {
if (pca->nelements != ca_element_count(arg.chid) ||
pca->dbrType != ca_field_type(arg.chid)) {
/* BUG: We have no way to clear any old subscription with the
* originally chosen data type/size. That will continue
* to send us data and will result in an assert() fail.
*/
/* Let next dbCaGetLink and/or dbCaPutLink determine options */
/* Size or type changed, clear everything and let the next call
to dbCaGetLink() and/or dbCaPutLink() reset everything */
if (pca->evidNative) {
ca_clear_event(pca->evidNative);
pca->evidNative = 0;
}
if (pca->evidString) {
ca_clear_event(pca->evidString);
pca->evidString = 0;
}
plink->value.pv_link.pvlMask &=
~(pvlOptInpNative | pvlOptInpString |
pvlOptOutNative | pvlOptOutString);
@@ -701,6 +706,7 @@ static void eventCallback(struct event_handler_args arg)
struct dbr_time_double *pdbr_time_double;
dbCaCallback monitor = 0;
void *userPvt = 0;
int doScan = 1;
assert(pca);
epicsMutexMustLock(pca->lock);
@@ -729,10 +735,13 @@ static void eventCallback(struct event_handler_args arg)
memcpy(pca->pgetString, dbr_value_ptr(arg.dbr, arg.type), size);
pca->gotInString = TRUE;
} else switch (arg.type){
case DBR_TIME_ENUM:
/* Disable the record scan if we also have a string monitor */
doScan = !(plink->value.pv_link.pvlMask & pvlOptInpString);
/* fall through */
case DBR_TIME_STRING:
case DBR_TIME_SHORT:
case DBR_TIME_FLOAT:
case DBR_TIME_ENUM:
case DBR_TIME_CHAR:
case DBR_TIME_LONG:
case DBR_TIME_DOUBLE:
@@ -748,7 +757,7 @@ static void eventCallback(struct event_handler_args arg)
pca->sevr = pdbr_time_double->severity;
pca->stat = pdbr_time_double->status;
memcpy(&pca->timeStamp, &pdbr_time_double->stamp, sizeof(epicsTimeStamp));
if (precord) {
if (doScan && precord) {
struct pv_link *ppv_link = &plink->value.pv_link;
if ((ppv_link->pvlMask & pvlOptCP) ||
@@ -1005,7 +1014,8 @@ static void dbCaTask(void *arg)
status = ca_add_array_event(
ca_field_type(pca->chid)+DBR_TIME_STRING,
ca_element_count(pca->chid),
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0);
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
&pca->evidNative);
if (status != ECA_NORMAL) {
errlogPrintf("dbCaTask ca_add_array_event %s\n",
ca_message(status));
@@ -1017,7 +1027,8 @@ static void dbCaTask(void *arg)
pca->pgetString = dbCalloc(1, MAX_STRING_SIZE);
epicsMutexUnlock(pca->lock);
status = ca_add_array_event(DBR_TIME_STRING, 1,
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0);
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
&pca->evidString);
if (status != ECA_NORMAL) {
errlogPrintf("dbCaTask ca_add_array_event %s\n",
ca_message(status));

View File

@@ -78,6 +78,8 @@ typedef struct caLink
char *pgetString;
void *pputNative;
char *pputString;
evid evidNative;
evid evidString;
char gotInNative;
char gotInString;
char gotOutNative;

View File

@@ -117,6 +117,8 @@ static char *EVENT_PEND_NAME = "eventTask";
static struct evSubscrip canceledEvent;
static epicsMutexId stopSync;
static unsigned short ringSpace ( const struct event_que *pevq )
{
if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) {
@@ -258,6 +260,10 @@ dbEventCtx db_init_events (void)
{
struct event_user * evUser;
if (!stopSync) {
stopSync = epicsMutexMustCreate();
}
if (!dbevEventUserFreeList) {
freeListInitPvt(&dbevEventUserFreeList,
sizeof(struct event_user),8);
@@ -321,6 +327,8 @@ fail:
return NULL;
}
/* intentionally leak stopSync to avoid possible shutdown races */
/*
* DB_CLOSE_EVENTS()
*
@@ -356,11 +364,15 @@ void db_close_events (dbEventCtx ctx)
epicsMutexUnlock ( evUser->lock );
epicsMutexMustLock (stopSync);
epicsEventDestroy(evUser->pexitsem);
epicsEventDestroy(evUser->ppendsem);
epicsEventDestroy(evUser->pflush_sem);
epicsMutexDestroy(evUser->lock);
epicsMutexUnlock (stopSync);
freeListFree(dbevEventUserFreeList, evUser);
}
@@ -1043,8 +1055,15 @@ static void event_task (void *pParm)
taskwdRemove(epicsThreadGetIdSelf());
/* use stopSync to ensure pexitsem is not destroy'd
* until epicsEventSignal() has returned.
*/
epicsMutexMustLock (stopSync);
epicsEventSignal(evUser->pexitsem);
epicsMutexUnlock(stopSync);
return;
}

View File

@@ -651,7 +651,7 @@ long dbGetLink(struct link *plink, short dbrType, void *pbuffer,
inherit_severity(&plink->value.pv_link, precord, stat, sevr);
break;
default:
cantProceed("dbGetLinkValue: Illegal link type %d\n", plink->type);
printf("dbGetLinkValue: Illegal link type %d\n", plink->type);
status = -1;
}
if (status) {
@@ -755,7 +755,7 @@ long dbPutLink(struct link *plink, short dbrType, const void *pbuffer,
status = dbCaPutLink(plink, dbrType, pbuffer, nRequest);
break;
default:
cantProceed("dbPutLinkValue: Illegal link type %d\n", plink->type);
printf("dbPutLinkValue: Illegal link type %d\n", plink->type);
status = -1;
}
if (status) {
@@ -836,4 +836,3 @@ long dbPutLinkLS(struct link *plink, char *pbuffer, epicsUInt32 len)
return dbPutLink(plink, DBR_STRING, pbuffer, 1);
}

View File

@@ -552,10 +552,10 @@ long dblsr(char *recordname,int level)
printf(" Not Locked\n");
} else {
printf(" thread %p",plockSet->thread_id);
if(! plockSet->precord || !plockSet->precord->name)
printf(" NULL record or record name\n");
if(! plockSet->precord)
printf(" NULL record\n");
else
printf(" record %s\n",plockSet->precord->name);
printf(" record %s\n",plockSet->precord->name);
}
if(level==0) { if(recordname) break; continue; }
for(plockRecord = (lockRecord *)ellFirst(&plockSet->lockRecordList);

View File

@@ -6,7 +6,7 @@
* Copyright (c) 2013 Helmholtz-Zentrum Berlin
* für Materialien und Energie GmbH.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbScan.c */
/* tasks and subroutines to scan the database */
@@ -111,8 +111,8 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = {
typedef struct event_list {
CALLBACK callback[NUM_CALLBACK_PRIORITIES];
scan_list scan_list[NUM_CALLBACK_PRIORITIES];
struct event_list *next;
char event_name[MAX_STRING_SIZE];
struct event_list *next;
char eventname[1]; /* actually arbitrary size */
} event_list;
static event_list * volatile pevent_list[256];
static epicsMutexId event_lock;
@@ -249,11 +249,6 @@ void scanAdd(struct dbCommon *precord)
event_list *pel;
eventname = precord->evnt;
if (strlen(eventname) >= MAX_STRING_SIZE) {
recGblRecordError(S_db_badField, (void *)precord,
"scanAdd: too long EVNT value");
return;
}
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
@@ -317,24 +312,17 @@ void scanDelete(struct dbCommon *precord)
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal SCAN value");
} else if (scan == menuScanEvent) {
char* eventname;
int prio;
event_list *pel;
scan_list *psl = 0;
eventname = precord->evnt;
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal PRIO field");
return;
}
do /* multithreading: make sure pel is consistent */
pel = pevent_list[0];
while (pel != pevent_list[0]);
for (; pel; pel=pel->next) {
if (strcmp(pel->event_name, eventname) == 0) break;
}
pel = eventNameToHandle(precord->evnt);
if (pel && (psl = &pel->scan_list[prio]))
deleteFromList(precord, psl);
} else if (scan == menuScanI_O_Intr) {
@@ -422,14 +410,12 @@ int scanpel(const char* eventname) /* print event list */
int prio;
event_list *pel;
do /* multithreading: make sure pel is consistent */
pel = pevent_list[0];
while (pel != pevent_list[0]);
for (; pel; pel = pel->next) {
if (!eventname || strcmp(pel->event_name, eventname) == 0) {
for (pel = pevent_list[0]; pel; pel = pel->next) {
if (!eventname || epicsStrGlobMatch(pel->eventname, eventname)) {
printf("Event \"%s\"\n", pel->eventname);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
if (ellCount(&pel->scan_list[prio].list) == 0) continue;
sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]);
sprintf(message, " Priority %s", priorityName[prio]);
printList(&pel->scan_list[prio], message);
}
}
@@ -480,18 +466,52 @@ event_list *eventNameToHandle(const char *eventname)
int prio;
event_list *pel;
static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
double eventnumber = 0;
size_t namelength;
if (!eventname || eventname[0] == 0)
return NULL;
if (!eventname) return NULL;
while (isspace((unsigned char)eventname[0])) eventname++;
if (!eventname[0]) return NULL;
namelength = strlen(eventname);
while (isspace((unsigned char)eventname[namelength-1])) namelength--;
/* Backward compatibility with numeric events:
Treat any string that represents a double with an
integer part between 0 and 255 the same as the integer
because it is most probably a conversion from double
like from a calc record.
*/
if (epicsParseDouble(eventname, &eventnumber, NULL) == 0)
{
if (eventnumber >= 0 && eventnumber < 256)
{
if (eventnumber < 1)
return NULL; /* 0 is no event */
if ((pel = pevent_list[(int)eventnumber]) != NULL)
return pel;
}
else
eventnumber = 0; /* not a numeric event between 1 and 255 */
}
epicsThreadOnce(&onceId, eventOnce, NULL);
epicsMutexMustLock(event_lock);
for (pel = pevent_list[0]; pel; pel=pel->next) {
if (strcmp(pel->event_name, eventname) == 0) break;
if (strncmp(pel->eventname, eventname, namelength) == 0
&& pel->eventname[namelength] == 0)
break;
}
if (pel == NULL) {
pel = dbCalloc(1, sizeof(event_list));
strcpy(pel->event_name, eventname);
pel = calloc(1, sizeof(event_list) + namelength);
if (!pel)
goto done;
if (eventnumber > 0) {
/* backward compatibility: make all numeric events look like integers */
sprintf(pel->eventname, "%i", (int)eventnumber);
pevent_list[(int)eventnumber] = pel;
}
else
strncpy(pel->eventname, eventname, namelength);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]);
callbackSetPriority(prio, &pel->callback[prio]);
@@ -501,13 +521,8 @@ event_list *eventNameToHandle(const char *eventname)
}
pel->next=pevent_list[0];
pevent_list[0]=pel;
{ /* backward compatibility */
char* p;
long e = strtol(eventname, &p, 0);
if (*p == 0 && e > 0 && e <= 255)
pevent_list[e] = pel;
}
}
done:
epicsMutexUnlock(event_lock);
return pel;
}
@@ -527,13 +542,8 @@ void postEvent(event_list *pel)
/* backward compatibility */
void post_event(int event)
{
event_list* pel;
if (event <= 0 || event > 255) return;
do { /* multithreading: make sure pel is consistent */
pel = pevent_list[event];
} while (pel != pevent_list[event]);
postEvent(pel);
postEvent(pevent_list[event]);
}
static void ioscanOnce(void *arg)

View File

@@ -50,7 +50,7 @@ epicsShareFunc void scanCleanup(void);
epicsShareFunc EVENTPVT eventNameToHandle(const char* event);
epicsShareFunc void postEvent(EVENTPVT epvt);
epicsShareFunc void post_event(int event) EPICS_DEPRECATED;
epicsShareFunc void post_event(int event);
epicsShareFunc void scanAdd(struct dbCommon *);
epicsShareFunc void scanDelete(struct dbCommon *);
epicsShareFunc double scanPeriod(int scan);

View File

@@ -308,6 +308,11 @@ long dbgf(const char *pname)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbgf only works after iocInit\n");
return -1;
}
no_elements = MIN(addr.no_elements, sizeof(buffer)/addr.field_size);
if (addr.dbr_field_type == DBR_ENUM) {
long status = dbGetField(&addr, DBR_STRING, pbuffer,
@@ -344,6 +349,11 @@ long dbpf(const char *pname,const char *pvalue)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbpf only works after iocInit\n");
return -1;
}
if (addr.no_elements > 1 &&
(addr.dbr_field_type == DBR_CHAR || addr.dbr_field_type == DBR_UCHAR)) {
dbrType = addr.dbr_field_type;
@@ -398,6 +408,11 @@ long dbtr(const char *pname)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbtr only works after iocInit\n");
return -1;
}
precord = (struct dbCommon*)addr.precord;
if (precord->pact) {
printf("record active\n");
@@ -437,6 +452,11 @@ long dbtgf(const char *pname)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbtgf only works after iocInit\n");
return -1;
}
/* try all options first */
req_options = 0xffffffff;
ret_options = req_options;
@@ -534,6 +554,11 @@ long dbtpf(const char *pname, const char *pvalue)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbtpf only works after iocInit\n");
return -1;
}
val_long = strtol(pvalue, &pend, 10);
validLong = (*pend == 0);
@@ -797,7 +822,7 @@ static void printBuffer(
printf("no_strs = %u:\n",
pdbr_enumStrs->no_str);
for (i = 0; i < pdbr_enumStrs->no_str; i++)
for (i = 0; i < pdbr_enumStrs->no_str; i++)
printf("\t\"%s\"\n", pdbr_enumStrs->strs[i]);
}
else {

View File

@@ -16,6 +16,7 @@
#include "epicsUnitTest.h"
#include "osiFileName.h"
#include "registry.h"
#include "epicsThread.h"
#define epicsExportSharedSymbols
#include "dbAccess.h"
@@ -111,7 +112,7 @@ long testdbVPutField(const char* pv, short dbrType, va_list ap)
return dbPutField(&addr, dbrType, pod.bytes, 1);
}
void testdbPutFieldOk(const char* pv, short dbrType, ...)
void testdbPutFieldOk(const char* pv, int dbrType, ...)
{
long ret;
va_list ap;
@@ -123,7 +124,7 @@ void testdbPutFieldOk(const char* pv, short dbrType, ...)
testOk(ret==0, "dbPutField(%s, %d, ...) == %ld", pv, dbrType, ret);
}
void testdbPutFieldFail(long status, const char* pv, short dbrType, ...)
void testdbPutFieldFail(long status, const char* pv, int dbrType, ...)
{
long ret;
va_list ap;
@@ -138,7 +139,7 @@ void testdbPutFieldFail(long status, const char* pv, short dbrType, ...)
testFail("dbPutField(\"%s\", %d, ...) != %ld (%ld)", pv, dbrType, status, ret);
}
void testdbGetFieldEqual(const char* pv, short dbrType, ...)
void testdbGetFieldEqual(const char* pv, int dbrType, ...)
{
va_list ap;
@@ -268,3 +269,26 @@ dbCommon* testdbRecordPtr(const char* pv)
return addr.precord;
}
static
epicsMutexId test_global;
static
epicsThreadOnceId test_global_once = EPICS_THREAD_ONCE_INIT;
static
void test_global_init(void* ignored)
{
test_global = epicsMutexMustCreate();
}
void testGlobalLock(void)
{
epicsThreadOnce(&test_global_once, &test_global_init, NULL);
epicsMutexMustLock(test_global);
}
void testGlobalUnlock(void)
{
epicsMutexUnlock(test_global);
}

View File

@@ -46,13 +46,13 @@ epicsShareFunc void testdbCleanup(void);
* testdbPutFieldOk("pvname", DBF_FLOAT, (double)4.1);
* testdbPutFieldOk("pvname", DBF_STRING, "hello world");
*/
epicsShareFunc void testdbPutFieldOk(const char* pv, short dbrType, ...);
epicsShareFunc void testdbPutFieldOk(const char* pv, int dbrType, ...);
/* Tests for put failure */
epicsShareFunc void testdbPutFieldFail(long status, const char* pv, short dbrType, ...);
epicsShareFunc void testdbPutFieldFail(long status, const char* pv, int dbrType, ...);
epicsShareFunc long testdbVPutField(const char* pv, short dbrType, va_list ap);
epicsShareFunc void testdbGetFieldEqual(const char* pv, short dbrType, ...);
epicsShareFunc void testdbGetFieldEqual(const char* pv, int dbrType, ...);
epicsShareFunc void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap);
/**
@@ -74,6 +74,65 @@ epicsShareFunc void testdbGetArrFieldEqual(const char* pv, short dbfType, long n
epicsShareFunc dbCommon* testdbRecordPtr(const char* pv);
/** Synchronize the shared callback queues.
*
* Block until all callback queue jobs which were queued, or running,
* have completed.
*/
epicsShareFunc void testSyncCallback(void);
/** Global mutex for use by test code.
*
* This utility mutex is intended to be used to avoid races in situations
* where some other syncronization primitive is being destroyed (epicsEvent,
* epicsMutex, ...).
*
* For example. The following has a subtle race where the event may be
* destroyed (free()'d) before the call to epicsEventMustSignal() has
* returned. On some targets this leads to a use after free() error.
*
@code
epicsEventId evt;
void thread1() {
evt = epicsEventMustCreate(...);
// spawn thread2()
epicsEventMustWait(evt);
epicsEventDestroy(evt);
}
// ...
void thread2() {
epicsEventMustSignal(evt);
}
@endcode
*
* One way to avoid this race is to use a global mutex to ensure
* that epicsEventMustSignal() has returned before destroying
* the event.
*
@code
epicsEventId evt;
void thread1() {
evt = epicsEventMustCreate(...);
// spawn thread2()
epicsEventMustWait(evt);
testGlobalLock(); // <-- added
epicsEventDestroy(evt);
testGlobalUnlock(); // <-- added
}
// ...
void thread2() {
testGlobalLock(); // <-- added
epicsEventMustSignal(evt);
testGlobalUnlock(); // <-- added
}
@endcode
*
* This must be a global mutex to avoid simply shifting the race
* from the event to a locally allocated mutex.
*/
epicsShareFunc void testGlobalLock(void);
epicsShareFunc void testGlobalUnlock(void);
#ifdef __cplusplus
}
#endif

View File

@@ -18,6 +18,7 @@
#include <limits.h>
#include "dbDefs.h"
#include "alarm.h"
#include "epicsMath.h"
#include "epicsPrint.h"
#include "epicsStdlib.h"
@@ -181,6 +182,9 @@ unsigned short recGblResetAlarms(void *precord)
epicsEnum16 val_mask = 0;
epicsEnum16 stat_mask = 0;
if (new_sevr > INVALID_ALARM)
new_sevr = INVALID_ALARM;
pdbc->stat = new_stat;
pdbc->sevr = new_sevr;
pdbc->nsta = 0;

View File

@@ -34,6 +34,8 @@
*
* Two time intervals are measured. The time to queue and run each of
* the immediate callbacks, and the actual delay of the delayed callback.
*
* Slow callbacks no longer fail the test, they just emit a diagnostic.
*/
#define NCALLBACKS 169
@@ -108,7 +110,7 @@ MAIN(callbackParallelTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
testPlan(4);
testPlan(2);
testDiag("Starting %d parallel callback threads", noCpus);
@@ -165,7 +167,8 @@ MAIN(callbackParallelTest)
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
testOk(slowups <= 1, "%d slowups during callback setup", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
@@ -182,7 +185,8 @@ MAIN(callbackParallelTest)
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
testOk(slowups < 5, "%d slowups during callbacks", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");

View File

@@ -34,6 +34,8 @@
*
* Two time intervals are measured. The time to queue and run each of
* the immediate callbacks, and the actual delay of the delayed callback.
*
* Slow callbacks no longer fail the test, they just emit a diagnostic.
*/
#define NCALLBACKS 169
@@ -108,7 +110,7 @@ MAIN(callbackTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
testPlan(4);
testPlan(2);
callbackInit();
epicsThreadSleep(1.0);
@@ -162,7 +164,8 @@ MAIN(callbackTest)
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
testOk(slowups <= 1, "%d slowups during callback setup", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
@@ -179,7 +182,8 @@ MAIN(callbackTest)
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
testOk(slowups < 5, "%d slowups during callbacks", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");

View File

@@ -1036,23 +1036,29 @@ static void dbRecordHead(char *recordType, char *name, int visible)
static void dbRecordField(char *name,char *value)
{
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
if(duplicate) return;
if (duplicate) return;
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbentry = ptempListNode->item;
status = dbFindField(pdbentry,name);
if(status) {
epicsPrintf("Record \"%s\" does not have a field \"%s\"\n",
dbGetRecordName(pdbentry), name);
yyerror(NULL);
return;
if (status) {
epicsPrintf("Record \"%s\" does not have a field \"%s\"\n",
dbGetRecordName(pdbentry), name);
yyerror(NULL);
return;
}
if (pdbentry->indfield == 0) {
epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n",
dbGetRecordName(pdbentry));
yyerror(NULL);
return;
}
dbTranslateEscape(value, value); /* yuck: in-place, but safe */
status = dbPutString(pdbentry,value);
if(status) {
if (status) {
epicsPrintf("Can't set \"%s.%s\" to \"%s\"\n",
dbGetRecordName(pdbentry), name, value);
yyerror(NULL);
@@ -1062,33 +1068,34 @@ static void dbRecordField(char *name,char *value)
static void dbRecordInfo(char *name, char *value)
{
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
if(duplicate) return;
if (duplicate) return;
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbentry = ptempListNode->item;
dbTranslateEscape(value, value); /* yuck: in-place, but safe */
status = dbPutInfo(pdbentry,name,value);
if(status) {
epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
if (status) {
epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
dbGetRecordName(pdbentry), name, value);
yyerror(NULL);
return;
yyerror(NULL);
return;
}
}
static void dbRecordAlias(char *name)
{
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
if(duplicate) return;
if (duplicate) return;
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbentry = ptempListNode->item;
status = dbCreateAlias(pdbentry, name);
if(status) {
if (status) {
epicsPrintf("Can't create alias \"%s\" for \"%s\"\n",
name, dbGetRecordName(pdbentry));
yyerror(NULL);
@@ -1098,15 +1105,16 @@ static void dbRecordAlias(char *name)
static void dbAlias(char *name, char *alias)
{
DBENTRY dbEntry;
DBENTRY *pdbEntry = &dbEntry;
DBENTRY dbEntry;
DBENTRY *pdbEntry = &dbEntry;
dbInitEntry(pdbbase, pdbEntry);
if (dbFindRecord(pdbEntry, name)) {
epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n",
alias, name);
yyerror(NULL);
} else if (dbCreateAlias(pdbEntry, alias)) {
}
else if (dbCreateAlias(pdbEntry, alias)) {
epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n",
alias, name);
yyerror(NULL);
@@ -1116,14 +1124,14 @@ static void dbAlias(char *name, char *alias)
static void dbRecordBody(void)
{
DBENTRY *pdbentry;
DBENTRY *pdbentry;
if(duplicate) {
duplicate = FALSE;
return;
if (duplicate) {
duplicate = FALSE;
return;
}
pdbentry = (DBENTRY *)popFirstTemp();
if(ellCount(&tempList))
yyerrorAbort("dbRecordBody: tempList not empty");
if (ellCount(&tempList))
yyerrorAbort("dbRecordBody: tempList not empty");
dbFreeEntry(pdbentry);
}

View File

@@ -851,10 +851,14 @@ long dbWriteRecordFP(
status=dbNextField(pdbentry,dctonly);
}
status = dbFirstInfo(pdbentry);
while(!status) {
fprintf(fp,"\tinfo(\"%s\",\"%s\")\n",
dbGetInfoName(pdbentry), dbGetInfoString(pdbentry));
status=dbNextInfo(pdbentry);
while (!status) {
const char *pinfostr = dbGetInfoString(pdbentry);
fprintf(fp, "\tinfo(\"%s\",\"",
dbGetInfoName(pdbentry));
epicsStrPrintEscaped(fp, pinfostr, strlen(pinfostr));
fprintf(fp, "\")\n");
status = dbNextInfo(pdbentry);
}
fprintf(fp,"}\n");
status = dbNextRecord(pdbentry);
@@ -1631,19 +1635,22 @@ int dbIsVisibleRecord(DBENTRY *pdbentry)
long dbCreateAlias(DBENTRY *pdbentry, const char *alias)
{
dbRecordType *precordType = pdbentry->precordType;
dbRecordNode *precnode = pdbentry->precnode;
dbRecordNode *pnewnode;
PVDENTRY *ppvd;
ELLLIST *preclist = NULL;
dbRecordType *precordType = pdbentry->precordType;
dbRecordNode *precnode = pdbentry->precnode;
dbRecordNode *pnewnode;
DBENTRY tempEntry;
PVDENTRY *ppvd;
if (!precordType)
return S_dbLib_recordTypeNotFound;
if (!precnode)
return S_dbLib_recNotFound;
dbInitEntry(pdbentry->pdbbase, &tempEntry);
if (!dbFindRecord(&tempEntry, alias))
return S_dbLib_recExists;
dbFinishEntry(&tempEntry);
if (!precordType) return S_dbLib_recordTypeNotFound;
if (!precnode) return S_dbLib_recNotFound;
zeroDbentry(pdbentry);
if (!dbFindRecord(pdbentry, alias)) return S_dbLib_recExists;
zeroDbentry(pdbentry);
pdbentry->precordType = precordType;
preclist = &precordType->recList;
pnewnode = dbCalloc(1, sizeof(dbRecordNode));
pnewnode->recordname = epicsStrDup(alias);
pnewnode->precord = precnode->precord;
@@ -1651,11 +1658,16 @@ long dbCreateAlias(DBENTRY *pdbentry, const char *alias)
if (!(precnode->flags & DBRN_FLAGS_ISALIAS))
precnode->flags |= DBRN_FLAGS_HASALIAS;
ellInit(&pnewnode->infoList);
ellAdd(preclist, &pnewnode->node);
ellAdd(&precordType->recList, &pnewnode->node);
precordType->no_aliases++;
pdbentry->precnode = pnewnode;
ppvd = dbPvdAdd(pdbentry->pdbbase, precordType, pnewnode);
if (!ppvd) {errMessage(-1,"Logic Err: Could not add to PVD");return(-1);}
if (!ppvd) {
errMessage(-1, "dbCreateAlias: Add to PVD failed");
return -1;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -34,10 +34,10 @@ be written to stdout unless the -o option is given.</p>
<dl>
<dt><tt>-V</tt></dt>
<dd>Verbose warnings; if this parameter is specified then any undefined
macro discovered in the template file which does not have an associated
default value is considered an error. An error message is generated, and
when msi terminates it will do so with an exit status of 2.</dd>
<dd>Verbose warnings; if this parameter is specified then any undefined or
recursive macros discovered in the template will be considered an error and
will be marked in the output file. An error message will be shown, and when
msi terminates it will do so with an exit status of 2.</dd>
<dt><tt>-g</tt></dt>
<dd>When this flag is given all macros defined in a substitution file will

View File

@@ -31,18 +31,18 @@ ok(msi('-S ../t5-substitute.txt ../t5-template.txt'), slurp('../t5-result.txt'))
# Substitution file, pattern format
ok(msi('-S../t6-substitute.txt ../t6-template.txt'), slurp('../t6-result.txt'));
# Output option -o
# Output option -o and verbose option -V
my $out = 't7-output.txt';
my $count = 5; # Try up to 5 times...
my $result;
do {
unlink $out;
msi("-I.. -o $out ../t1-template.txt");
msi("-I.. -V -o $out ../t1-template.txt");
$result = slurp($out);
print "# msi output file empty, retrying\n"
if $result eq '';
} while ($result eq '') && (--$count > 0);
ok($result, slurp('../t1-result.txt'));
ok($result, slurp('../t7-result.txt'));
# Dependency generation, include/substitute model
ok(msi('-I.. -D -o t8.txt ../t1-template.txt'), slurp('../t8-result.txt'));

View File

@@ -1,6 +1,6 @@
This is t1-template.txt
With $(a,undefined) & $(b,undefined):
With $(a) & $(b):
This is t1-include.txt
a = default value used when a is undefined
b = default value used when b is undefined

View File

@@ -1,6 +1,6 @@
a = va1-a b = def-b c = def-c d = $(d,undefined)
a = va2-a b = va2-b c = def-c d = $(d,undefined)
a = va3-a b = va3-b c = va3-c d = $(d,undefined)
a = va4-a b = va4-b c = def-c d = $(d,undefined)
a = va5-a b = def-b c = def-c d = $(d,undefined)
a = pt3-a b = pt3-b c = pt3-c d = $(d,undefined)
a = va1-a b = def-b c = def-c d = $(d)
a = va2-a b = va2-b c = def-c d = $(d)
a = va3-a b = va3-b c = va3-c d = $(d)
a = va4-a b = va4-b c = def-c d = $(d)
a = va5-a b = def-b c = def-c d = $(d)
a = pt3-a b = pt3-b c = pt3-c d = $(d)

View File

@@ -1,28 +1,28 @@
a = gb1-a b = gb1-b c = def-c d = $(d,undefined)
a = va1-a b = gb1-b c = def-c d = $(d,undefined)
a = va2-a b = va2-b c = def-c d = $(d,undefined)
a = va3-a b = va3-b c = va3-c d = $(d,undefined)
a = va4-a b = va4-b c = def-c d = $(d,undefined)
a = va5-a b = gb1-b c = def-c d = $(d,undefined)
a = gb1-a b = gb1-b c = def-c d = $(d,undefined)
a = gb2-a b = gb2-b c = def-c d = $(d,undefined)
a = va1-a b = gb2-b c = def-c d = $(d,undefined)
a = va2-a b = va2-b c = def-c d = $(d,undefined)
a = va3-a b = va3-b c = va3-c d = $(d,undefined)
a = va4-a b = va4-b c = def-c d = $(d,undefined)
a = va5-a b = gb2-b c = def-c d = $(d,undefined)
a = gb2-a b = gb2-b c = def-c d = $(d,undefined)
a = gb3-a b = gb3-b c = def-c d = $(d,undefined)
a = pt1-a b = gb3-b c = def-c d = $(d,undefined)
a = pt2-a b = pt2-b c = def-c d = $(d,undefined)
a = pt3-a b = pt3-b c = pt3-c d = $(d,undefined)
a = pt4-a b = pt4-b c = def-c d = $(d,undefined)
a = pt5-a b = gb3-b c = def-c d = $(d,undefined)
a = gb3-a b = gb3-b c = def-c d = $(d,undefined)
a = gb4-a b = gb4-b c = def-c d = $(d,undefined)
a = pt1-a b = gb4-b c = def-c d = $(d,undefined)
a = pt2-a b = pt2-b c = def-c d = $(d,undefined)
a = pt3-a b = pt3-b c = pt3-c d = $(d,undefined)
a = pt4-a b = pt4-b c = def-c d = $(d,undefined)
a = pt5-a b = gb4-b c = def-c d = $(d,undefined)
a = gb4-a b = gb4-b c = def-c d = $(d,undefined)
a = gb1-a b = gb1-b c = def-c d = $(d)
a = va1-a b = gb1-b c = def-c d = $(d)
a = va2-a b = va2-b c = def-c d = $(d)
a = va3-a b = va3-b c = va3-c d = $(d)
a = va4-a b = va4-b c = def-c d = $(d)
a = va5-a b = gb1-b c = def-c d = $(d)
a = gb1-a b = gb1-b c = def-c d = $(d)
a = gb2-a b = gb2-b c = def-c d = $(d)
a = va1-a b = gb2-b c = def-c d = $(d)
a = va2-a b = va2-b c = def-c d = $(d)
a = va3-a b = va3-b c = va3-c d = $(d)
a = va4-a b = va4-b c = def-c d = $(d)
a = va5-a b = gb2-b c = def-c d = $(d)
a = gb2-a b = gb2-b c = def-c d = $(d)
a = gb3-a b = gb3-b c = def-c d = $(d)
a = pt1-a b = gb3-b c = def-c d = $(d)
a = pt2-a b = pt2-b c = def-c d = $(d)
a = pt3-a b = pt3-b c = pt3-c d = $(d)
a = pt4-a b = pt4-b c = def-c d = $(d)
a = pt5-a b = gb3-b c = def-c d = $(d)
a = gb3-a b = gb3-b c = def-c d = $(d)
a = gb4-a b = gb4-b c = def-c d = $(d)
a = pt1-a b = gb4-b c = def-c d = $(d)
a = pt2-a b = pt2-b c = def-c d = $(d)
a = pt3-a b = pt3-b c = pt3-c d = $(d)
a = pt4-a b = pt4-b c = def-c d = $(d)
a = pt5-a b = gb4-b c = def-c d = $(d)
a = gb4-a b = gb4-b c = def-c d = $(d)

View File

@@ -1,6 +1,6 @@
a = va1-a b = def-b c = def-c d = $(d,undefined)
a = va2-a b = va2-b c = def-c d = $(d,undefined)
a = va3-a b = va3-b c = va3-c d = $(d,undefined)
a = va4-a b = va4-b c = va3-c d = $(d,undefined)
a = va5-a b = va4-b c = va3-c d = $(d,undefined)
a = pt3-a b = pt3-b c = pt3-c d = $(d,undefined)
a = va1-a b = def-b c = def-c d = $(d)
a = va2-a b = va2-b c = def-c d = $(d)
a = va3-a b = va3-b c = va3-c d = $(d)
a = va4-a b = va4-b c = va3-c d = $(d)
a = va5-a b = va4-b c = va3-c d = $(d)
a = pt3-a b = pt3-b c = pt3-c d = $(d)

View File

@@ -2,19 +2,19 @@
a = 111
b = 222
c = xx
d = $(d,undefined)
d = $(d)
# comment line
a = aaa
b = bbb
c = ccc
d = $(d,undefined)
d = $(d)
# comment line
a = AA
b = BB
c = xx
d = $(d,undefined)
d = $(d)
# comment line
a = aaa
b = bbb
c = yy
d = $(d,undefined)
d = $(d)

View File

@@ -2,19 +2,19 @@
a = 111
b = 222
c = xx
d = $(d,undefined)
d = $(d)
# comment line
a = aaa
b = bbb
c = ccc
d = $(d,undefined)
d = $(d)
# comment line
a = AA
b = BB
c = xx
d = $(d,undefined)
d = $(d)
# comment line
a = aaa
b = bbb
c = yy
d = $(d,undefined)
d = $(d)

View File

@@ -0,0 +1,21 @@
This is t1-template.txt
With $(a,undefined) & $(b,undefined):
This is t1-include.txt
a = default value used when a is undefined
b = default value used when b is undefined
End of t1-include.txt
On defining a=aaa & b=bbb:
This is t1-include.txt again
a = aaa
b = bbb
End of t1-include.txt
On setting a="aa":
This is t1-include.txt again
a = "aa"
b = bbb
End of t1-include.txt
End of t1-template.txt

View File

@@ -26,3 +26,4 @@ dbCore_SRCS += miscIocRegister.c
dbCore_SRCS += dlload.c
dbCore_SRCS += iocshRegisterCommon.c
miscIocRegister_CFLAGS_iOS = -DSYSTEM_UNAVAILABLE

View File

@@ -17,9 +17,6 @@
#define epicsExportSharedSymbols
#include "epicsRelease.h"
static const char id[] EPICS_UNUSED =
"@(#) " EPICS_VERSION_STRING ", Misc. Utilities Library" __DATE__;
epicsShareFunc int coreRelease(void)
{
printf ( "############################################################################\n" );

View File

@@ -66,10 +66,12 @@ void miscIocRegister(void)
/* system -- escape to system command interpreter.
*
* Disabled by default, for security reasons. To enable this command, add
* Disabled by default for security reasons, not available on all OSs.
* To enable this command, add
* registrar(iocshSystemCommand)
* to an application dbd file.
* to an application dbd file, or include system.dbd
*/
#ifndef SYSTEM_UNAVAILABLE
static const iocshArg systemArg0 = { "command string",iocshArgString};
static const iocshArg * const systemArgs[] = {&systemArg0};
static const iocshFuncDef systemFuncDef = {"system",1,systemArgs};
@@ -77,12 +79,15 @@ static void systemCallFunc(const iocshArgBuf *args)
{
system(args[0].sval);
}
#endif
static void iocshSystemCommand(void)
{
#ifndef SYSTEM_UNAVAILABLE
if (system(NULL))
iocshRegister(&systemFuncDef, systemCallFunc);
else
#endif
errlogPrintf ("Can't register 'system' command -- no command interpreter available.\n");
}
epicsExportRegistrar(iocshSystemCommand);

View File

@@ -45,7 +45,6 @@ void rsrv_online_notify_task(void *pParm)
caHdr msg;
int status;
ca_uint32_t beaconCounter = 0;
char buf[16];
taskwdInsert (epicsThreadGetIdSelf(),NULL,NULL);
@@ -85,10 +84,12 @@ void rsrv_online_notify_task(void *pParm)
&pAddr->addr.sa, sizeof(pAddr->addr));
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToDottedIP (&pAddr->addr.ia, buf, sizeof(buf));
char sockDipBuf[22];
epicsSocketConvertErrnoToString(sockErrBuf, sizeof(sockErrBuf));
ipAddrToDottedIP(&pAddr->addr.ia, sockDipBuf, sizeof(sockDipBuf));
errlogPrintf ( "CAS: CA beacon send to %s error: %s\n",
buf, sockErrBuf);
sockDipBuf, sockErrBuf);
}
else {
assert (status == sizeof(msg));

View File

@@ -95,6 +95,7 @@ epicsShareFunc long epicsShareAPI
envGetBoolConfigParam(const ENV_PARAM *pParam, int *pBool);
epicsShareFunc long epicsShareAPI epicsPrtEnvParams(void);
epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value);
epicsShareFunc void epicsShareAPI epicsEnvUnset (const char *name);
epicsShareFunc void epicsShareAPI epicsEnvShow (const char *name);
#ifdef __cplusplus

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* flex - tool to generate fast lexical analyzers */
@@ -14,7 +14,7 @@
*
* This code is derived from software contributed to Berkeley by
* Vern Paxson.
*
*
* The United States Government has rights in this work pursuant
* to contract no. DE-AC03-76SF00098 between the United States
* Department of Energy and the University of California.
@@ -495,6 +495,13 @@ void flexinit(int argc, char **argv)
/* stupid do-nothing deprecated option */
break;
case 'o':
if ( i != 1 )
flexerror( "-o flag must be given separately" );
outfile = arg + i + 1;
goto get_next_arg;
case 'p':
performance_report = true;
break;

View File

@@ -110,6 +110,21 @@ static void epicsEnvSetCallFunc(const iocshArgBuf *args)
epicsEnvSet (name, value);
}
/* epicsEnvUnset */
static const iocshArg epicsEnvUnsetArg0 = { "name",iocshArgString};
static const iocshArg * const epicsEnvUnsetArgs[1] = {&epicsEnvUnsetArg0};
static const iocshFuncDef epicsEnvUnsetFuncDef = {"epicsEnvUnset",1,epicsEnvUnsetArgs};
static void epicsEnvUnsetCallFunc(const iocshArgBuf *args)
{
char *name = args[0].sval;
if (name == NULL) {
fprintf(stderr, "Missing environment variable name argument.\n");
return;
}
epicsEnvUnset (name);
}
/* epicsParamShow */
static const iocshFuncDef epicsParamShowFuncDef = {"epicsParamShow",0,NULL};
static void epicsParamShowCallFunc(const iocshArgBuf *args)
@@ -367,6 +382,7 @@ void epicsShareAPI libComRegister(void)
iocshRegister(&pwdFuncDef, pwdCallFunc);
iocshRegister(&epicsEnvSetFuncDef, epicsEnvSetCallFunc);
iocshRegister(&epicsEnvUnsetFuncDef, epicsEnvUnsetCallFunc);
iocshRegister(&epicsParamShowFuncDef, epicsParamShowCallFunc);
iocshRegister(&epicsPrtEnvParamsFuncDef, epicsPrtEnvParamsCallFunc);
iocshRegister(&epicsEnvShowFuncDef, epicsEnvShowCallFunc);

View File

@@ -347,11 +347,6 @@ static int openLogFile (struct ioc_log_server *pserver)
{
enum TF_RETURN ret;
if (ioc_log_file_limit==0u) {
pserver->poutfile = stderr;
return IOCLS_ERROR;
}
if (pserver->poutfile && pserver->poutfile != stderr){
fclose (pserver->poutfile);
pserver->poutfile = NULL;
@@ -627,7 +622,7 @@ static void writeMessagesToLog (struct iocLogClient *pclient)
strlen(pclient->ascii_time) + nchar + 3u;
assert (nTotChar <= INT_MAX);
ntci = (int) nTotChar;
if ( pclient->pserver->filePos+ntci >= pclient->pserver->max_file_size ) {
if ( pclient->pserver->max_file_size && pclient->pserver->filePos+ntci >= pclient->pserver->max_file_size ) {
if ( pclient->pserver->max_file_size >= pclient->pserver->filePos ) {
unsigned nPadChar;
/*
@@ -771,7 +766,7 @@ static int getConfig(void)
&EPICS_IOC_LOG_FILE_LIMIT,
&ioc_log_file_limit);
if(status>=0){
if (ioc_log_file_limit<=0) {
if (ioc_log_file_limit < 0) {
envFailureNotify (&EPICS_IOC_LOG_FILE_LIMIT);
return IOCLS_ERROR;
}

View File

@@ -902,11 +902,16 @@ static void refer ( MAC_HANDLE *handle, MAC_ENTRY *entry, int level,
}
}
/* Bad reference, insert $(name,errval) */
/* Bad reference, insert either $(name,<error>) or $(name) */
if ( v < valend ) *v++ = '$';
if ( v < valend ) *v++ = '(';
cpy2val( refname, &v, valend );
cpy2val( errval, &v, valend );
if (handle->flags & FLAG_SUPPRESS_WARNINGS) {
if ( v < valend ) *v++ = ')';
*v = '\0';
}
else
cpy2val( errval, &v, valend );
cleanup:
if (pop) {

View File

@@ -269,7 +269,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
}
}
} else {
if (epicsTimeGreaterThanEqual(pDest,
if (epicsTimeGreaterThanEqual(&ts,
&gtPvt.eventTime[eventNumber])) {
*pDest = ts;
gtPvt.eventTime[eventNumber] = ts;
@@ -279,7 +279,6 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
key = epicsInterruptLock();
gtPvt.ErrorCounts++;
epicsInterruptUnlock(key);
}
IFDEBUG(10) {
char last[40], buff[40];
@@ -291,6 +290,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
" %s, using %s instead\n",
ptp->name, buff, last);
}
}
}
break;
}

View File

@@ -34,20 +34,22 @@ extern "C" {
/* Make printf, puts and putchar use *our* version of stdout */
#ifdef printf
# undef printf
#endif /* printf */
#define printf epicsStdoutPrintf
#ifndef epicsStdioStdPrintfEtc
# ifdef printf
# undef printf
# endif
# define printf epicsStdoutPrintf
#ifdef puts
# undef puts
#endif /* puts */
#define puts epicsStdoutPuts
# ifdef puts
# undef puts
# endif
# define puts epicsStdoutPuts
#ifdef putchar
# undef putchar
#endif /* putchar */
#define putchar epicsStdoutPutchar
# ifdef putchar
# undef putchar
# endif
# define putchar epicsStdoutPutchar
#endif
epicsShareFunc int epicsShareAPI epicsSnprintf(
char *str, size_t size, const char *format, ...) EPICS_PRINTF_STYLE(3,4);
@@ -87,6 +89,19 @@ epicsShareFunc int epicsShareAPI epicsStdoutPutchar(int c);
#ifdef __cplusplus
}
#endif
/* Also pull functions into the std namespace (see lp:1786927) */
#if !defined(__GNUC__) || (__GNUC__ > 2)
namespace std {
using ::epicsGetStdin;
using ::epicsGetStdout;
using ::epicsGetStderr;
using ::epicsStdoutPrintf;
using ::epicsStdoutPuts;
using ::epicsStdoutPutchar;
}
#endif /* __GNUC__ > 2 */
#endif /* __cplusplus */
#endif /* epicsStdioh */

View File

@@ -39,6 +39,16 @@ epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *val
setenv(name, value, 1);
}
/*
* Unset an environment variable
*/
epicsShareFunc void epicsShareAPI epicsEnvUnset (const char *name)
{
iocshEnvClear(name);
unsetenv(name);
}
/*
* Show the value of the specified, or all, environment variables
*/

View File

@@ -0,0 +1,89 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* osdEnv.c */
/*
* Author: Eric Norum
* Date: May 7, 2001
*
* Routines to modify/display environment variables and EPICS parameters
*
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#define epicsExportSharedSymbols
#include "epicsStdio.h"
#include "errlog.h"
#include "cantProceed.h"
#include "envDefs.h"
#include "osiUnistd.h"
#include "epicsFindSymbol.h"
#include "iocsh.h"
/*
* Set the value of an environment variable
* Leaks memory, but the assumption is that this routine won't be
* called often enough for the leak to be a problem.
*/
epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value)
{
char *cp;
iocshEnvClear(name);
cp = mallocMustSucceed (strlen (name) + strlen (value) + 2, "epicsEnvSet");
strcpy (cp, name);
strcat (cp, "=");
strcat (cp, value);
if (putenv (cp) < 0) {
errPrintf(
-1L,
__FILE__,
__LINE__,
"Failed to set environment parameter \"%s\" to \"%s\": %s\n",
name,
value,
strerror (errno));
free (cp);
}
}
/*
* Unset an environment variable
* Using putenv with a an existing name plus "=" (without value) deletes
*/
epicsShareFunc void epicsShareAPI epicsEnvUnset (const char *name)
{
iocshEnvClear(name);
if (getenv(name) != NULL)
epicsEnvSet((char*)name, "");
}
/*
* Show the value of the specified, or all, environment variables
*/
epicsShareFunc void epicsShareAPI epicsEnvShow (const char *name)
{
if (name == NULL) {
extern char **environ;
char **sp;
for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++)
printf ("%s\n", *sp);
}
else {
const char *cp = getenv (name);
if (cp == NULL)
printf ("%s is not an environment variable.\n", name);
else
printf ("%s=%s\n", name, cp);
}
}

View File

@@ -19,13 +19,13 @@
#endif
#include <stdlib.h>
#include <stdio.h>
#define STRICT
#include <windows.h>
#define epicsExportSharedSymbols
#include "osiProcess.h"
#include "errlog.h"
epicsShareFunc osiGetUserNameReturn epicsShareAPI osiGetUserName (char *pBuf, unsigned bufSizeIn)
{
@@ -94,16 +94,11 @@ epicsShareFunc osiSpawnDetachedProcessReturn epicsShareAPI osiSpawnDetachedProce
pFmtArgs[1] = (char *) pBaseExecutableName;
pFmtArgs[2] = errStrMsgBuf;
pFmtArgs[3] = "Changes may be required in your \"path\" environment variable.";
pFmtArgs[4] = "PATH = ";
pFmtArgs[5] = getenv ("path");
if ( pFmtArgs[5] == NULL ) {
pFmtArgs[5] = "<empty string>";
}
W32status = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING |
FORMAT_MESSAGE_ARGUMENT_ARRAY | 80,
"%1 \"%2\". %3 %4 %5 \"%6\"",
"%1 \"%2\". %3 %4",
0,
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
(LPTSTR) &complteMsgBuf,
@@ -111,24 +106,20 @@ epicsShareFunc osiSpawnDetachedProcessReturn epicsShareAPI osiSpawnDetachedProce
pFmtArgs
);
if (W32status) {
/* Display the string. */
MessageBox (NULL, complteMsgBuf, "Configuration Problem",
MB_OK | MB_ICONINFORMATION);
fprintf (stderr, "%s\n", (char *) complteMsgBuf);
LocalFree (complteMsgBuf);
}
else {
/* Display the string. */
MessageBox (NULL, errStrMsgBuf, "Failed to start executable",
MB_OK | MB_ICONINFORMATION);
fprintf (stderr, "%s\n", (char *) errStrMsgBuf);
}
/* Free the buffer. */
LocalFree (errStrMsgBuf);
}
else {
errlogPrintf ("!!WARNING!!\n");
errlogPrintf ("Unable to locate executable \"%s\".\n", pBaseExecutableName);
errlogPrintf ("You may need to modify your \"path\" environment variable.\n");
fprintf (stderr, "!!WARNING!!\n");
fprintf (stderr, "Unable to locate executable \"%s\".\n", pBaseExecutableName);
fprintf (stderr, "You may need to modify your \"path\" environment variable.\n");
}
return osiSpawnDetachedProcessFail;
}

View File

@@ -55,6 +55,18 @@ epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *val
}
}
/*
* Unset an environment variable
* Using putenv with a an existing name but without "=..." deletes
*/
epicsShareFunc void epicsShareAPI epicsEnvUnset (const char *name)
{
iocshEnvClear(name);
if (getenv(name) != NULL)
putenv((char*)name);
}
/*
* Show the value of the specified, or all, environment variables
*/

View File

@@ -36,6 +36,16 @@ epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *val
setenv(name, value, 1);
}
/*
* Unset an environment variable
*/
epicsShareFunc void epicsShareAPI epicsEnvUnset (const char *name)
{
iocshEnvClear(name);
unsetenv(name);
}
/*
* Show the value of the specified, or all, environment variables
*/

View File

@@ -0,0 +1,62 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* osdEnv.c */
/*
* Author: Eric Norum
* Date: May 7, 2001
*
* Routines to modify/display environment variables and EPICS parameters
*
*/
#include <stdlib.h>
#include <stdio.h>
#define epicsExportSharedSymbols
#include "epicsStdio.h"
#include "envDefs.h"
#include "osiUnistd.h"
#include "iocsh.h"
/*
* Set the value of an environment variable
*/
epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value)
{
iocshEnvClear(name);
setenv(name, value, 1);
}
/*
* Unset an environment variable
*/
epicsShareFunc void epicsShareAPI epicsEnvUnset (const char *name)
{
iocshEnvClear(name);
unsetenv(name);
}
/*
* Show the value of the specified, or all, environment variables
*/
epicsShareFunc void epicsShareAPI epicsEnvShow (const char *name)
{
if (name == NULL) {
extern char **environ;
char **sp;
for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++)
printf ("%s\n", *sp);
}
else {
const char *cp = getenv (name);
if (cp == NULL)
printf ("%s is not an environment variable.\n", name);
else
printf ("%s=%s\n", name, cp);
}
}

View File

@@ -51,6 +51,25 @@ epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *val
}
}
/*
* Unset an environment variable
* Basically destroy the name of that variable because vxWorks does not
* support to really unset an environment variable.
*/
epicsShareFunc void epicsShareAPI epicsEnvUnset (const char *name)
{
char* var;
if (!name) return;
iocshEnvClear(name);
var = getenv(name);
if (!var) return;
var -= strlen(name);
var --;
*var = 0;
}
/*
* Show the value of the specified, or all, environment variables
*/

View File

@@ -41,16 +41,18 @@ static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
#ifdef CLOCK_REALTIME
/* This code is not used on systems without Posix CLOCK_REALTIME such
* as Darwin, but the only way to detect that is from the OS headers,
* so the Makefile can't exclude building this file on those systems.
/* This code is not used on systems without Posix CLOCK_REALTIME,
* but the only way to detect that is from the OS headers, so the
* Makefile can't exclude compiling this file on those systems.
*/
/* Forward references */
static int ClockTimeGetCurrent(epicsTimeStamp *pDest);
static void ClockTimeSync(void *dummy);
#if defined(vxWorks) || defined(__rtems__)
static void ClockTimeSync(void *dummy);
#endif
/* ClockTime_Report iocsh command */
static const iocshArg ReportArg0 = { "interest_level", iocshArgArgv};
@@ -98,12 +100,18 @@ void ClockTime_Init(int synchronize)
if (synchronize == CLOCKTIME_SYNC) {
if (ClockTimePvt.synchronize == CLOCKTIME_NOSYNC) {
#if defined(vxWorks) || defined(__rtems__)
/* Start synchronizing */
ClockTimePvt.synchronize = synchronize;
epicsThreadCreate("ClockTimeSync", epicsThreadPriorityHigh,
epicsThreadGetStackSize(epicsThreadStackSmall),
ClockTimeSync, NULL);
#else
errlogPrintf("Clock synchronization must be performed by the OS\n");
#endif
}
else {
/* No change, sync thread should already be running */
@@ -139,6 +147,7 @@ void ClockTime_GetProgramStart(epicsTimeStamp *pDest)
/* Synchronization thread */
#if defined(vxWorks) || defined(__rtems__)
static void ClockTimeSync(void *dummy)
{
taskwdInsert(0, NULL, NULL);
@@ -177,6 +186,7 @@ static void ClockTimeSync(void *dummy)
ClockTimePvt.synchronized = 0;
taskwdRemove(0);
}
#endif
/* Time Provider Routine */
@@ -188,6 +198,7 @@ static int ClockTimeGetCurrent(epicsTimeStamp *pDest)
/* If a Hi-Res clock is available and works, use it */
#ifdef CLOCK_REALTIME_HR
clock_gettime(CLOCK_REALTIME_HR, &clockNow) &&
/* Note: Uses the lo-res clock below if the above call fails */
#endif
clock_gettime(CLOCK_REALTIME, &clockNow);
@@ -195,9 +206,15 @@ static int ClockTimeGetCurrent(epicsTimeStamp *pDest)
clockNow.tv_sec < POSIX_TIME_AT_EPICS_EPOCH) {
clockNow.tv_sec = POSIX_TIME_AT_EPICS_EPOCH + 86400;
clockNow.tv_nsec = 0;
#if defined(vxWorks) || defined(__rtems__)
clock_settime(CLOCK_REALTIME, &clockNow);
errlogPrintf("WARNING: OS Clock time was read before being set.\n"
"Using 1990-01-02 00:00:00.000000 UTC\n");
#else
errlogPrintf("WARNING: OS Clock pre-dates the EPICS epoch!\n"
"Using 1990-01-02 00:00:00.000000 UTC\n");
#endif
}
epicsTimeFromTimespec(pDest, &clockNow);

View File

@@ -62,6 +62,11 @@ epicsEnvTest_SRCS += epicsEnvTest.c
testHarness_SRCS += epicsEnvTest.c
TESTS += epicsEnvTest
TESTPROD_HOST += epicsEnvUnsetTest
epicsEnvUnsetTest_SRCS += epicsEnvUnsetTest.c
testHarness_SRCS += epicsEnvUnsetTest.c
TESTS += epicsEnvUnsetTest
TESTPROD_HOST += epicsErrlogTest
epicsErrlogTest_SRCS += epicsErrlogTest.c
testHarness_SRCS += epicsErrlogTest.c

View File

@@ -391,7 +391,7 @@ MAIN(epicsCalcTest)
testExpr(isnan(0.));
testExpr(isnan(Inf));
testExpr(isnan(-Inf));
testExpr(isnan(NaN));
testExpr(!!isnan(NaN)); // As above
testCalc("isnan(0,1,2)", 0);
testCalc("isnan(0,1,NaN)", 1);
testCalc("isnan(0,NaN,2)", 1);

View File

@@ -0,0 +1,37 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "macLib.h"
#include "envDefs.h"
#include "errlog.h"
#include "epicsUnitTest.h"
#include "testMain.h"
static void check(const char* variable, const char* expected)
{
const char* value;
value = getenv(variable);
if (!testOk((!expected && !value) || (expected && value && strcmp(expected, value) == 0),
"%s = \"%s\"", variable, value))
{
testDiag("should have been \"%s\"", expected);
}
}
MAIN(epicsEnvUnsetTest)
{
eltc(0);
testPlan(3);
check("TEST_VAR_A",NULL);
epicsEnvSet("TEST_VAR_A","test value");
check("TEST_VAR_A","test value");
epicsEnvUnset("TEST_VAR_A");
check("TEST_VAR_A",NULL);
testDone();
return 0;
}

View File

@@ -65,11 +65,11 @@ static void ovcheck(void)
MAIN(macLibTest)
{
testPlan(91);
testPlan(93);
if (macCreateHandle(&h, NULL))
testAbort("macCreateHandle() failed");
macSuppressWarning(h, TRUE);
eltc(0);
check("FOO", " FOO");
@@ -215,6 +215,10 @@ MAIN(macLibTest)
check("${FOO,FOO=${FOO}}", "!$(FOO,recursive)");
check("${FOO=GRIBBLE,FOO=${FOO}}", "!$(FOO,recursive)");
macSuppressWarning(h, TRUE);
check("$(CRUX)", "!$(CRUX)");
check("${FOO}", "!$(BAR)");
ovcheck();
return testDone();

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -22,6 +22,7 @@
#include "alarm.h"
#include "dbDefs.h"
#include "dbAccess.h"
#include "dbEvent.h"
#include "recGbl.h"
#include "devSup.h"
#include "cantProceed.h"
@@ -71,13 +72,18 @@ static long init_record(aaiRecord *prec)
static long read_aai(aaiRecord *prec)
{
epicsUInt32 nord = prec->nord;
long nRequest = prec->nelm;
dbGetLink(prec->simm == menuYesNoYES ? &prec->siol : &prec->inp,
prec->ftvl, prec->bptr, 0, &nRequest);
if (nRequest > 0) {
prec->nord = nRequest;
prec->udf=FALSE;
if (nord != prec->nord)
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
prec->udf = FALSE;
if (prec->tsel.type == CONSTANT &&
prec->tse == epicsTimeEventDeviceTime)
dbGetTimeStamp(&prec->inp, &prec->time);

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 Lawrence Berkeley Laboratory,The Control Systems
* Group, Systems Engineering Department
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -19,6 +19,7 @@
#include "alarm.h"
#include "dbDefs.h"
#include "dbAccess.h"
#include "dbEvent.h"
#include "recGbl.h"
#include "devSup.h"
#include "subArrayRecord.h"
@@ -67,6 +68,7 @@ static long init_record(subArrayRecord *prec)
static long read_sa(subArrayRecord *prec)
{
long nRequest = prec->indx + prec->nelm;
epicsUInt32 nord = prec->nord;
long ecount;
if (nRequest > prec->malm)
@@ -89,6 +91,8 @@ static long read_sa(subArrayRecord *prec)
ecount = 0;
prec->nord = ecount;
if (nord != prec->nord)
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
if (nRequest > 0 &&
prec->tsel.type == CONSTANT &&

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -67,11 +67,16 @@ static long init_record(waveformRecord *prec)
static long read_wf(waveformRecord *prec)
{
epicsUInt32 nord = prec->nord;
long nRequest = prec->nelm;
dbGetLink(&prec->inp, prec->ftvl, prec->bptr, 0, &nRequest);
if (nRequest > 0) {
prec->nord = nRequest;
if (nord != prec->nord)
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
if (prec->tsel.type == CONSTANT &&
prec->tse == epicsTimeEventDeviceTime)
dbGetTimeStamp(&prec->inp, &prec->time);

View File

@@ -146,9 +146,9 @@ Note: Negative index numbers address from the end of the array, with C<-1> being
=item Square bracket notation C<[start:increment:end]> (shorthand)
The common square bracket notation with can be used in place of JSON.
The common square bracket notation which can be used in place of JSON.
Any parameter may be omitted (keeping the colons) to use the default value.
If only one colon is included, this means C<[start:end]> with a increment of 1.
If only one colon is included, this means C<[start:end]> with an increment of 1.
If only a single parameter is used C<[index]> the filter returns one element.
=item Start index C<"s">

View File

@@ -206,6 +206,14 @@ static long init_record(aSubRecord *prec, int pass)
}
strcpy(prec->onam, prec->snam);
prec->oval = prec->val;
for (i = 0; i < NUM_ARGS; i++) {
epicsUInt32 nev = (&prec->neva)[i];
(&prec->onva)[i] = nev;
if (nev)
memcpy((&prec->ovla)[i], (&prec->vala)[i],
dbValueSize((&prec->ftva)[i]) * nev);
}
return 0;
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2002 Southeastern Universities Research Association, as
* Operator of Thomas Jefferson National Accelerator Facility.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* recAai.c */
@@ -11,7 +11,7 @@
* Original Author: Dave Barker
*
* C E B A F
*
*
* Continuous Electron Beam Accelerator Facility
* Newport News, Virginia, USA.
*
@@ -139,12 +139,12 @@ static long init_record(aaiRecord *prec, int pass)
}
return 0;
}
/* SIML must be a CONSTANT or a PV_LINK or a DB_LINK */
if (prec->siml.type == CONSTANT) {
recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
}
/* must have read_aai function defined */
if (pdset->number < 5 || pdset->read_aai == NULL) {
recGblRecordError(S_dev_missingSup, prec, "aai: init_record");
@@ -204,10 +204,14 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
static long put_array_info(DBADDR *paddr, long nNew)
{
aaiRecord *prec = (aaiRecord *)paddr->precord;
epicsUInt32 nord = prec->nord;
prec->nord = nNew;
if (prec->nord > prec->nelm)
prec->nord = prec->nelm;
if (nord != prec->nord)
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
return 0;
}
@@ -220,7 +224,7 @@ static long get_units(DBADDR *paddr, char *units)
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
break;
break;
case indexof(HOPR):
case indexof(LOPR):
strncpy(units,prec->egu,DB_UNITS_SIZE);
@@ -314,12 +318,11 @@ static void monitor(aaiRecord *prec)
static long readValue(aaiRecord *prec)
{
long status;
struct aaidset *pdset = (struct aaidset *)prec->dset;
long status;
if (prec->pact == TRUE){
status = pdset->read_aai(prec);
return status;
return pdset->read_aai(prec);
}
status = dbGetLink(&prec->siml, DBR_ENUM, &prec->simm, 0, 0);
@@ -327,10 +330,16 @@ static long readValue(aaiRecord *prec)
return status;
if (prec->simm == menuYesNoNO){
return pdset->read_aai(prec);
epicsUInt32 nord = prec->nord;
status = pdset->read_aai(prec);
if (nord != prec->nord)
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
return status;
}
if (prec->simm == menuYesNoYES){
epicsUInt32 nord = prec->nord;
/* Device suport is responsible for buffer
which might be read-only so we may not be
allowed to call dbGetLink on it.
@@ -339,10 +348,13 @@ static long readValue(aaiRecord *prec)
Thus call device now.
*/
recGblSetSevr(prec, SIMM_ALARM, prec->sims);
return pdset->read_aai(prec);
status = pdset->read_aai(prec);
if (nord != prec->nord)
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
return status;
}
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
return -1;
}

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2002 Southeastern Universities Research Association, as
* Operator of Thomas Jefferson National Accelerator Facility.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* recAao.c */
@@ -11,7 +11,7 @@
* Original Author: Dave Barker
*
* C E B A F
*
*
* Continuous Electron Beam Accelerator Facility
* Newport News, Virginia, USA.
*
@@ -204,10 +204,14 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
static long put_array_info(DBADDR *paddr, long nNew)
{
aaoRecord *prec = (aaoRecord *)paddr->precord;
epicsUInt32 nord = prec->nord;
prec->nord = nNew;
if (prec->nord > prec->nelm)
prec->nord = prec->nelm;
if (nord != prec->nord)
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
return 0;
}
@@ -220,7 +224,7 @@ static long get_units(DBADDR *paddr, char *units)
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
break;
break;
case indexof(HOPR):
case indexof(LOPR):
strncpy(units,prec->egu,DB_UNITS_SIZE);
@@ -343,4 +347,3 @@ static long writeValue(aaoRecord *prec)
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
return -1;
}

View File

@@ -4,12 +4,12 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Original Author: Bob Dalesio
* Date: 7-14-89
* Date: 7-14-89
*/
#include <stddef.h>
@@ -405,11 +405,15 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
static long put_array_info(DBADDR *paddr, long nNew)
{
compressRecord *prec = (compressRecord *) paddr->precord;
epicsUInt32 nuse = prec->nuse;
prec->off = (prec->off + nNew) % prec->nsam;
prec->nuse += nNew;
if (prec->nuse > prec->nsam)
prec->nuse = prec->nsam;
if (nuse != prec->nuse)
db_post_events(prec, &prec->nuse, DBE_VALUE | DBE_LOG);
return 0;
}

View File

@@ -22,6 +22,7 @@
#include "dbDefs.h"
#include "epicsPrint.h"
#include "epicsMath.h"
#include "alarm.h"
#include "dbAccess.h"
#include "dbEvent.h"
@@ -225,15 +226,17 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
{
longinRecord *prec=(longinRecord *)paddr->precord;
if(dbGetFieldIndex(paddr) == indexof(VAL)){
pad->upper_alarm_limit = prec->hihi;
pad->upper_warning_limit = prec->high;
pad->lower_warning_limit = prec->low;
pad->lower_alarm_limit = prec->lolo;
} else recGblGetAlarmDouble(paddr,pad);
return(0);
if (dbGetFieldIndex(paddr) == indexof(VAL)){
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN;
}
else
recGblGetAlarmDouble(paddr,pad);
return 0;
}
static void checkAlarms(longinRecord *prec, epicsTimeStamp *timeLast)
{
enum {

View File

@@ -19,6 +19,7 @@
#include "dbDefs.h"
#include "epicsPrint.h"
#include "epicsMath.h"
#include "alarm.h"
#include "dbAccess.h"
#include "dbEvent.h"
@@ -256,15 +257,17 @@ static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
{
longoutRecord *prec=(longoutRecord *)paddr->precord;
if(dbGetFieldIndex(paddr) == indexof(VAL)) {
pad->upper_alarm_limit = prec->hihi;
pad->upper_warning_limit = prec->high;
pad->lower_warning_limit = prec->low;
pad->lower_alarm_limit = prec->lolo;
} else recGblGetAlarmDouble(paddr,pad);
return(0);
if (dbGetFieldIndex(paddr) == indexof(VAL)) {
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN;
}
else
recGblGetAlarmDouble(paddr,pad);
return 0;
}
static void checkAlarms(longoutRecord *prec)
{
epicsInt32 val, hyst, lalm;

View File

@@ -93,6 +93,7 @@ static long readValue(stringinRecord *);
static long init_record(stringinRecord *prec, int pass)
{
STATIC_ASSERT(sizeof(prec->oval)==sizeof(prec->val));
STATIC_ASSERT(sizeof(prec->sval)==sizeof(prec->val));
struct stringindset *pdset;
long status;
@@ -119,7 +120,7 @@ static long init_record(stringinRecord *prec, int pass)
if( pdset->init_record ) {
if((status=(*pdset->init_record)(prec))) return(status);
}
strcpy(prec->oval,prec->val);
strncpy(prec->oval, prec->val, sizeof(prec->val));
return(0);
}
@@ -193,7 +194,7 @@ static long readValue(stringinRecord *prec)
status=dbGetLink(&(prec->siol),DBR_STRING,
prec->sval,0,0);
if (status==0) {
strcpy(prec->val,prec->sval);
strncpy(prec->val, prec->sval, sizeof(prec->val));
prec->udf=FALSE;
}
} else {

View File

@@ -95,6 +95,7 @@ static long writeValue(stringoutRecord *);
static long init_record(stringoutRecord *prec, int pass)
{
STATIC_ASSERT(sizeof(prec->oval)==sizeof(prec->val));
STATIC_ASSERT(sizeof(prec->ivov)==sizeof(prec->val));
struct stringoutdset *pdset;
long status=0;
@@ -121,7 +122,7 @@ static long init_record(stringoutRecord *prec, int pass)
if( pdset->init_record ) {
if((status=(*pdset->init_record)(prec))) return(status);
}
strcpy(prec->oval,prec->val);
strncpy(prec->oval, prec->val, sizeof(prec->val));
return(0);
}
@@ -159,7 +160,7 @@ static long process(stringoutRecord *prec)
break;
case (menuIvoaSet_output_to_IVOV) :
if(prec->pact == FALSE){
strcpy(prec->val,prec->ivov);
strncpy(prec->val, prec->ivov, sizeof(prec->val));
}
status=writeValue(prec); /* write the new value */
break;

Some files were not shown because too many files have changed in this diff Show More