Compare commits
261 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7e42fab3c | ||
|
|
2f28ce94f4 | ||
|
|
732f8b19be | ||
|
|
b03e2f376b | ||
|
|
59c68807b6 | ||
|
|
2e7ed02a60 | ||
|
|
089954aaab | ||
|
|
34e0b2f305 | ||
|
|
ceb13797a6 | ||
|
|
084557bd3e | ||
|
|
aeed7cfbdd | ||
|
|
183c3b2a3e | ||
|
|
cf2fef2405 | ||
|
|
298c8706ec | ||
|
|
49de2ec498 | ||
|
|
0aa6e9603b | ||
|
|
314e09d8ca | ||
|
|
076175386f | ||
|
|
f40d379485 | ||
|
|
445cbb8221 | ||
|
|
a9c8d8d5d3 | ||
|
|
1ff64f72a9 | ||
|
|
f10d0d95b0 | ||
|
|
dfbda1394d | ||
|
|
d05d8807ec | ||
|
|
582a9dbef5 | ||
|
|
b655662131 | ||
|
|
be061e1084 | ||
|
|
91c18c32d4 | ||
|
|
3790ce4452 | ||
|
|
566ab038d2 | ||
|
|
648589e6ab | ||
|
|
841effe9ee | ||
|
|
a9727fd5cb | ||
|
|
fde0485d6b | ||
|
|
cbf917e833 | ||
|
|
45cf2ea5ce | ||
|
|
a95635a018 | ||
|
|
9df39475cd | ||
|
|
bdf01e7a67 | ||
|
|
0dd5f863ef | ||
|
|
38339b6ccf | ||
|
|
2aecf3142a | ||
|
|
1687757752 | ||
|
|
1533a4f13f | ||
|
|
a1aeb23314 | ||
|
|
933e276e1a | ||
|
|
7f02f8a386 | ||
|
|
cb3fb18f40 | ||
|
|
062c75a078 | ||
|
|
b2160bd618 | ||
|
|
5b7f896312 | ||
|
|
a9034bb586 | ||
|
|
f9820577c1 | ||
|
|
e6914f3b80 | ||
|
|
41f1b0ffb5 | ||
|
|
d82d3d3679 | ||
| e48cdb48ac | |||
|
|
3944b32e04 | ||
|
|
a0667a122b | ||
|
|
f2b4c412d3 | ||
|
|
8250339e0d | ||
|
|
803593560d | ||
|
|
bfae080af4 | ||
|
|
6ae3f56560 | ||
|
|
4844fbbd82 | ||
|
|
983937a52f | ||
|
|
6867f97346 | ||
|
|
1d9e9ff4f7 | ||
|
|
eb8ca22704 | ||
|
|
bfd289e85f | ||
|
|
a5bae49dab | ||
|
|
7a612f9524 | ||
|
|
0db8f8ca1b | ||
|
|
dbd6f7e807 | ||
|
|
54cd7e7ba1 | ||
|
|
cbe6173417 | ||
|
|
f64f84744e | ||
|
|
d97a12f095 | ||
|
|
475963453c | ||
|
|
f5a442c0de | ||
|
|
df519ce1a2 | ||
|
|
feb938fae2 | ||
|
|
e068191684 | ||
|
|
33f2d8c4aa | ||
|
|
60a092fa50 | ||
|
|
24f08460bb | ||
|
|
247fea0fa9 | ||
|
|
8a9637568e | ||
|
|
87229fdef0 | ||
|
|
b0418e5274 | ||
|
|
2e89a60c2d | ||
|
|
09ec3af337 | ||
|
|
70e9d46d75 | ||
|
|
1d18aa3e6c | ||
|
|
a85967caea | ||
|
|
a50b850ebd | ||
|
|
6767bcd31e | ||
|
|
81550ac4d3 | ||
| d2d8674cb9 | |||
| 6f193242e0 | |||
| 39e8ccdef4 | |||
| eb8992a750 | |||
| 62fb49f93b | |||
| a5c9db8c8e | |||
| 04e752c83a | |||
| a16ce877e7 | |||
| 15f28f1183 | |||
| 9c18ce007a | |||
| 765af2efea | |||
| 059c385286 | |||
| feb1f9b0df | |||
| 9d9840ad1e | |||
| af73e4cf65 | |||
| ad861a0617 | |||
| 1b88e834d6 | |||
| e000ea4913 | |||
| 06f1a8ec23 | |||
| cf2658be53 | |||
| 74a403090b | |||
| dc123a0a37 | |||
|
|
7eee262486 | ||
|
|
a10379327c | ||
|
|
b37bfe3ed0 | ||
|
|
41d86ecd7a | ||
|
|
961dd2bc5d | ||
|
|
db4ad455d2 | ||
|
|
74a90d141b | ||
|
|
ed9d7550f2 | ||
|
|
87c68663f3 | ||
|
|
3881328f2f | ||
|
|
9722e707fd | ||
|
|
10e9db3710 | ||
|
|
ec31feea05 | ||
|
|
d0ff3c7672 | ||
|
|
178d5779a2 | ||
|
|
00334c981c | ||
|
|
5b5fd8004c | ||
|
|
c7db681e25 | ||
|
|
3ff62f4ddb | ||
|
|
b34859fb86 | ||
|
|
953dd2b7f9 | ||
|
|
3128fdb930 | ||
|
|
47f295fecb | ||
|
|
4816a3c04b | ||
|
|
e0950643bb | ||
|
|
252983efca | ||
|
|
7ca26c515a | ||
|
|
a961ca2fe5 | ||
|
|
a2fe07aa76 | ||
|
|
a69803f278 | ||
|
|
ee38b99e0f | ||
|
|
0a01c38698 | ||
|
|
9efefad955 | ||
|
|
0c62fc8d84 | ||
|
|
292dfe8e16 | ||
|
|
1c93726ee6 | ||
|
|
643d58fd04 | ||
|
|
f08b412a18 | ||
|
|
77574022a1 | ||
|
|
75a1b82322 | ||
|
|
73fec88168 | ||
|
|
2461dc3574 | ||
|
|
704e6251e6 | ||
|
|
f70c17ee69 | ||
|
|
96e3e678e9 | ||
|
|
9d4b652c5e | ||
|
|
0d3cc5a20a | ||
|
|
9255256f15 | ||
|
|
4685f7567b | ||
|
|
e5f8683144 | ||
|
|
4f63bf139f | ||
|
|
d7d142650b | ||
|
|
eac3d2719b | ||
|
|
a3d0699b84 | ||
|
|
a16bf2dc38 | ||
|
|
13936680e9 | ||
|
|
7b6c67b51b | ||
|
|
33febb52ba | ||
|
|
44149c170e | ||
|
|
db6825f62e | ||
|
|
6905ded0d0 | ||
|
|
4f31205188 | ||
|
|
90d9be1c00 | ||
|
|
b93f92c843 | ||
|
|
83458421aa | ||
|
|
89e3c582b5 | ||
|
|
623539c3e8 | ||
|
|
2a0df61974 | ||
|
|
6e3a15e318 | ||
|
|
86b1882186 | ||
|
|
03e613cec0 | ||
|
|
177c377b81 | ||
|
|
1cf831939a | ||
|
|
26cd81d35f | ||
|
|
31811e53b3 | ||
|
|
128d2a93c8 | ||
|
|
67583b4bda | ||
|
|
8a39ca7489 | ||
|
|
b9bc836d1e | ||
|
|
9b5034f307 | ||
|
|
a6812c5869 | ||
|
|
b89494a840 | ||
|
|
771ad6a442 | ||
|
|
84c86e67e8 | ||
|
|
cac3e2dc3b | ||
|
|
8ff6ce4821 | ||
|
|
44ea66aaaf | ||
|
|
c9c4eea0f8 | ||
|
|
78ce2dac05 | ||
|
|
b2285bb8aa | ||
|
|
f79c69f0a0 | ||
|
|
e03c7edfe5 | ||
|
|
398fdee33e | ||
|
|
59cb5ba6a0 | ||
|
|
2db2f1a53f | ||
|
|
b811d3402f | ||
|
|
e75a72ef76 | ||
|
|
33e099a51b | ||
|
|
d3a8a49552 | ||
|
|
96998f55e0 | ||
|
|
b57f02ece2 | ||
|
|
b0db6568ea | ||
|
|
30812c23f0 | ||
|
|
5cfff383b2 | ||
|
|
345cfcffa8 | ||
|
|
deb9dbcd77 | ||
|
|
96259b7bdc | ||
|
|
25576c316a | ||
|
|
2d3de1916b | ||
|
|
16ddcaeaed | ||
|
|
297206e247 | ||
|
|
63bf8a8219 | ||
|
|
ec7193d0be | ||
|
|
1f95d0db12 | ||
|
|
e02c5c3026 | ||
|
|
8e9d75ad71 | ||
|
|
630663caa8 | ||
|
|
736075daf6 | ||
|
|
9ef3b77348 | ||
|
|
5e1bad2b34 | ||
|
|
a9606dbf6e | ||
|
|
409ee26fae | ||
|
|
9a4787155c | ||
|
|
84dba0d2b7 | ||
|
|
87f6c3dec9 | ||
|
|
940814becf | ||
|
|
68a1a529b2 | ||
|
|
ce38caf41b | ||
|
|
f03f10e664 | ||
|
|
b4f4fb853d | ||
|
|
b518ebe85b | ||
|
|
e461d782f4 | ||
|
|
ef2a381e92 | ||
|
|
265d4962a4 | ||
|
|
db9267bbd5 | ||
|
|
1cf3fa9ba9 | ||
|
|
3e8b0028dc | ||
|
|
d8f18c27f4 | ||
|
|
801c01b9b6 | ||
|
|
0c1874bbfe |
131
.appveyor.yml
Normal file
131
.appveyor.yml
Normal file
@@ -0,0 +1,131 @@
|
||||
# .appveyor.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
# Version format
|
||||
version: base-{branch}-{build}
|
||||
|
||||
#---------------------------------#
|
||||
# build cache #
|
||||
#---------------------------------#
|
||||
# The AppVeyor cache allowance is way too small (1GB per account across all projects, branches and jobs)
|
||||
# to be used for the dependency builds.
|
||||
|
||||
cache:
|
||||
- C:\Users\appveyor\.tools
|
||||
|
||||
#---------------------------------#
|
||||
# repository cloning #
|
||||
#---------------------------------#
|
||||
|
||||
# Called at very beginning, before repo cloning
|
||||
init:
|
||||
# Set autocrlf to make batch files work
|
||||
- git config --global core.autocrlf true
|
||||
|
||||
# Set clone depth (do not fetch complete history)
|
||||
clone_depth: 5
|
||||
|
||||
# Skipping commits affecting only specific files
|
||||
skip_commits:
|
||||
files:
|
||||
- 'documentation/*'
|
||||
- 'templates/*'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
|
||||
#---------------------------------#
|
||||
# build matrix configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# Build Configurations: dll/static, regular/debug
|
||||
configuration:
|
||||
- dynamic
|
||||
- static
|
||||
- dynamic-debug
|
||||
- static-debug
|
||||
|
||||
# Environment variables: compiler toolchain, base version, setup file, ...
|
||||
environment:
|
||||
# common / default variables for all jobs
|
||||
SETUP_PATH: .ci-local:.ci
|
||||
BASE: SELF
|
||||
|
||||
matrix:
|
||||
- CMP: vs2019
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- CMP: vs2017
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
- CMP: vs2015
|
||||
- CMP: vs2013
|
||||
- CMP: vs2012
|
||||
- CMP: vs2010
|
||||
- CMP: mingw
|
||||
|
||||
# Platform: processor architecture
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
# Matrix configuration: exclude sets of jobs
|
||||
matrix:
|
||||
exclude:
|
||||
# VS2012 and older installs don't have the 64 bit compiler
|
||||
- platform: x64
|
||||
CMP: vs2012
|
||||
- platform: x64
|
||||
CMP: vs2010
|
||||
- platform: x64
|
||||
CMP: vs2008
|
||||
# Exclude more jobs to reduce build time
|
||||
# Skip 32-bit for "middle-aged" compilers
|
||||
- platform: x86
|
||||
CMP: vs2017
|
||||
- platform: x86
|
||||
CMP: vs2015
|
||||
|
||||
#---------------------------------#
|
||||
# building & testing #
|
||||
#---------------------------------#
|
||||
|
||||
install:
|
||||
- cmd: git submodule update --init --recursive
|
||||
- cmd: python .ci/appveyor/do.py prepare
|
||||
|
||||
build_script:
|
||||
- cmd: python .ci/appveyor/do.py build
|
||||
|
||||
test_script:
|
||||
- cmd: python .ci/appveyor/do.py test
|
||||
|
||||
on_finish:
|
||||
- ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||
- cmd: python .ci/appveyor/do.py build test-results -s
|
||||
|
||||
#---------------------------------#
|
||||
# debugging #
|
||||
#---------------------------------#
|
||||
|
||||
## if you want to connect by remote desktop to a failed build, uncomment these lines
|
||||
## note that you will need to connect within the usual build timeout limit (60 minutes)
|
||||
## so you may want to adjust the build matrix above to just build the one of interest
|
||||
|
||||
# print the connection info
|
||||
#init:
|
||||
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
# block a failed build (until the watchdog barks)
|
||||
#on_failure:
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
#---------------------------------#
|
||||
# notifications #
|
||||
#---------------------------------#
|
||||
|
||||
notifications:
|
||||
|
||||
- provider: Email
|
||||
to:
|
||||
- core-talk@aps.anl.gov
|
||||
on_build_success: false
|
||||
|
||||
- provider: GitHubPullRequest
|
||||
1
.ci
Submodule
1
.ci
Submodule
Submodule .ci added at e91a588370
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,6 +7,7 @@
|
||||
/include/
|
||||
/templates/
|
||||
/configure/*.local
|
||||
/.tests-failed
|
||||
O.*/
|
||||
/QtC-*
|
||||
*.orig
|
||||
|
||||
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule ".ci"]
|
||||
path = .ci
|
||||
url = https://github.com/epics-base/ci-scripts
|
||||
branch = master
|
||||
107
.travis.yml
107
.travis.yml
@@ -1,32 +1,93 @@
|
||||
sudo: false
|
||||
dist: trusty
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
# .travis.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
dist: xenial
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache
|
||||
|
||||
env:
|
||||
- CMPLR=gcc
|
||||
- CMPLR=gcc EXTRA=CMD_CXXFLAGS=-std=c++11
|
||||
- CMPLR=gcc STATIC=YES
|
||||
- CMPLR=clang
|
||||
- CMPLR=clang STATIC=YES
|
||||
- WINE=32 TEST=NO STATIC=YES
|
||||
- WINE=32 TEST=NO STATIC=NO
|
||||
- RTEMS=4.10 TEST=NO
|
||||
- RTEMS=4.9 TEST=NO
|
||||
global:
|
||||
- SETUP_PATH=.ci-local:.ci
|
||||
- BASE=SELF
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# for all EPICS builds
|
||||
- libreadline6-dev
|
||||
- libncurses5-dev
|
||||
- perl
|
||||
# for clang compiler
|
||||
- clang
|
||||
# for mingw builds (32bit and 64bit)
|
||||
- g++-mingw-w64-i686
|
||||
- bison
|
||||
- flex
|
||||
- texinfo
|
||||
- install-info
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache
|
||||
install: sh ci/travis-prepare.sh </dev/null
|
||||
script: sh ci/travis-build.sh </dev/null
|
||||
- g++-mingw-w64-x86-64
|
||||
# for RTEMS cross builds
|
||||
- qemu-system-x86
|
||||
homebrew:
|
||||
packages:
|
||||
# for all EPICS builds
|
||||
- bash
|
||||
update: true
|
||||
|
||||
install:
|
||||
- ./.ci/travis/prepare.sh
|
||||
|
||||
script:
|
||||
- ./.ci/travis/build.sh
|
||||
|
||||
# Define build jobs
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
||||
# Different configurations of default gcc and clang
|
||||
# (the DIST settings are just FYI on the travis-ci.org site)
|
||||
- dist: bionic
|
||||
env: DIST=bionic
|
||||
|
||||
- env: DIST=xenial
|
||||
|
||||
- dist: bionic
|
||||
env: DIST=bionic EXTRA="CMD_CXXFLAGS=-std=c++11"
|
||||
|
||||
- dist: trusty
|
||||
env: DIST=trusty STATIC=YES EXTRA="CMD_CXXFLAGS=-std=c++11"
|
||||
|
||||
- dist: bionic
|
||||
compiler: clang
|
||||
env: DIST=bionic
|
||||
|
||||
- compiler: clang
|
||||
env: DIST=xenial
|
||||
|
||||
- dist: trusty
|
||||
compiler: clang
|
||||
env: DIST=trusty STATIC=YES
|
||||
|
||||
# Cross-compilations to Windows using MinGW and WINE
|
||||
|
||||
- env: WINE=32 TEST=NO STATIC=YES
|
||||
compiler: mingw
|
||||
|
||||
- env: WINE=32 TEST=NO STATIC=NO
|
||||
compiler: mingw
|
||||
|
||||
# Cross-compilation to RTEMS
|
||||
|
||||
- env: RTEMS=4.10 TEST=NO
|
||||
|
||||
- env: RTEMS=4.9 TEST=NO
|
||||
|
||||
# MacOS build
|
||||
|
||||
- os: osx
|
||||
env:
|
||||
- EXTRA="CMD_CFLAGS=-mmacosx-version-min=10.7"
|
||||
- EXTRA1="CMD_CXXFLAGS=-mmacosx-version-min=10.7 -std=c++11 -stdlib=libc++"
|
||||
- EXTRA2="CMD_LDXFLAGS=-mmacosx-version-min=10.7 -std=c++11 -stdlib=libc++"
|
||||
compiler: clang
|
||||
|
||||
85
appveyor.yml
85
appveyor.yml
@@ -1,85 +0,0 @@
|
||||
# AppVeyor configuration for EPICS Base
|
||||
|
||||
# Ralph Lange <ralph.lange@gmx.de>
|
||||
# Copyright (c) 2016-2017 ITER Organization
|
||||
|
||||
# Version format
|
||||
version: base-{branch}-{build}
|
||||
|
||||
#---------------------------------#
|
||||
# repository cloning #
|
||||
#---------------------------------#
|
||||
|
||||
# Called at very beginning, before repo cloning
|
||||
init:
|
||||
# Set autocrlf to make batch files work
|
||||
- git config --global core.autocrlf true
|
||||
|
||||
# Set clone depth (do not fetch complete history)
|
||||
clone_depth: 2
|
||||
|
||||
# Skipping commits affecting only specific files
|
||||
skip_commits:
|
||||
files:
|
||||
- 'documentation/*'
|
||||
- 'templates/*'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
|
||||
#---------------------------------#
|
||||
# build matrix configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# Build Configurations: dll/static, regular/debug
|
||||
configuration:
|
||||
- dynamic
|
||||
- static
|
||||
- dynamic-debug
|
||||
- static-debug
|
||||
|
||||
# Environment variables: compiler toolchain
|
||||
environment:
|
||||
matrix:
|
||||
- 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
|
||||
|
||||
# Platform: architecture
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
# Matrix configuration: allow specific failing jobs
|
||||
matrix:
|
||||
exclude:
|
||||
# VS Express installs don't have the 64 bit compiler
|
||||
- platform: x64
|
||||
TOOLCHAIN: 10.0
|
||||
|
||||
#---------------------------------#
|
||||
# building & testing #
|
||||
#---------------------------------#
|
||||
|
||||
install:
|
||||
- cmd: ci/appveyor-prepare.bat
|
||||
|
||||
build_script:
|
||||
- cmd: ci/appveyor-make.bat
|
||||
|
||||
test_script:
|
||||
- cmd: ci/appveyor-make.bat runtests
|
||||
|
||||
#---------------------------------#
|
||||
# notifications #
|
||||
#---------------------------------#
|
||||
|
||||
notifications:
|
||||
|
||||
- provider: Slack
|
||||
incoming_webhook:
|
||||
secure: RYOm3FIUYeZGjWKaeTVKwq+C3fzK54AKwbmAoECED45mex3lN+8HmrC845a6mg9xPUJ/ND51RopWVaKDD9/UzaM0SO195RQLKqUTIUafiuM=
|
||||
@@ -1,137 +0,0 @@
|
||||
:: Universal build script for AppVeyor (https://ci.appveyor.com/)
|
||||
:: Environment:
|
||||
:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/cygwin/mingw]
|
||||
:: CONFIGURATION - determines EPICS build [dynamic/static]
|
||||
:: PLATFORM - architecture [x86/x64]
|
||||
::
|
||||
:: All command line args are passed to make
|
||||
|
||||
Setlocal EnableDelayedExpansion
|
||||
|
||||
set "ST="
|
||||
if /i "%CONFIGURATION%"=="static" set ST=-static
|
||||
|
||||
set OS=64BIT
|
||||
if "%PLATFORM%"=="x86" set OS=32BIT
|
||||
|
||||
echo [INFO] Platform: %OS%
|
||||
|
||||
:: Use parallel make, except for 3.14
|
||||
set "MAKEARGS=-j2 -Otarget"
|
||||
if "%APPVEYOR_REPO_BRANCH%"=="3.14" set MAKEARGS=
|
||||
|
||||
if "%TOOLCHAIN%"=="cygwin" (
|
||||
set "MAKE=make"
|
||||
if "%OS%"=="64BIT" (
|
||||
set "EPICS_HOST_ARCH=cygwin-x86_64"
|
||||
set "INCLUDE=C:\cygwin64\include;%INCLUDE%"
|
||||
set "PATH=C:\cygwin64\bin;%PATH%"
|
||||
echo [INFO] Cygwin Toolchain 64bit
|
||||
) else (
|
||||
set "EPICS_HOST_ARCH=cygwin-x86"
|
||||
set "INCLUDE=C:\cygwin\include;%INCLUDE%"
|
||||
set "PATH=C:\cygwin\bin;%PATH%"
|
||||
echo [INFO] Cygwin Toolchain 32bit
|
||||
)
|
||||
echo [INFO] Compiler Version
|
||||
gcc -v
|
||||
goto Finish
|
||||
)
|
||||
|
||||
if "%TOOLCHAIN%"=="mingw" (
|
||||
set "MAKE=mingw32-make"
|
||||
if "%OS%"=="64BIT" (
|
||||
set "EPICS_HOST_ARCH=windows-x64-mingw"
|
||||
set "INCLUDE=C:\tools\mingw64\include;%INCLUDE%"
|
||||
set "PATH=C:\tools\mingw64\bin;%PATH%"
|
||||
echo [INFO] MinGW Toolchain 64bit
|
||||
) else (
|
||||
set "EPICS_HOST_ARCH=win32-x86-mingw"
|
||||
set "INCLUDE=C:\tools\mingw32\include;%INCLUDE%"
|
||||
set "PATH=C:\tools\mingw32\bin;%PATH%"
|
||||
echo [INFO] MinGW Toolchain 32bit
|
||||
)
|
||||
echo [INFO] Compiler Version
|
||||
gcc -v
|
||||
goto Finish
|
||||
)
|
||||
|
||||
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
|
||||
if !ERRORLEVEL! NEQ 0 (
|
||||
call "%VSINSTALL%\VC\vcvarsall.bat" x86_amd64
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
)
|
||||
goto MSFound
|
||||
)
|
||||
if exist "%VSINSTALL%\VC\bin\amd64\vcvars64.bat" (
|
||||
call "%VSINSTALL%\VC\bin\amd64\vcvars64.bat"
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
goto MSFound
|
||||
)
|
||||
) 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
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
goto MSFound
|
||||
)
|
||||
if exist "%VSINSTALL%\Common7\Tools\vsvars32.bat" (
|
||||
call "%VSINSTALL%\Common7\Tools\vsvars32.bat"
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
goto MSFound
|
||||
)
|
||||
)
|
||||
|
||||
:MSMissing
|
||||
echo [INFO] Installation for MSVC Toolchain %TOOLCHAIN% / %OS% seems to be missing
|
||||
exit 1
|
||||
|
||||
:MSFound
|
||||
echo [INFO] Microsoft Visual Studio Toolchain %TOOLCHAIN%
|
||||
echo [INFO] Compiler Version
|
||||
cl
|
||||
|
||||
:Finish
|
||||
echo [INFO] EPICS_HOST_ARCH: %EPICS_HOST_ARCH%
|
||||
echo [INFO] Make version
|
||||
%MAKE% --version
|
||||
echo [INFO] Perl version
|
||||
perl --version
|
||||
|
||||
%MAKE% %MAKEARGS% %*
|
||||
@@ -1,70 +0,0 @@
|
||||
:: Build script for AppVeyor (https://ci.appveyor.com/)
|
||||
:: Environment:
|
||||
:: TOOLCHAIN - Toolchain Version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
|
||||
:: CONFIGURATION - determines EPICS build [dynamic/static, -debug]
|
||||
:: PLATFORM - "x86" -> use 32bit architecture
|
||||
::
|
||||
:: Prepares an Appveyor build by excuting the following steps
|
||||
:: - Set up configure\CONFIG_SITE for static vs. dynamic build
|
||||
:: - Install Cygwin / Mingw (TOOLCHAIN setting) in the in the appropriate flavor
|
||||
:: - Download and install Make-4.1 from EPICS download page
|
||||
|
||||
Setlocal EnableDelayedExpansion
|
||||
|
||||
set OS=64BIT
|
||||
if "%PLATFORM%"=="x86" set OS=32BIT
|
||||
|
||||
echo [INFO] Platform: %OS%
|
||||
|
||||
if "%TOOLCHAIN%"=="cygwin" (
|
||||
echo.%CONFIGURATION% | findstr /C:"static">nul && (
|
||||
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
|
||||
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
|
||||
echo [INFO] EPICS set up for static build
|
||||
) || (
|
||||
echo [INFO] EPICS set up for dynamic build
|
||||
)
|
||||
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
|
||||
echo HOST_OPT=NO>> configure\CONFIG_SITE
|
||||
echo [INFO] EPICS set up for debug build
|
||||
) || (
|
||||
echo [INFO] EPICS set up for optimized build
|
||||
)
|
||||
if "%OS%"=="64BIT" (
|
||||
echo [INFO] Installing Cygwin 64bit and dependencies
|
||||
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86_64.exe', 'C:\cygwin64\setup-x86_64.exe')"
|
||||
C:\cygwin64\setup-x86_64.exe -q -P "libreadline-devel,libncursesw-devel"
|
||||
) else (
|
||||
echo [INFO] Installing Cygwin 32bit and dependencies
|
||||
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86.exe', 'C:\cygwin\setup-x86.exe')"
|
||||
C:\cygwin\setup-x86.exe -q -P "libreadline-devel,libncursesw-devel"
|
||||
)
|
||||
)
|
||||
|
||||
if "%TOOLCHAIN%"=="mingw" (
|
||||
echo.%CONFIGURATION% | findstr /C:"static">nul && (
|
||||
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
|
||||
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
|
||||
echo [INFO] EPICS set up for static build
|
||||
) || (
|
||||
echo [INFO] EPICS set up for dynamic build
|
||||
)
|
||||
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
|
||||
echo HOST_OPT=NO>> configure\CONFIG_SITE
|
||||
echo [INFO] EPICS set up for debug build
|
||||
) || (
|
||||
echo [INFO] EPICS set up for optimized build
|
||||
)
|
||||
if "%OS%"=="64BIT" (
|
||||
echo [INFO] Installing MinGW 64bit
|
||||
cinst mingw || cinst mingw
|
||||
) else (
|
||||
echo [INFO] Installing MinGW 32bit
|
||||
cinst mingw --x86 || cinst mingw --x86
|
||||
)
|
||||
)
|
||||
|
||||
echo [INFO] Installing Make 4.1
|
||||
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
|
||||
@@ -1,90 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e -x
|
||||
|
||||
die() {
|
||||
echo "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
ticker() {
|
||||
while true
|
||||
do
|
||||
sleep 60
|
||||
date -R
|
||||
[ -r "$1" ] && tail -n10 "$1"
|
||||
done
|
||||
}
|
||||
|
||||
CACHEKEY=1
|
||||
|
||||
EPICS_HOST_ARCH=`perl src/tools/EpicsHostArch.pl`
|
||||
|
||||
[ -e configure/os/CONFIG_SITE.Common.linux-x86 ] || die "Wrong location: $PWD"
|
||||
|
||||
case "$CMPLR" in
|
||||
clang)
|
||||
echo "Host compiler is clang"
|
||||
cat << EOF >> configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH
|
||||
GNU = NO
|
||||
CMPLR_CLASS = clang
|
||||
CC = clang
|
||||
CCC = clang++
|
||||
EOF
|
||||
;;
|
||||
*) echo "Host compiler is default";;
|
||||
esac
|
||||
|
||||
if [ "$STATIC" = "YES" ]
|
||||
then
|
||||
echo "Build static libraries/executables"
|
||||
cat << EOF >> configure/CONFIG_SITE
|
||||
SHARED_LIBRARIES=NO
|
||||
STATIC_BUILD=YES
|
||||
EOF
|
||||
fi
|
||||
|
||||
# requires wine and g++-mingw-w64-i686
|
||||
if [ "$WINE" = "32" ]
|
||||
then
|
||||
echo "Cross mingw32"
|
||||
sed -i -e '/CMPLR_PREFIX/d' configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
|
||||
cat << EOF >> configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
|
||||
CMPLR_PREFIX=i686-w64-mingw32-
|
||||
EOF
|
||||
cat << EOF >> configure/CONFIG_SITE
|
||||
CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw
|
||||
EOF
|
||||
fi
|
||||
|
||||
# set RTEMS to eg. "4.9" or "4.10"
|
||||
# requires qemu, bison, flex, texinfo, install-info
|
||||
if [ -n "$RTEMS" ]
|
||||
then
|
||||
echo "Cross RTEMS${RTEMS} for pc386"
|
||||
install -d /home/travis/.cache
|
||||
curl -L "https://github.com/mdavidsaver/rsb/releases/download/travis-20160306-2/rtems${RTEMS}-i386-trusty-20190306-2.tar.gz" \
|
||||
| tar -C /home/travis/.cache -xj
|
||||
|
||||
sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' configure/os/CONFIG_SITE.Common.RTEMS
|
||||
cat << EOF >> configure/os/CONFIG_SITE.Common.RTEMS
|
||||
RTEMS_VERSION=$RTEMS
|
||||
RTEMS_BASE=/home/travis/.cache/rtems${RTEMS}-i386
|
||||
EOF
|
||||
cat << EOF >> configure/CONFIG_SITE
|
||||
CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386
|
||||
EOF
|
||||
|
||||
# find local qemu-system-i386
|
||||
export PATH="$HOME/.cache/qemu/usr/bin:$PATH"
|
||||
echo -n "Using QEMU: "
|
||||
type qemu-system-i386 || echo "Missing qemu"
|
||||
EXTRA=RTEMS_QEMU_FIXUPS=YES
|
||||
fi
|
||||
|
||||
make -j2 $EXTRA
|
||||
|
||||
if [ "$TEST" != "NO" ]
|
||||
then
|
||||
make tapfiles
|
||||
make -s test-results
|
||||
fi
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e -x
|
||||
|
||||
die() {
|
||||
echo "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
CURDIR="$PWD"
|
||||
|
||||
QDIR="$HOME/.cache/qemu"
|
||||
|
||||
if [ -n "$RTEMS" -a "$TEST" = "YES" ]
|
||||
then
|
||||
git clone --quiet --branch vme --depth 10 https://github.com/mdavidsaver/qemu.git "$HOME/.build/qemu"
|
||||
cd "$HOME/.build/qemu"
|
||||
|
||||
HEAD=`git log -n1 --pretty=format:%H`
|
||||
echo "HEAD revision $HEAD"
|
||||
|
||||
[ -e "$HOME/.cache/qemu/built" ] && BUILT=`cat "$HOME/.cache/qemu/built"`
|
||||
echo "Cached revision $BUILT"
|
||||
|
||||
if [ "$HEAD" != "$BUILT" ]
|
||||
then
|
||||
echo "Building QEMU"
|
||||
git submodule --quiet update --init
|
||||
|
||||
install -d "$HOME/.build/qemu/build"
|
||||
cd "$HOME/.build/qemu/build"
|
||||
|
||||
"$HOME/.build/qemu/configure" --prefix="$HOME/.cache/qemu/usr" --target-list=i386-softmmu --disable-werror
|
||||
make -j2
|
||||
make install
|
||||
|
||||
echo "$HEAD" > "$HOME/.cache/qemu/built"
|
||||
fi
|
||||
fi
|
||||
|
||||
cd "$CURDIR"
|
||||
@@ -68,7 +68,6 @@ DBTOMENUH = $(PERL) $(TOOLS)/dbdToMenuH.pl
|
||||
REGISTERRECORDDEVICEDRIVER = $(PERL) $(TOOLS)/registerRecordDeviceDriver.pl
|
||||
CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl)
|
||||
FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
|
||||
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
|
||||
|
||||
#-------------------------------------------------------
|
||||
# tools for installing libraries and products
|
||||
@@ -82,6 +81,15 @@ INSTALL_LIBRARY = $(INSTALL)
|
||||
MKMF = $(PERL) $(TOOLS)/mkmf.pl
|
||||
REPLACEVAR = $(PERL) $(TOOLS)/replaceVAR.pl
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Tools for testing
|
||||
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
|
||||
PROVE = $(PERL) $(TOOLS)/epicsProve.pl
|
||||
PROVE.tap = $(PROVE) --ext .tap --exec "$(CAT)"
|
||||
|
||||
TEST_FAILURE_FILE = $(TOP)/.tests-failed
|
||||
PROVE_FAILURE = echo $(abspath .)>> $(TEST_FAILURE_FILE)
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# private versions of lex/yacc from EPICS
|
||||
EYACC = $(TOOLS)/antelope$(HOSTEXE)
|
||||
|
||||
@@ -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 the file LICENSE that is included with this distribution.
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
#
|
||||
# EPICS Version information
|
||||
@@ -27,23 +27,19 @@ EPICS_VERSION = 3
|
||||
EPICS_REVISION = 15
|
||||
|
||||
# EPICS_MODIFICATION must be a number >=0 and <256
|
||||
EPICS_MODIFICATION = 6
|
||||
EPICS_MODIFICATION = 8
|
||||
|
||||
# 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
|
||||
#EPICS_DEV_SNAPSHOT=-pre2-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-rc1
|
||||
#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
|
||||
|
||||
|
||||
@@ -24,40 +24,41 @@
|
||||
|
||||
# Site-specific environment settings
|
||||
|
||||
# Time service:
|
||||
# EPICS_TIMEZONE
|
||||
# Local timezone info for vxWorks and RTEMS. The format is
|
||||
# <name>::<minutesWest>:<startDST>:<endDST>
|
||||
# where <name> is only used by strftime() for %Z conversions,
|
||||
# and <startDST> and <endDST> are mmddhh - that is month,day,hour
|
||||
# e.g. for ANL in 2018: EPICS_TIMEZONE=CUS::360:031102:110402
|
||||
# The future dates below assume the rules don't get changed;
|
||||
# see http://www.timeanddate.com/time/dst/2018.html to check.
|
||||
#
|
||||
# DST for 2018 US: Mar 11 - Nov 04
|
||||
# EU: Mar 25 - Oct 28
|
||||
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: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: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: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:103003
|
||||
## Time service:
|
||||
# EPICS_TZ
|
||||
# Local timezone rules for vxWorks and RTEMS. The value follows the Posix
|
||||
# TZ environment variable's Mm.n.d/h format (see the IBM link below for
|
||||
# details). If TZ hasn't already been set when the osdTime timeRegister()
|
||||
# C++ static constructor runs, this parameter will be copied into the TZ
|
||||
# environment variable. Once the OS clock has been synchronized to NTP the
|
||||
# routine tz2timezone() will be run to convert TZ into the TIMEZONE
|
||||
# variable format that VxWorks needs.
|
||||
# https://developer.ibm.com/articles/au-aix-posix/
|
||||
|
||||
# Japan Standard Time, no DST:
|
||||
#EPICS_TZ = "JST-9"
|
||||
|
||||
# Central European (Summer) Time:
|
||||
#EPICS_TZ = "CET-1CEST,M3.5.0/2,M10.5.0/3"
|
||||
|
||||
# Greenwich Mean/British Summer Time:
|
||||
#EPICS_TZ = "GMT0BST,M3.5.0/1,M10.5.0/2"
|
||||
|
||||
# US Eastern Standard/Daylight Time:
|
||||
#EPICS_TZ = "EST5EDT,M3.2.0/2,M11.1.0/2"
|
||||
|
||||
# US Central Standard/Daylight Time:
|
||||
EPICS_TZ = "CST6CDT,M3.2.0/2,M11.1.0/2"
|
||||
|
||||
# US Mountain Standard/Daylight Time:
|
||||
#EPICS_TZ = "MST7MDT,M3.2.0/2,M11.1.0/2"
|
||||
|
||||
# US Pacific Standard/Daylight Time:
|
||||
#EPICS_TZ = "PST8PDT,M3.2.0/2,M11.1.0/2"
|
||||
|
||||
# US Hawaiian Standard Time, no DST:
|
||||
#EPICS_TZ = "HST10"
|
||||
|
||||
|
||||
# EPICS_TS_NTP_INET
|
||||
# NTP time server ip address for VxWorks and RTEMS.
|
||||
|
||||
@@ -105,17 +105,17 @@ PRODTARGETS += $(PRODNAME) $(MUNCHNAME) $(CTDT_SRCS) $(CTDT_OBJS) $(NMS)
|
||||
TESTPRODTARGETS += $(TESTPRODNAME) $(TESTMUNCHNAME)
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Test specifications and test result files
|
||||
# Test result files
|
||||
#
|
||||
ifneq (,$(strip $(TESTS)))
|
||||
TARGETS += testspec
|
||||
endif
|
||||
|
||||
# Enable testing if this host can run tests on the current target
|
||||
ifneq (,$(findstring $(T_A),$(EPICS_HOST_ARCH) $(CROSS_COMPILER_RUNTEST_ARCHS)))
|
||||
# Enable testing if this host can run tests for the current target
|
||||
ifneq (,$(filter $(T_A), $(EPICS_HOST_ARCH) $(CROSS_COMPILER_RUNTEST_ARCHS)))
|
||||
RUNTESTS_ENABLED = YES
|
||||
TAPFILES += $(TESTSCRIPTS:.t=.tap)
|
||||
JUNITFILES += $(TAPFILES:.tap=.xml)
|
||||
TESTSCRIPTS.t = $(filter %.t, $(TESTSCRIPTS))
|
||||
TAPFILES.t += $(TESTSCRIPTS.t:.t=.tap)
|
||||
JUNITFILES.t += $(TESTSCRIPTS.t:.t=.xml)
|
||||
TAPFILES += $(TAPFILES.t)
|
||||
JUNITFILES += $(JUNITFILES.t)
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------
|
||||
@@ -335,23 +335,22 @@ $(MODNAME): %$(MODEXT): %$(EXE)
|
||||
#---------------------------------------------------------------
|
||||
# Automated testing
|
||||
|
||||
runtests: $(TESTSCRIPTS)
|
||||
runtests: run-tap-tests
|
||||
run-tap-tests: $(TESTSCRIPTS.t)
|
||||
ifneq ($(TESTSCRIPTS.t),)
|
||||
ifdef RUNTESTS_ENABLED
|
||||
-$(PERL) -MTest::Harness -e 'runtests @ARGV if @ARGV;' $^
|
||||
$(PROVE) --failures --color $^ || $(PROVE_FAILURE)
|
||||
endif
|
||||
endif
|
||||
|
||||
testspec: $(TESTSCRIPTS)
|
||||
@$(RM) $@
|
||||
@echo OS-class: $(OS_CLASS) > $@
|
||||
@echo Target-arch: $(T_A) >> $@
|
||||
$(if $^, @echo Tests: $^ >> $@)
|
||||
$(if $(TESTFILES), @echo Files: $(TESTFILES) >> $@)
|
||||
$(if $(TESTSPEC_$(OS_CLASS)), @echo "Harness: $(TESTSPEC_$(OS_CLASS))" >> $@)
|
||||
tapfiles: $(TAPFILES)
|
||||
junitfiles: $(JUNITFILES)
|
||||
|
||||
test-results: tapfiles
|
||||
ifneq ($(TAPFILES),)
|
||||
test-results: tap-results
|
||||
tap-results: $(TAPFILES)
|
||||
ifneq ($(strip $(TAPFILES)),)
|
||||
ifdef RUNTESTS_ENABLED
|
||||
prove --failures --ext .tap --exec "$(CAT)" --color $(TAPFILES)
|
||||
$(PROVE.tap) --failures --color $^ || $(PROVE_FAILURE)
|
||||
endif
|
||||
|
||||
CURRENT_TAPFILES := $(wildcard $(TAPFILES))
|
||||
@@ -366,16 +365,13 @@ ifneq ($(CURRENT_JUNITFILES),)
|
||||
$(RM) $(CURRENT_JUNITFILES)
|
||||
endif
|
||||
|
||||
tapfiles: $(TESTSCRIPTS) $(TAPFILES)
|
||||
junitfiles: $(JUNITFILES)
|
||||
|
||||
# A .tap file is the output from running the associated test script
|
||||
%.tap: %.t
|
||||
$(TAPFILES.t): %.tap: %.t
|
||||
ifdef RUNTESTS_ENABLED
|
||||
-$(PERL) $< -tap > $@
|
||||
endif
|
||||
|
||||
%.xml: %.tap
|
||||
$(JUNITFILES.t): %.xml: %.tap
|
||||
$(TAPTOJUNIT) --puretap --output $@ --input $< $*
|
||||
|
||||
# If there's a perl test script (.plt) available, use it
|
||||
@@ -522,8 +518,8 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
|
||||
.PRECIOUS: $(COMMON_INC)
|
||||
|
||||
.PHONY: all host inc build install clean rebuild buildInstall build_clean
|
||||
.PHONY: runtests tapfiles clean-tests test-results junitfiles
|
||||
.PHONY: checkRelease warnRelease noCheckRelease
|
||||
.PHONY: runtests run-tap-tests tapfiles junitfiles test-results tap-results
|
||||
.PHONY: clean-tests checkRelease warnRelease noCheckRelease
|
||||
|
||||
endif # BASE_RULES_BUILD
|
||||
# EOF RULES_BUILD
|
||||
|
||||
@@ -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 the file LICENSE that is included with this distribution.
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
ARCHS += $(BUILD_ARCHS)
|
||||
@@ -54,7 +54,7 @@ $(foreach dir, $(DIRS), \
|
||||
|
||||
define DEP_template2
|
||||
$(1)$$(DIVIDER)$(2) : $$(foreach ddir, $$($(1)_DEPEND_DIRS), \
|
||||
$$(addsuffix $$(DIVIDER)$(2),$$(ddir)))
|
||||
$$(addsuffix $$(DIVIDER)$(2),$$(ddir))) | before-$(2)
|
||||
endef
|
||||
$(foreach action, $(ACTIONS), \
|
||||
$(foreach dir, $(DIRS), \
|
||||
@@ -79,15 +79,22 @@ $(foreach arch, $(ARCHS), \
|
||||
|
||||
dirPart = $(join $(dir $@), $(word 1, $(subst $(DIVIDER), ,$(notdir $@))))
|
||||
actionArchPart = $(join $(word 2, $(subst $(DIVIDER), ,$(notdir $@))), \
|
||||
$(addprefix $(DIVIDER),$(word 3, $(subst $(DIVIDER), ,$(notdir $@)))))
|
||||
$(DIRS) $(dirActionTargets) $(dirArchTargets) $(dirActionArchTargets) :
|
||||
$(addprefix $(DIVIDER),$(word 3, $(subst $(DIVIDER), ,$(notdir $@)))))
|
||||
|
||||
$(DIRS) $(dirActionTargets) $(dirArchTargets) $(dirActionArchTargets):
|
||||
$(MAKE) -C $(dirPart) $(actionArchPart)
|
||||
|
||||
# before-action rules are run once prior to recursing through the
|
||||
# list of subdirectories and running the action rule in each one.
|
||||
# See DEP_template2 above for how that rule ordering is achieved.
|
||||
beforeActions = $(addprefix before-,$(ACTIONS))
|
||||
$(beforeActions):
|
||||
|
||||
$(ARCHS) $(ACTIONS) $(actionArchTargets) :%: \
|
||||
$(foreach dir, $(DIRS), $(dir)$(DIVIDER)%)
|
||||
|
||||
.PHONY : $(DIRS) all host rebuild
|
||||
.PHONY : $(ARCHS) $(ACTIONS)
|
||||
.PHONY : $(ARCHS) $(ACTIONS) $(beforeActions)
|
||||
.PHONY : $(dirActionTargets) $(dirArchTargets)
|
||||
.PHONY : $(dirActionArchTargets)
|
||||
.PHONY : $(actionArchTargets)
|
||||
|
||||
@@ -16,32 +16,30 @@ cvsclean:
|
||||
$(PERL) $(CVSCLEAN)
|
||||
|
||||
realuninstall: uninstallDirs
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN) $(INSTALL_LOCATION_LIB)
|
||||
|
||||
UNINSTALL_DIRS += $(INSTALL_DBD) $(INSTALL_INCLUDE) $(INSTALL_DOC) \
|
||||
$(INSTALL_HTML) $(INSTALL_TEMPLATES) $(INSTALL_DB) $(DIRECTORY_TARGETS)
|
||||
uninstallDirs:
|
||||
$(RMDIR) $(UNINSTALL_DIRS)
|
||||
|
||||
EMPTY_INSTALL_DIRS = \
|
||||
$(if $(wildcard $(INSTALL_LOCATION_BIN)/*),,$(INSTALL_LOCATION_BIN)) \
|
||||
$(if $(wildcard $(INSTALL_LOCATION_LIB)/*),,$(INSTALL_LOCATION_LIB))
|
||||
uninstall: archuninstall uninstallDirs
|
||||
$(RMDIR) $(EMPTY_INSTALL_DIRS)
|
||||
|
||||
archuninstall: $(addprefix uninstall$(DIVIDER),$(BUILD_ARCHS)) | cleandirs
|
||||
archuninstall: $(addprefix uninstall$(DIVIDER),$(BUILD_ARCHS))
|
||||
|
||||
archPart = $(word 2, $(subst $(DIVIDER), ,$@))
|
||||
uninstall$(DIVIDER)%:
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN)/$(archPart)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)/$(archPart)
|
||||
|
||||
cleandirs:
|
||||
@$(NOP)
|
||||
ifeq ($(wildcard $(INSTALL_LOCATION_BIN)/*),)
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN)
|
||||
endif
|
||||
ifeq ($(wildcard $(INSTALL_LOCATION_LIB)/*),)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)
|
||||
endif
|
||||
$(RMDIR) $(addsuffix /$(subst uninstall$(DIVIDER),,$@), \
|
||||
$(INSTALL_LOCATION_BIN) $(INSTALL_LOCATION_LIB))
|
||||
|
||||
before-runtests before-test-results: rm-failure-file
|
||||
rm-failure-file:
|
||||
@$(RM) $(TEST_FAILURE_FILE)
|
||||
runtests test-results:
|
||||
$(PERL) $(TOOLS)/testFailures.pl $(TEST_FAILURE_FILE)
|
||||
|
||||
help:
|
||||
@echo "Usage: gnumake [options] [target] ..."
|
||||
@@ -75,8 +73,8 @@ help:
|
||||
@echo "Indiv. object targets are supported by O.<arch> level Makefile .e.g"
|
||||
@echo " xxxRecord.o"
|
||||
|
||||
.PHONY: cleandirs distclean cvsclean realuninstall archuninstall uninstallDirs
|
||||
.PHONY: uninstall help
|
||||
.PHONY: distclean cvsclean realuninstall archuninstall uninstallDirs
|
||||
.PHONY: uninstall rm-failure-file help
|
||||
|
||||
# Include <top>/cfg/TOP_RULES* files from tops defined in RELEASE* files
|
||||
#
|
||||
|
||||
@@ -30,7 +30,7 @@ ARCH_DEP_LDFLAGS += -m32
|
||||
# Compiler does not define __unix __unix__ unix
|
||||
|
||||
# Override for -DUNIX from CONFIG.Common.UnixCommon
|
||||
OP_SYS_CPPFLAGS = -D_MINGW
|
||||
OP_SYS_CPPFLAGS = -D_MINGW -D__USE_MINGW_ANSI_STDIO
|
||||
|
||||
EXE = .exe
|
||||
RES = .coff
|
||||
|
||||
@@ -4,21 +4,5 @@
|
||||
# Override these definitions in CONFIG_SITE.linux-x86.windows-x64-mingw
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Include common gnu compiler definitions
|
||||
include $(CONFIG)/CONFIG.gnuCommon
|
||||
|
||||
# Add resource compiler
|
||||
RCCMD = $(GNU_BIN)/$(CMPLR_PREFIX)windres$(CMPLR_SUFFIX) $(INCLUDES) $< $@
|
||||
|
||||
# Remove -fPIC flags, add out-implib
|
||||
SHRLIB_CFLAGS =
|
||||
SHRLIB_LDFLAGS = -shared \
|
||||
-Wl,--out-implib,$(DLLSTUB_PREFIX)$*$(DLLSTUB_SUFFIX)
|
||||
LOADABLE_SHRLIB_LDFLAGS = -shared \
|
||||
-Wl,--out-implib,$(DLLSTUB_PREFIX)$*$(DLLSTUB_SUFFIX)
|
||||
|
||||
# No need to explicitly link with gcc library
|
||||
GNU_LDLIBS_YES =
|
||||
|
||||
# Link with winsock2
|
||||
OP_SYS_LDLIBS = -lws2_32
|
||||
# Use the definitions from the win32-x86-mingw target
|
||||
include $(CONFIG)/os/CONFIG.linux-x86.win32-x86-mingw
|
||||
|
||||
@@ -141,13 +141,16 @@ STATIC_LDFLAGS=
|
||||
RANLIB=
|
||||
|
||||
#
|
||||
# option needed for parallel builds with Visual Studio 2015 onward
|
||||
#
|
||||
# option needed for parallel builds with Visual Studio 2013 onward
|
||||
# VS2012 and above have VisualStudioVersion, so just need to exclude 2012 (11.0)
|
||||
# -FS Force Synchronous PDB Writes
|
||||
#
|
||||
ifneq ($(VisualStudioVersion),)
|
||||
ifneq ($(VisualStudioVersion),11.0)
|
||||
OPT_CXXFLAGS_NO += -FS
|
||||
OPT_CFLAGS_NO += -FS
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
|
||||
@@ -1,39 +1,35 @@
|
||||
# CONFIG_SITE.Common.linux-arm
|
||||
#
|
||||
# Site Specific definitions for all linux-arm targets
|
||||
#-------------------------------------------------------
|
||||
# Site-specific settings for the linux-arm target
|
||||
|
||||
# NOTE for SHARED_LIBRARIES: In most cases if this is set to YES the
|
||||
# NOTE: In most cases if SHARED_LIBRARIES is set to YES the
|
||||
# shared libraries will be found automatically. However if the .so
|
||||
# files are installed at a different path to their compile-time path
|
||||
# then in order to be found at runtime do one of these:
|
||||
# a) LD_LIBRARY_PATH must include the full absolute pathname to
|
||||
# $(INSTALL_LOCATION)/lib/$(EPICS_HOST_ARCH) when invoking base
|
||||
# executables.
|
||||
# b) Add the runtime path to SHRLIB_DEPLIB_DIRS and PROD_DEPLIB_DIRS, which
|
||||
# b) Add the runtime path to SHRLIB_DEPLIB_DIRS and PROD_DEPLIB_DIRS, which
|
||||
# will add the named directory to the list contained in the executables.
|
||||
# c) Add the runtime path to /etc/ld.so.conf and run ldconfig
|
||||
# to inform the system of the shared library location.
|
||||
|
||||
# Depending on your version of Linux you'll want one of the following
|
||||
# lines to enable command-line editing and history in iocsh. If you're
|
||||
# not sure which, start with the top one and work downwards until the
|
||||
# build doesn't fail to link the readline library. If none of them work,
|
||||
# comment them all out to build without readline support.
|
||||
|
||||
# No other libraries needed (recent Fedora, Ubuntu etc.):
|
||||
#COMMANDLINE_LIBRARY = READLINE
|
||||
# Use GNU Readline if the header file is installed
|
||||
COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \
|
||||
$(firstword $(READLINE_DIR) $(GNU_DIR))/include/readline/readline.h), \
|
||||
READLINE, EPICS))
|
||||
|
||||
# Needs -lncurses (RHEL 5 etc.):
|
||||
# If libreadline needs additional libraries to be linked with it, try
|
||||
# uncommenting each of the lines below in turn, starting with the top
|
||||
# one and working downwards, until the build succeeds. Do a 'make rebuild'
|
||||
# from the top of the Base tree after changing this setting.
|
||||
|
||||
# Needs -lncurses:
|
||||
#COMMANDLINE_LIBRARY = READLINE_NCURSES
|
||||
|
||||
# Needs -lcurses (older versions)
|
||||
# Needs -lcurses:
|
||||
#COMMANDLINE_LIBRARY = READLINE_CURSES
|
||||
|
||||
|
||||
# It makes sense to include debugging symbols even in optimized builds
|
||||
# in case you want to attach gdb to the process or examine a core-dump.
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
# Readline is broken or you don't want use it:
|
||||
#COMMANDLINE_LIBRARY = EPICS
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# CONFIG_SITE.Common.linux-cris
|
||||
#
|
||||
# Site Specific definitions for linux-cris target
|
||||
# Only the local epics system manager should modify this file
|
||||
# Site-specific settings for the linux-cris target
|
||||
|
||||
# NOTE for SHARED_LIBRARIES: In most cases if this is set to YES the
|
||||
# NOTE: In most cases if SHARED_LIBRARIES is set to YES the
|
||||
# shared libraries will be found automatically. However if the .so
|
||||
# files are installed at a different path to their compile-time path
|
||||
# then in order to be found at runtime do one of these:
|
||||
@@ -15,21 +14,21 @@
|
||||
# c) Add the runtime path to /etc/ld.so.conf and run ldconfig
|
||||
# to inform the system of the shared library location.
|
||||
|
||||
# Depending on your version of Linux you may want one of the following
|
||||
# lines to enable command-line editing and history in iocsh. If you're
|
||||
# not sure which, start with the top one and work downwards until the
|
||||
# build doesn't fail to link the readline library. If none of them work,
|
||||
# comment them all out to build without readline support.
|
||||
|
||||
# No other libraries needed (recent Fedora, Ubuntu etc.):
|
||||
#COMMANDLINE_LIBRARY = READLINE
|
||||
# Use GNU Readline if the header file is installed
|
||||
COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \
|
||||
$(GNU_DIR)/include/readline/readline.h), READLINE, EPICS))
|
||||
|
||||
# Needs -lncurses (RHEL 5 etc.):
|
||||
# If libreadline needs additional libraries to be linked with it, try
|
||||
# uncommenting each of the lines below in turn, starting with the top
|
||||
# one and working downwards, until the build succeeds. Do a 'make rebuild'
|
||||
# from the top of the Base tree after changing this setting.
|
||||
|
||||
# Needs -lncurses:
|
||||
#COMMANDLINE_LIBRARY = READLINE_NCURSES
|
||||
|
||||
# Needs -lcurses (older versions)
|
||||
# Needs -lcurses:
|
||||
#COMMANDLINE_LIBRARY = READLINE_CURSES
|
||||
|
||||
|
||||
OP_SYS_CFLAGS += -g
|
||||
|
||||
# Readline is broken or you don't want use it:
|
||||
#COMMANDLINE_LIBRARY = EPICS
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# CONFIG_SITE.Common.linux-microblaze
|
||||
#
|
||||
# Site specific definitions for linux-microblaze target builds.
|
||||
#-------------------------------------------------------
|
||||
# Site-specific settings for the linux-microblaze target
|
||||
|
||||
# The gnu tools for cross compiling for MicroBlaze (little endian)
|
||||
# on Linux can be downloaded from the Xilinx git server:
|
||||
@@ -12,3 +11,21 @@
|
||||
|
||||
GNU_DIR = /usr/local/vw/microblaze-2.0/microblazeel-unknown-linux-gnu
|
||||
|
||||
|
||||
# Use GNU Readline if the header file is installed
|
||||
COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \
|
||||
$(GNU_DIR)/include/readline/readline.h), READLINE, EPICS))
|
||||
|
||||
# If libreadline needs additional libraries to be linked with it, try
|
||||
# uncommenting each of the lines below in turn, starting with the top
|
||||
# one and working downwards, until the build succeeds. Do a 'make rebuild'
|
||||
# from the top of the Base tree after changing this setting.
|
||||
|
||||
# Needs -lncurses:
|
||||
#COMMANDLINE_LIBRARY = READLINE_NCURSES
|
||||
|
||||
# Needs -lcurses:
|
||||
#COMMANDLINE_LIBRARY = READLINE_CURSES
|
||||
|
||||
# Readline is broken or you don't want use it:
|
||||
#COMMANDLINE_LIBRARY = EPICS
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# CONFIG_SITE.Common.linux-x86
|
||||
#
|
||||
# Site Specific definitions for linux-x86 target
|
||||
# Only the local epics system manager should modify this file
|
||||
# Site-specific settings for the linux-x86 target
|
||||
|
||||
# NOTE for SHARED_LIBRARIES: In most cases if this is set to YES the
|
||||
# NOTE: In most cases if SHARED_LIBRARIES is set to YES the
|
||||
# shared libraries will be found automatically. However if the .so
|
||||
# files are installed at a different path to their compile-time path
|
||||
# then in order to be found at runtime do one of these:
|
||||
@@ -15,14 +14,15 @@
|
||||
# c) Add the runtime path to /etc/ld.so.conf and run ldconfig
|
||||
# to inform the system of the shared library location.
|
||||
|
||||
# Depending on your version of Linux you'll want one of the following
|
||||
# lines to enable command-line editing and history in iocsh. If you're
|
||||
# not sure which, start with the top one and work downwards until the
|
||||
# build doesn't fail to link the readline library. If none of them work,
|
||||
# comment them all out to build without readline support.
|
||||
|
||||
# No other libraries needed (recent Fedora, Ubuntu etc.):
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
# Use GNU Readline if the header file is installed
|
||||
COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \
|
||||
$(GNU_DIR)/include/readline/readline.h), READLINE, EPICS))
|
||||
|
||||
# If libreadline needs additional libraries to be linked with it, try
|
||||
# uncommenting each of the lines below in turn, starting with the top
|
||||
# one and working downwards, until the build succeeds. Do a 'make rebuild'
|
||||
# from the top of the Base tree after changing this setting.
|
||||
|
||||
# Needs -lncurses (RHEL 5 etc.):
|
||||
#COMMANDLINE_LIBRARY = READLINE_NCURSES
|
||||
@@ -30,6 +30,9 @@ COMMANDLINE_LIBRARY = READLINE
|
||||
# Needs -lcurses (older versions)
|
||||
#COMMANDLINE_LIBRARY = READLINE_CURSES
|
||||
|
||||
# Readline is broken or you don't want use it:
|
||||
#COMMANDLINE_LIBRARY = EPICS
|
||||
|
||||
|
||||
# Permit access to 64-bit file-systems
|
||||
OP_SYS_CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
@@ -43,14 +46,6 @@ OP_SYS_CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
#CCC = clang++
|
||||
|
||||
|
||||
# It makes sense to include debugging symbols even in optimized builds
|
||||
# in case you want to attach gdb to the process or examine a core-dump.
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
|
||||
|
||||
# Tune GNU compiler output for a specific 32-bit cpu-type
|
||||
# (e.g. generic, native, i386, i686, pentium2/3/4, prescott, k6, athlon etc.)
|
||||
GNU_TUNE_CFLAGS = -mtune=generic
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# CONFIG_SITE.Common.linux-x86_64
|
||||
#
|
||||
# Site Specific definitions for linux-x86_64 target
|
||||
# Only the local epics system manager should modify this file
|
||||
# Site-specific settings for the linux-x86_64 target
|
||||
|
||||
# NOTE for SHARED_LIBRARIES: In most cases if this is set to YES the
|
||||
# NOTE: In most cases if SHARED_LIBRARIES is set to YES the
|
||||
# shared libraries will be found automatically. However if the .so
|
||||
# files are installed at a different path to their compile-time path
|
||||
# then in order to be found at runtime do one of these:
|
||||
@@ -15,14 +14,15 @@
|
||||
# c) Add the runtime path to /etc/ld.so.conf and run ldconfig
|
||||
# to inform the system of the shared library location.
|
||||
|
||||
# Depending on your version of Linux you'll want one of the following
|
||||
# lines to enable command-line editing and history in iocsh. If you're
|
||||
# not sure which, start with the top one and work downwards until the
|
||||
# build doesn't fail to link the readline library. If none of them work,
|
||||
# comment them all out to build without readline support.
|
||||
|
||||
# No other libraries needed (recent Fedora, Ubuntu etc.):
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
# Use GNU Readline if the header file is installed
|
||||
COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \
|
||||
$(GNU_DIR)/include/readline/readline.h), READLINE, EPICS))
|
||||
|
||||
# If libreadline needs additional libraries to be linked with it, try
|
||||
# uncommenting each of the lines below in turn, starting with the top
|
||||
# one and working downwards, until the build succeeds. Do a 'make rebuild'
|
||||
# from the top of the Base tree after changing this setting.
|
||||
|
||||
# Needs -lncurses (RHEL 5 etc.):
|
||||
#COMMANDLINE_LIBRARY = READLINE_NCURSES
|
||||
@@ -30,6 +30,9 @@ COMMANDLINE_LIBRARY = READLINE
|
||||
# Needs -lcurses (older versions)
|
||||
#COMMANDLINE_LIBRARY = READLINE_CURSES
|
||||
|
||||
# Readline is broken or you don't want use it:
|
||||
#COMMANDLINE_LIBRARY = EPICS
|
||||
|
||||
|
||||
# Uncomment the followings lines to build with CLANG instead of GCC.
|
||||
#
|
||||
@@ -39,14 +42,6 @@ COMMANDLINE_LIBRARY = READLINE
|
||||
#CCC = clang++
|
||||
|
||||
|
||||
# It makes sense to include debugging symbols even in optimized builds
|
||||
# in case you want to attach gdb to the process or examine a core-dump.
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
|
||||
|
||||
# Tune GNU compiler output for a specific 64-bit cpu-type
|
||||
# (e.g. generic, native, core2, nocona, k8, opteron, athlon64, barcelona etc.)
|
||||
GNU_TUNE_CFLAGS = -mtune=generic
|
||||
|
||||
@@ -1,4 +1,23 @@
|
||||
# CONFIG_SITE.Common.linux-xscale_be
|
||||
#
|
||||
# Site specific definitions for all linux-xscale_be target builds.
|
||||
#-------------------------------------------------------
|
||||
# Site-specific settings for the linux-xscale_be target
|
||||
|
||||
|
||||
# Use GNU Readline if the header file is installed
|
||||
COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \
|
||||
$(firstword $(READLINE_DIR) $(GNU_DIR))/include/readline/readline.h), \
|
||||
READLINE, EPICS))
|
||||
|
||||
# If libreadline needs additional libraries to be linked with it, try
|
||||
# uncommenting each of the lines below in turn, starting with the top
|
||||
# one and working downwards, until the build succeeds. Do a 'make rebuild'
|
||||
# from the top of the Base tree after changing this setting.
|
||||
|
||||
# Needs -lncurses:
|
||||
#COMMANDLINE_LIBRARY = READLINE_NCURSES
|
||||
|
||||
# Needs -lcurses:
|
||||
#COMMANDLINE_LIBRARY = READLINE_CURSES
|
||||
|
||||
# Readline is broken or you don't want use it:
|
||||
#COMMANDLINE_LIBRARY = EPICS
|
||||
|
||||
11
configure/os/CONFIG_SITE.Common.linuxCommon
Normal file
11
configure/os/CONFIG_SITE.Common.linuxCommon
Normal file
@@ -0,0 +1,11 @@
|
||||
# CONFIG_SITE.Common.linuxCommon
|
||||
#
|
||||
# Site-specific settings for all linux targets
|
||||
|
||||
|
||||
# It makes sense to include debugging symbols even in optimized builds
|
||||
# in case you want to attach gdb to the process or examine a core-dump.
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
@@ -4,17 +4,17 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<title>Known Problems in R3.15.6</title>
|
||||
<title>Known Problems in R3.15.8</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 style="text-align: center">EPICS Base R3.15.6: Known Problems</h1>
|
||||
<h1 style="text-align: center">EPICS Base R3.15.8: Known Problems</h1>
|
||||
|
||||
<p>Any patch files linked below should be applied at the root of the
|
||||
base-3.15.6 tree. Download them, then use the GNU Patch program as
|
||||
base-3.15.8 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>
|
||||
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.8</b>
|
||||
% <b>patch -p1 < <i>/path/to/</i>file.patch</b></pre></blockquote>
|
||||
|
||||
<p>The following significant problems have been reported with this
|
||||
|
||||
@@ -1,346 +0,0 @@
|
||||
Installation Instructions
|
||||
|
||||
EPICS Base Release 3.15.6
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
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?
|
||||
|
||||
The Experimental Physics and Industrial Control Systems (EPICS) is an
|
||||
extensible set of software components and tools with which application
|
||||
developers can create a control system. This control system can be used
|
||||
to control accelerators, detectors, telescopes, or other scientific
|
||||
experimental equipment. EPICS base is the set of core software, i.e. the
|
||||
components of EPICS without which EPICS would not function. EPICS base
|
||||
allows an arbitrary number of target systems, IOCs (input/output
|
||||
controllers), and host systems, OPIs (operator interfaces) of various
|
||||
types.
|
||||
|
||||
What is new in this release?
|
||||
|
||||
Please check the RELEASE_NOTES file in the distribution for description
|
||||
of changes and release migration details.
|
||||
|
||||
Copyright
|
||||
|
||||
Please review the LICENSE file included in the distribution for legal
|
||||
terms of usage.
|
||||
|
||||
Supported platforms
|
||||
|
||||
The list of platforms supported by this version of EPICS base is given
|
||||
in the configure/CONFIG_SITE file. If you are trying to build EPICS Base
|
||||
on an unlisted host or for a different target machine you must have the
|
||||
proper host/target cross compiler and header files, and you will have to
|
||||
create and add the appropriate new configure files to the
|
||||
base/configure/os/directory. You can start by copying existing
|
||||
configuration files in the configure/os directory and then make changes
|
||||
for your new platforms.
|
||||
|
||||
Supported compilers
|
||||
|
||||
This version of EPICS base has been built and tested using the host
|
||||
vendor's C and C++ compilers, as well as the GNU gcc and g++ compilers.
|
||||
The GNU cross-compilers work for all cross-compiled targets. You may
|
||||
need the C and C++ compilers to be in your search path to do EPICS
|
||||
builds; check the definitions of CC and CCC in
|
||||
base/configure/os/CONFIG.<host>.<host> if you have problems.
|
||||
|
||||
Software requirements
|
||||
|
||||
GNU make
|
||||
You must use GNU make, gnumake, for any EPICS builds. Set your path so
|
||||
that a gnumake version 3.81 or later is available.
|
||||
|
||||
Perl
|
||||
You must have Perl version 5.8.1 or later installed. The EPICS
|
||||
configuration files do not specify the perl full pathname, so the perl
|
||||
executable must be found through your normal search path.
|
||||
|
||||
Unzip and tar (Winzip on WIN32 systems)
|
||||
You must have tools available to unzip and untar the EPICS base
|
||||
distribution file.
|
||||
|
||||
Target systems
|
||||
EPICS supports IOCs running on embedded platforms such as VxWorks and
|
||||
RTEMS built using a cross-compiler, and also supports soft IOCs running
|
||||
as processes on the host platform.
|
||||
|
||||
vxWorks
|
||||
You must have vxWorks 5.5.x or 6.x installed if any of your target
|
||||
systems are vxWorks systems; the C++ compiler for vxWorks 5.4 is now too
|
||||
old to support. The vxWorks installation provides the cross-compiler and
|
||||
header files needed to build for these targets. The absolute path to and
|
||||
the version number of the vxWorks installation must be set in the
|
||||
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
|
||||
target-specific overrides.
|
||||
|
||||
Consult the vxWorks 5.x or vxWorks 6.x EPICS web pages about and the
|
||||
vxWorks documentation for information about configuring your vxWorks
|
||||
operating system for use with EPICS.
|
||||
|
||||
RTEMS
|
||||
For RTEMS targets, you need RTEMS core and toolset version 4.9.2 or
|
||||
later.
|
||||
|
||||
GNU readline or Tecla library
|
||||
GNU readline and Tecla libraries can be used by the IOC shell to provide
|
||||
command line editing and command line history recall and edit. GNU
|
||||
readline (or Tecla library) must be installed on your target system when
|
||||
COMMANDLINE_LIBRARY is set to READLINE (or TECLA) for that target. EPICS
|
||||
(EPICS shell) is the default specified in CONFIG_COMMON. A READLINE
|
||||
override is defined for linux-x86 in the EPICS distribution. Comment out
|
||||
COMMANDLINE_LIBRARY=READLINE in
|
||||
configure/os/CONFIG_SITE.Common.linux-x86 if readline is not installed
|
||||
on linux-x86. Command-line editing and history will then be those
|
||||
supplied by the os. On vxWorks the ledLib command-line input library is
|
||||
used instead.
|
||||
|
||||
Host system storage requirements
|
||||
|
||||
The compressed tar file is approximately 1.6 MB in size. The
|
||||
distribution source tree takes up approximately 12 MB. Each host target
|
||||
will need around 40 MB for build files, and each cross-compiled target
|
||||
around 20 MB.
|
||||
|
||||
Documentation
|
||||
|
||||
EPICS documentation is available through the EPICS website at Argonne.
|
||||
|
||||
Release specific documentation can also be found in the
|
||||
base/documentation directory of the distribution.
|
||||
|
||||
Directory Structure
|
||||
|
||||
Distribution directory structure:
|
||||
|
||||
base Root directory of the base distribution
|
||||
base/configure Operating system independent build config files
|
||||
base/configure/os Operating system dependent build config files
|
||||
base/documentation Distribution documentation
|
||||
base/src Source code in various subdirectories
|
||||
base/startup Scripts for setting up path and environment
|
||||
|
||||
Install directories created by the build:
|
||||
|
||||
bin Installed scripts and executables in subdirs
|
||||
cfg Installed build configuration files
|
||||
db Installed data bases
|
||||
dbd Installed data base definitions
|
||||
doc Installed documentation files
|
||||
html Installed html documentation
|
||||
include Installed header files
|
||||
include/os Installed os specific header files in subdirs
|
||||
include/compiler Installed compiler-specific header files
|
||||
lib Installed libraries in arch subdirectories
|
||||
lib/perl Installed perl modules
|
||||
templates Installed templates
|
||||
|
||||
Build related components
|
||||
|
||||
base/documentation directory - contains setup, build, and install documents
|
||||
|
||||
README.1st Instructions for setup and building epics base
|
||||
README.html html version of README.1st
|
||||
README.darwin.html Installation notes for Mac OS X (Darwin)
|
||||
RELEASE_NOTES.html Notes on release changes
|
||||
KnownProblems.html List of known problems and workarounds
|
||||
|
||||
base/startup directory - contains scripts to set environment and path
|
||||
|
||||
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
|
||||
|
||||
CONFIG Includes configure files and allows variable overrides
|
||||
CONFIG.CrossCommon Cross build definitions
|
||||
CONFIG.gnuCommon Gnu compiler build definitions for all archs
|
||||
CONFIG_ADDONS Definitions for <osclass> and DEFAULT options
|
||||
CONFIG_APP_INCLUDE
|
||||
CONFIG_BASE EPICS base tool and location definitions
|
||||
CONFIG_BASE_VERSION Definitions for EPICS base version number
|
||||
CONFIG_COMMON Definitions common to all builds
|
||||
CONFIG_ENV Definitions of EPICS environment variables
|
||||
CONFIG_FILE_TYPE
|
||||
CONFIG_SITE Site specific make definitions
|
||||
CONFIG_SITE_ENV Site defaults for EPICS environment variables
|
||||
MAKEFILE Installs CONFIG* RULES* creates
|
||||
RELEASE Location of external products
|
||||
RULES Includes appropriate rules file
|
||||
RULES.Db Rules for database and database definition files
|
||||
RULES.ioc Rules for application iocBoot/ioc* directory
|
||||
RULES_ARCHS Definitions and rules for building architectures
|
||||
RULES_BUILD Build and install rules and definitions
|
||||
RULES_DIRS Definitions and rules for building subdirectories
|
||||
RULES_EXPAND
|
||||
RULES_FILE_TYPE
|
||||
RULES_TARGET
|
||||
RULES_TOP Rules specific to a <top> dir (uninstall and tar)
|
||||
Sample.Makefile Sample makefile with comments
|
||||
|
||||
base/configure/os directory - contains os-arch specific definitions
|
||||
|
||||
CONFIG.<host>.<target> Specific host-target build definitions
|
||||
CONFIG.Common.<target> Specific target definitions for all hosts
|
||||
CONFIG.<host>.Common Specific host definitions for all targets
|
||||
CONFIG.UnixCommon.Common Definitions for Unix hosts and all targets
|
||||
CONFIG.Common.UnixCommon Definitions for Unix targets and all hosts
|
||||
CONFIG.Common.vxWorksCommon Specific host definitions for all vx targets
|
||||
CONFIG_SITE.<host>.<target> Site specific host-target definitions
|
||||
CONFIG_SITE.Common.<target> Site specific target defs for all hosts
|
||||
CONFIG_SITE.<host>.Common Site specific host defs for all targets
|
||||
|
||||
Building EPICS base (Unix and Win32)
|
||||
|
||||
Unpack file
|
||||
|
||||
Unzip and untar the distribution file. Use WinZip on Windows systems.
|
||||
|
||||
Set environment variables
|
||||
|
||||
Files in the base/startup directory have been provided to help set
|
||||
required path and other environment variables.
|
||||
|
||||
EPICS_HOST_ARCH
|
||||
Before you can build or use EPICS R3.15, the environment variable
|
||||
EPICS_HOST_ARCH must be defined. A perl script EpicsHostArch.pl in the
|
||||
base/startup directory has been provided to help set EPICS_HOST_ARCH.
|
||||
You should have EPICS_HOST_ARCH set to your host operating system
|
||||
followed by a dash and then your host architecture, e.g.
|
||||
solaris-sparc. If you are not using the OS vendor's c/c++ compiler for
|
||||
host builds, you will need another dash followed by the alternate
|
||||
compiler name (e.g. "-gnu" for GNU c/c++ compilers on a solaris host
|
||||
or "-mingw" for MinGW c/c++ compilers on a WIN32 host). See
|
||||
configure/CONFIG_SITE for a list of supported EPICS_HOST_ARCH values.
|
||||
|
||||
PERLLIB
|
||||
On WIN32, some versions of Perl require that the environment variable
|
||||
PERLLIB be set to <perl directory location>.
|
||||
|
||||
PATH
|
||||
As already mentioned, you must have the perl executable and you may
|
||||
need C and C++ compilers in your search path. For building base you
|
||||
also must have echo in your search path. For Unix host builds you also
|
||||
need ln, cpp, cp, rm, mv, and mkdir in your search path and /bin/chmod
|
||||
must exist. On some Unix systems you may also need ar and ranlib in
|
||||
your path, and the C compiler may require as and ld in your path. On
|
||||
solaris systems you need uname in your path.
|
||||
|
||||
LD_LIBRARY_PATH
|
||||
R3.15 shared libraries and executables normally contain the full path
|
||||
to any libraries they require. However, if you move the EPICS files or
|
||||
directories from their build-time location then in order for the
|
||||
shared libraries to be found at runtime LD_LIBRARY_PATH must include
|
||||
the full pathname to $(INSTALL_LOCATION)/lib/$(EPICS_HOST_ARCH) when
|
||||
invoking executables, or some equivalent OS-specific mechanism (such
|
||||
as /etc/ld.so.conf on Linux) must be used. Shared libraries are now
|
||||
built by default on all Unix type hosts.
|
||||
|
||||
Do site-specific build configuration
|
||||
|
||||
Site configuration
|
||||
To configure EPICS, you may want to modify the default definitions in
|
||||
the following files:
|
||||
|
||||
configure/CONFIG_SITE Build choices. Specify target archs.
|
||||
configure/CONFIG_SITE_ENV Environment variable defaults
|
||||
configure/RELEASE TORNADO2 full path location
|
||||
|
||||
Host configuration
|
||||
To configure each host system, you may override the default
|
||||
definitions by adding a new file in the configure/os directory with
|
||||
override definitions. The new file should have the same name as the
|
||||
distribution file to be overridden except with CONFIG in the name
|
||||
changed to CONFIG_SITE.
|
||||
|
||||
configure/os/CONFIG.<host>.<host> Host build settings
|
||||
configure/os/CONFIG.<host>.Common Host common build settings
|
||||
|
||||
Target configuration
|
||||
To configure each target system, you may override the default
|
||||
definitions by adding a new file in the configure/os directory with
|
||||
override definitions. The new file should have the same name as the
|
||||
distribution file to be overridden except with CONFIG in the name
|
||||
replaced by CONFIG_SITE. This step is necessary even if the host
|
||||
system is the only target system.
|
||||
|
||||
configure/os/CONFIG.Common.<target> Target common settings
|
||||
configure/os/CONFIG.<host>.<target> Host-target settings
|
||||
|
||||
Build EPICS base
|
||||
|
||||
After configuring the build you should be able to build EPICS base by
|
||||
issuing the following commands in the distribution's root directory
|
||||
(base):
|
||||
|
||||
gnumake clean uninstall
|
||||
gnumake
|
||||
|
||||
The command "gnumake clean uninstall" will remove all files and
|
||||
directories generated by a previous build. The command "gnumake" will
|
||||
build and install everything for the configured host and targets.
|
||||
|
||||
It is recommended that you do a "gnumake clean uninstall" at the root
|
||||
directory of an EPICS directory structure before each complete rebuild
|
||||
to ensure that all components will be rebuilt.
|
||||
|
||||
Example application and extension
|
||||
|
||||
A perl tool, makeBaseApp.pl is included in the distribution file. This
|
||||
script will create a sample application that can be built and then
|
||||
executed to try out this release of base.
|
||||
|
||||
Instructions for building and executing the 3.15 example application can
|
||||
be found in the section "Example Application" of Chapter 2, "Getting
|
||||
Started", in the "IOC Application Developer's Guide" for this release.
|
||||
The "Example IOC Application" section briefly explains how to create and
|
||||
build an example application in a user created <top> directory. It also
|
||||
explains how to run the example application on a vxWorks ioc or as a
|
||||
process on the host system. By running the example application as a
|
||||
host-based IOC, you will be able to quickly implement a complete EPICS
|
||||
system and be able to run channel access clients on the host system.
|
||||
|
||||
A perl script, makeBaseExt.pl, is included in the distribution file.
|
||||
This script will create a sample extension that can be built and
|
||||
executed. The makeBaseApp.pl and makeBaseExt.pl scripts are installed
|
||||
into the install location bin/<hostarch> directory during the base
|
||||
build.
|
||||
|
||||
Multiple host platforms
|
||||
|
||||
You can build using a single EPICS directory structure on multiple host
|
||||
systems and for multiple cross target systems. The intermediate and
|
||||
binary files generated by the build will be created in separate
|
||||
subdirectories and installed into the appropriate separate host/target
|
||||
install directories. EPICS executables and perl scripts are installed
|
||||
into the $(INSTALL_LOCATION)/bin/<arch> directories. Libraries are
|
||||
installed into $(INSTALL_LOCATION)/lib/<arch>. The default definition
|
||||
for $(INSTALL_LOCATION) is $(TOP) which is the root directory in the
|
||||
distribution directory structure, base. Created object files are stored
|
||||
in O.<arch> source subdirectories, This allows objects for multiple
|
||||
cross target architectures to be maintained at the same time. To build
|
||||
EPICS base for a specific host/target combination you must have the
|
||||
proper host/target C/C++ cross compiler and target header files and the
|
||||
base/configure/os directory must have the appropriate configure files.
|
||||
@@ -1,383 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!-- Generate the README.1st file from this file using:
|
||||
elinks -dump -no-numbering -no-references -dump-width 80 README.html
|
||||
-->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>README - EPICS Base Installation Instructions</TITLE>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<CENTER>
|
||||
<H1>Installation Instructions</H1>
|
||||
<H2>EPICS Base Release 3.15.6</H2><BR>
|
||||
</CENTER>
|
||||
<HR>
|
||||
<H3> Table of Contents</H3>
|
||||
<UL>
|
||||
<LI><A HREF="#0_0_1"> What is EPICS base?</A></LI>
|
||||
<LI><A HREF="#0_0_2"> What is new in this release?</A></LI>
|
||||
<LI><A HREF="#0_0_3"> Copyright</A></LI>
|
||||
<LI><A HREF="#0_0_4"> Supported platforms</A></LI>
|
||||
<LI><A HREF="#0_0_5"> Supported compilers</A></LI>
|
||||
<LI><A HREF="#0_0_6"> Software requirements</A></LI>
|
||||
<LI><A HREF="#0_0_7"> Host system storage requirements</A></LI>
|
||||
<LI><A HREF="#0_0_8"> Documentation</A></LI>
|
||||
<LI><A HREF="#0_0_10"> Directory Structure</A></LI>
|
||||
<LI><A HREF="#0_0_11"> Build related components</A></LI>
|
||||
<LI><A HREF="#0_0_12"> Building EPICS base (Unix and Win32)</A></LI>
|
||||
<LI><A HREF="#0_0_13"> Example application and extension</A></LI>
|
||||
<LI><A HREF="#0_0_14"> Multiple host platforms</A></LI>
|
||||
</UL>
|
||||
<HR>
|
||||
|
||||
<H3><A NAME="0_0_1"> What is EPICS base?</A></H3>
|
||||
<BLOCKQUOTE>The Experimental Physics and Industrial Control Systems
|
||||
(EPICS) is an extensible set of software components and tools with
|
||||
which application developers can create a control system. This control
|
||||
system can be used to control accelerators, detectors, telescopes, or
|
||||
other scientific experimental equipment. EPICS base is the set of core
|
||||
software, i.e. the components of EPICS without which EPICS would not
|
||||
function. EPICS base allows an arbitrary number of target systems, IOCs
|
||||
(input/output controllers), and host systems, OPIs (operator
|
||||
interfaces) of various types.</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_2"> What is new in this release?</A></H3>
|
||||
<BLOCKQUOTE> Please check the RELEASE_NOTES file in the distribution for
|
||||
description of changes and release migration details.</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_3"> Copyright</A></H3>
|
||||
<BLOCKQUOTE>Please review the LICENSE file included in the
|
||||
distribution for legal terms of usage.</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_4"> Supported platforms</A></H3>
|
||||
|
||||
<BLOCKQUOTE>The list of platforms supported by this version of EPICS base
|
||||
is given in the configure/CONFIG_SITE file. If you are trying to build
|
||||
EPICS Base on an unlisted host or for a different target machine you
|
||||
must have the proper host/target cross compiler and header files, and
|
||||
you will have to create and add the appropriate new configure files to
|
||||
the base/configure/os/directory. You can start by copying existing
|
||||
configuration files in the configure/os directory and then make changes
|
||||
for your new platforms.</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_5"> Supported compilers</A></H3>
|
||||
|
||||
<BLOCKQUOTE>This version of EPICS base has been built and tested using the host
|
||||
vendor's C and C++ compilers, as well as the GNU gcc and g++ compilers. The GNU
|
||||
cross-compilers work for all cross-compiled targets. You may need the C and C++
|
||||
compilers to be in your search path to do EPICS builds; check the definitions
|
||||
of CC and CCC in base/configure/os/CONFIG.<host>.<host> if you have
|
||||
problems.</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_6"> Software requirements</A></H3>
|
||||
|
||||
<BLOCKQUOTE><B>GNU make</B><BR>
|
||||
You must use GNU make, gnumake, for any EPICS builds. Set your path
|
||||
so that a gnumake version 3.81 or later is available.
|
||||
|
||||
<P><B>Perl</B><BR>
|
||||
You must have Perl version 5.8.1 or later installed. The EPICS configuration
|
||||
files do not specify the perl full pathname, so the perl executable must
|
||||
be found through your normal search path.</P>
|
||||
|
||||
<P><B>Unzip and tar (Winzip on WIN32 systems)</B><BR>
|
||||
You must have tools available to unzip and untar the EPICS base
|
||||
distribution file.</P>
|
||||
|
||||
<P><B>Target systems</B><BR>
|
||||
EPICS supports IOCs running on embedded platforms such as VxWorks
|
||||
and RTEMS built using a cross-compiler, and also supports soft IOCs running
|
||||
as processes on the host platform.</P>
|
||||
|
||||
<P><B>vxWorks</B><BR>
|
||||
You must have vxWorks 5.5.x or 6.x installed if any of your target systems are
|
||||
vxWorks systems; the C++ compiler for vxWorks 5.4 is now too old to support.
|
||||
The vxWorks installation provides the cross-compiler and header files needed to
|
||||
build for these targets. The absolute path to and the version number of the
|
||||
vxWorks installation must be set in the
|
||||
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
|
||||
target-specific overrides.</P>
|
||||
|
||||
<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>
|
||||
|
||||
<P><B>RTEMS</B><BR>
|
||||
For RTEMS targets, you need RTEMS core and toolset version 4.9.2 or later.</P>
|
||||
|
||||
<P><B>GNU readline or Tecla library</B><BR>
|
||||
GNU readline and Tecla libraries can be used by the IOC shell to
|
||||
provide command line editing and command line history recall and edit.
|
||||
GNU readline (or Tecla library) must be installed on your target system
|
||||
when COMMANDLINE_LIBRARY is set to READLINE (or TECLA) for that target.
|
||||
EPICS (EPICS shell) is the default specified in CONFIG_COMMON. A
|
||||
READLINE override is defined for linux-x86 in the EPICS distribution.
|
||||
Comment out COMMANDLINE_LIBRARY=READLINE in
|
||||
configure/os/CONFIG_SITE.Common.linux-x86 if readline is not installed
|
||||
on linux-x86. Command-line editing and history will then be those
|
||||
supplied by the os. On vxWorks the ledLib command-line input library is
|
||||
used instead.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_7"> Host system storage requirements</A></H3>
|
||||
|
||||
<BLOCKQUOTE>The compressed tar file is approximately 1.6 MB in size. The
|
||||
distribution source tree takes up approximately 12 MB. Each host target will
|
||||
need around 40 MB for build files, and each cross-compiled target around 20
|
||||
MB.</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_8"> Documentation</A></H3>
|
||||
<BLOCKQUOTE>EPICS documentation is available through the
|
||||
<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>
|
||||
|
||||
<H3><A NAME="0_0_10"> Directory Structure</A></H3>
|
||||
<BLOCKQUOTE><H4>Distribution directory structure:</H4>
|
||||
|
||||
<PRE>
|
||||
base Root directory of the base distribution
|
||||
base/configure Operating system independent build config files
|
||||
base/configure/os Operating system dependent build config files
|
||||
base/documentation Distribution documentation
|
||||
base/src Source code in various subdirectories
|
||||
base/startup Scripts for setting up path and environment
|
||||
</PRE>
|
||||
|
||||
<H4>Install directories created by the build:</H4>
|
||||
<PRE>
|
||||
bin Installed scripts and executables in subdirs
|
||||
cfg Installed build configuration files
|
||||
db Installed data bases
|
||||
dbd Installed data base definitions
|
||||
doc Installed documentation files
|
||||
html Installed html documentation
|
||||
include Installed header files
|
||||
include/os Installed os specific header files in subdirs
|
||||
include/compiler Installed compiler-specific header files
|
||||
lib Installed libraries in arch subdirectories
|
||||
lib/perl Installed perl modules
|
||||
templates Installed templates
|
||||
</PRE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_11"> Build related components</A></H3>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<H4>base/documentation directory - contains setup, build, and install
|
||||
documents</H4>
|
||||
<PRE>
|
||||
README.1st Instructions for setup and building epics base
|
||||
README.html html version of README.1st
|
||||
README.darwin.html Installation notes for Mac OS X (Darwin)
|
||||
RELEASE_NOTES.html Notes on release changes
|
||||
KnownProblems.html List of known problems and workarounds
|
||||
</PRE>
|
||||
|
||||
<H4>base/startup directory - contains scripts to set environment and path</H4>
|
||||
<PRE>
|
||||
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>
|
||||
<PRE>
|
||||
CONFIG Includes configure files and allows variable overrides
|
||||
CONFIG.CrossCommon Cross build definitions
|
||||
CONFIG.gnuCommon Gnu compiler build definitions for all archs
|
||||
CONFIG_ADDONS Definitions for <osclass> and DEFAULT options
|
||||
CONFIG_APP_INCLUDE
|
||||
CONFIG_BASE EPICS base tool and location definitions
|
||||
CONFIG_BASE_VERSION Definitions for EPICS base version number
|
||||
CONFIG_COMMON Definitions common to all builds
|
||||
CONFIG_ENV Definitions of EPICS environment variables
|
||||
CONFIG_FILE_TYPE
|
||||
CONFIG_SITE Site specific make definitions
|
||||
CONFIG_SITE_ENV Site defaults for EPICS environment variables
|
||||
MAKEFILE Installs CONFIG* RULES* creates
|
||||
RELEASE Location of external products
|
||||
RULES Includes appropriate rules file
|
||||
RULES.Db Rules for database and database definition files
|
||||
RULES.ioc Rules for application iocBoot/ioc* directory
|
||||
RULES_ARCHS Definitions and rules for building architectures
|
||||
RULES_BUILD Build and install rules and definitions
|
||||
RULES_DIRS Definitions and rules for building subdirectories
|
||||
RULES_EXPAND
|
||||
RULES_FILE_TYPE
|
||||
RULES_TARGET
|
||||
RULES_TOP Rules specific to a <top> dir (uninstall and tar)
|
||||
Sample.Makefile Sample makefile with comments
|
||||
</PRE>
|
||||
|
||||
<H4>base/configure/os directory - contains os-arch specific definitions</H4>
|
||||
<PRE>
|
||||
CONFIG.<host>.<target> Specific host-target build definitions
|
||||
CONFIG.Common.<target> Specific target definitions for all hosts
|
||||
CONFIG.<host>.Common Specific host definitions for all targets
|
||||
CONFIG.UnixCommon.Common Definitions for Unix hosts and all targets
|
||||
CONFIG.Common.UnixCommon Definitions for Unix targets and all hosts
|
||||
CONFIG.Common.vxWorksCommon Specific host definitions for all vx targets
|
||||
CONFIG_SITE.<host>.<target> Site specific host-target definitions
|
||||
CONFIG_SITE.Common.<target> Site specific target defs for all hosts
|
||||
CONFIG_SITE.<host>.Common Site specific host defs for all targets
|
||||
</PRE>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_12"> Building EPICS base (Unix and Win32)</A></H3>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<H4> Unpack file</H4>
|
||||
<BLOCKQUOTE>
|
||||
Unzip and untar the distribution file. Use WinZip on Windows
|
||||
systems.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H4>Set environment variables</H4>
|
||||
<BLOCKQUOTE>
|
||||
Files in the base/startup directory have been provided to
|
||||
help set required path and other environment variables.
|
||||
|
||||
<P><B>EPICS_HOST_ARCH</B><BR>
|
||||
Before you can build or use EPICS R3.15, the environment variable
|
||||
EPICS_HOST_ARCH must be defined. A perl script EpicsHostArch.pl in the
|
||||
base/startup directory has been provided to help set EPICS_HOST_ARCH.
|
||||
You should have EPICS_HOST_ARCH set to your host operating system
|
||||
followed by a dash and then your host architecture, e.g. solaris-sparc.
|
||||
If you are not using the OS vendor's c/c++ compiler for host builds,
|
||||
you will need another dash followed by the alternate compiler name
|
||||
(e.g. "-gnu" for GNU c/c++ compilers on a solaris host or "-mingw"
|
||||
for MinGW c/c++ compilers on a WIN32 host). See configure/CONFIG_SITE
|
||||
for a list of supported EPICS_HOST_ARCH values.</P>
|
||||
|
||||
<P><B>PERLLIB</B><BR>
|
||||
On WIN32, some versions of Perl require that the environment
|
||||
variable PERLLIB be set to <perl directory location>.</P>
|
||||
|
||||
<P><B>PATH</B><BR>
|
||||
As already mentioned, you must have the perl executable and you may
|
||||
need C and C++ compilers in your search path. For building base you
|
||||
also must have echo in your search path. For Unix host builds you also
|
||||
need ln, cpp, cp, rm, mv, and mkdir in your search path and /bin/chmod
|
||||
must exist. On some Unix systems you may also need ar and ranlib in
|
||||
your path, and the C compiler may require as and ld in your path. On
|
||||
solaris systems you need uname in your path.</P>
|
||||
|
||||
<P><B>LD_LIBRARY_PATH</B><BR>
|
||||
|
||||
R3.15 shared libraries and executables normally contain the full path
|
||||
to any libraries they require.
|
||||
However, if you move the EPICS files or directories from their build-time
|
||||
location then in order for the shared libraries to be found at runtime
|
||||
LD_LIBRARY_PATH must include the full pathname to
|
||||
$(INSTALL_LOCATION)/lib/$(EPICS_HOST_ARCH) when invoking executables, or
|
||||
some equivalent OS-specific mechanism (such as /etc/ld.so.conf on Linux)
|
||||
must be used.
|
||||
Shared libraries are now built by default on all Unix type hosts.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H4>Do site-specific build configuration</H4>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<B>Site configuration</B><BR>
|
||||
To configure EPICS, you may want to modify the default definitions
|
||||
in the following files:
|
||||
<PRE>
|
||||
configure/CONFIG_SITE Build choices. Specify target archs.
|
||||
configure/CONFIG_SITE_ENV Environment variable defaults
|
||||
configure/RELEASE TORNADO2 full path location
|
||||
</PRE>
|
||||
|
||||
<B> Host configuration</B><BR>
|
||||
To configure each host system, you may override the default
|
||||
definitions by adding a new file in the configure/os directory with
|
||||
override definitions. The new file should have the same name as the
|
||||
distribution file to be overridden except with CONFIG in the name
|
||||
changed to CONFIG_SITE.
|
||||
|
||||
<PRE>
|
||||
configure/os/CONFIG.<host>.<host> Host build settings
|
||||
configure/os/CONFIG.<host>.Common Host common build settings
|
||||
</PRE>
|
||||
|
||||
<B>Target configuration</B><BR>
|
||||
To configure each target system, you may override the default
|
||||
definitions by adding a new file in the configure/os directory with
|
||||
override definitions. The new file should have the same name as the
|
||||
distribution file to be overridden except with CONFIG in the name
|
||||
replaced by CONFIG_SITE. This step is necessary even if the host system
|
||||
is the only target system.
|
||||
<PRE>
|
||||
configure/os/CONFIG.Common.<target> Target common settings
|
||||
configure/os/CONFIG.<host>.<target> Host-target settings
|
||||
</PRE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H4>Build EPICS base</H4>
|
||||
<BLOCKQUOTE>After configuring the build you should be able to build
|
||||
EPICS base by issuing the following commands in the distribution's root
|
||||
directory (base):
|
||||
<PRE>
|
||||
gnumake clean uninstall
|
||||
gnumake
|
||||
</PRE>
|
||||
|
||||
The command "gnumake clean uninstall"
|
||||
will remove all files and directories generated by a previous build.
|
||||
The command "gnumake" will build and install everything for the
|
||||
configured host and targets.
|
||||
|
||||
<P> It is recommended that you do a "gnumake clean uninstall" at the
|
||||
root directory of an EPICS directory structure before each complete
|
||||
rebuild to ensure that all components will be rebuilt.
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_13"> Example application and extension</A></H3>
|
||||
<BLOCKQUOTE>A perl tool, makeBaseApp.pl is included in the distribution
|
||||
file. This script will create a sample application that can be built
|
||||
and then executed to try out this release of base.
|
||||
|
||||
<P>
|
||||
Instructions for building and executing the 3.15 example application
|
||||
can be found in the section "Example Application" of Chapter 2,
|
||||
"Getting Started", in the "IOC Application Developer's Guide" for this
|
||||
release. The "Example IOC Application" section briefly explains how to
|
||||
create and build an example application in a user created <top>
|
||||
directory. It also explains how to run the example application on a
|
||||
vxWorks ioc or as a process on the host system.
|
||||
By running the example application as a host-based IOC, you will be
|
||||
able to quickly implement a complete EPICS system and be able to run channel
|
||||
access clients on the host system.
|
||||
|
||||
<P>
|
||||
A perl script,
|
||||
makeBaseExt.pl, is included in the distribution file. This script will
|
||||
create a sample extension that can be built and executed. The
|
||||
makeBaseApp.pl and makeBaseExt.pl scripts are installed into the
|
||||
install location bin/<hostarch> directory during the base build.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="0_0_14"> Multiple host platforms</A></H3>
|
||||
<BLOCKQUOTE>You can build using a single EPICS directory structure on
|
||||
multiple host systems and for multiple cross target systems. The
|
||||
intermediate and binary files generated by the build will be created in
|
||||
separate subdirectories and installed into the appropriate separate
|
||||
host/target install directories. EPICS executables and perl scripts are
|
||||
installed into the <TT>$(INSTALL_LOCATION)/bin/<arch></TT> directories.
|
||||
Libraries are installed into $<TT>(INSTALL_LOCATION)/lib/<arch></TT>.
|
||||
The default definition for <TT>$(INSTALL_LOCATION)</TT> is <TT>$(TOP)</TT>
|
||||
which is the root directory in the distribution directory structure,
|
||||
base. Created object files are stored in O.<arch> source
|
||||
subdirectories, This allows objects for multiple cross target
|
||||
architectures to be maintained at the same time. To build EPICS base
|
||||
for a specific host/target combination you must have the proper
|
||||
host/target C/C++ cross compiler and target header files and the
|
||||
base/configure/os directory must have the appropriate configure files.
|
||||
</BLOCKQUOTE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
373
documentation/README.md
Normal file
373
documentation/README.md
Normal file
@@ -0,0 +1,373 @@
|
||||
# Installation Instructions
|
||||
|
||||
## EPICS Base Release 3.15.8
|
||||
|
||||
-----
|
||||
|
||||
### Table of Contents
|
||||
|
||||
- [What is EPICS base?](#0_0_1)
|
||||
- [What is new in this release?](#0_0_2)
|
||||
- [Copyright](#0_0_3)
|
||||
- [Supported platforms](#0_0_4)
|
||||
- [Supported compilers](#0_0_5)
|
||||
- [Software requirements](#0_0_6)
|
||||
- [Host system storage requirements](#0_0_7)
|
||||
- [Documentation](#0_0_8)
|
||||
- [Directory Structure](#0_0_10)
|
||||
- [Build related components](#0_0_11)
|
||||
- [Building EPICS base (Unix and Win32)](#0_0_12)
|
||||
- [Example application and extension](#0_0_13)
|
||||
- [Multiple host platforms](#0_0_14)
|
||||
|
||||
-----
|
||||
|
||||
### <span id="0_0_1">What is EPICS base?</span>
|
||||
|
||||
The Experimental Physics and Industrial Control Systems (EPICS) is an
|
||||
extensible set of software components and tools with which application
|
||||
developers can create a control system. This control system can be
|
||||
used to control accelerators, detectors, telescopes, or other
|
||||
scientific experimental equipment. EPICS base is the set of core
|
||||
software, i.e. the components of EPICS without which EPICS would not
|
||||
function. EPICS base allows an arbitrary number of target systems,
|
||||
IOCs (input/output controllers), and host systems, OPIs (operator
|
||||
interfaces) of various types.
|
||||
|
||||
### <span id="0_0_2">What is new in this release?</span>
|
||||
|
||||
Please check the `RELEASE_NOTES` file in the distribution for
|
||||
description of changes and release migration details.
|
||||
|
||||
### <span id="0_0_3">Copyright</span>
|
||||
|
||||
Please review the LICENSE file included in the distribution for legal
|
||||
terms of usage.
|
||||
|
||||
### <span id="0_0_4">Supported platforms</span>
|
||||
|
||||
The list of platforms supported by this version of EPICS base is given
|
||||
in the `configure/CONFIG_SITE` file. If you are trying to build EPICS
|
||||
Base on an unlisted host or for a different target machine you must
|
||||
have the proper host/target cross compiler and header files, and you
|
||||
will have to create and add the appropriate new configure files to the
|
||||
base/configure/os/directory. You can start by copying existing
|
||||
configuration files in the configure/os directory and then make
|
||||
changes for your new platforms.
|
||||
|
||||
### <span id="0_0_5">Supported compilers</span>
|
||||
|
||||
This version of EPICS base has been built and tested using the host
|
||||
vendor's C and C++ compilers, as well as the GNU gcc and g++
|
||||
compilers. The GNU cross-compilers work for all cross-compiled
|
||||
targets. You may need the C and C++ compilers to be in your search
|
||||
path to do EPICS builds; check the definitions of CC and CCC in
|
||||
`base/configure/os/CONFIG.<host>.<host>` if you have problems.
|
||||
|
||||
### <span id="0_0_6">Software requirements</span>
|
||||
|
||||
**GNU make**
|
||||
You must use GNU make, gnumake, for any EPICS builds. Set your path so
|
||||
that a gnumake version 3.81 or later is available.
|
||||
|
||||
**Perl**
|
||||
You must have Perl version 5.8.1 or later installed. The EPICS
|
||||
configuration files do not specify the perl full pathname, so the perl
|
||||
executable must be found through your normal search path.
|
||||
|
||||
**Unzip and tar (Winzip on WIN32 systems)**
|
||||
You must have tools available to unzip and untar the EPICS base
|
||||
distribution file.
|
||||
|
||||
**Target systems**
|
||||
EPICS supports IOCs running on embedded platforms such as VxWorks and
|
||||
RTEMS built using a cross-compiler, and also supports soft IOCs
|
||||
running as processes on the host platform.
|
||||
|
||||
**vxWorks**
|
||||
You must have vxWorks 5.5.x or 6.x installed if any of your target
|
||||
systems are vxWorks systems; the C++ compiler for vxWorks 5.4 is now
|
||||
too old to support. The vxWorks installation provides the
|
||||
cross-compiler and header files needed to build for these targets. The
|
||||
absolute path to and the version number of the vxWorks installation
|
||||
must be set in the `base/configure/os/CONFIG_SITE.Common.vxWorksCommon`
|
||||
file or in one of its target-specific overrides.
|
||||
|
||||
Consult the [vxWorks 5.x](https://epics.anl.gov/base/tornado.php) or
|
||||
[vxWorks 6.x](https://epics.anl.gov/base/vxWorks6.php) EPICS web pages
|
||||
about and the vxWorks documentation for information about configuring
|
||||
your vxWorks operating system for use with EPICS.
|
||||
|
||||
**RTEMS**
|
||||
For RTEMS targets, you need RTEMS core and toolset version 4.9.2 or
|
||||
later.
|
||||
|
||||
**GNU readline or Tecla library**
|
||||
GNU readline and Tecla libraries can be used by the IOC shell to
|
||||
provide command line editing and command line history recall and edit.
|
||||
GNU readline (or Tecla library) must be installed on your target
|
||||
system when `COMMANDLINE_LIBRARY` is set to READLINE (or TECLA) for
|
||||
that target. EPICS (EPICS shell) is the default specified in
|
||||
`CONFIG_COMMON`. A READLINE override is defined for linux-x86 in the
|
||||
EPICS distribution. Comment out `COMMANDLINE_LIBRARY=READLINE` in
|
||||
`configure/os/CONFIG_SITE.Common.linux-x86` if readline is not
|
||||
installed on linux-x86. Command-line editing and history will then be
|
||||
those supplied by the os. On vxWorks the ledLib command-line input
|
||||
library is used instead.
|
||||
|
||||
### <span id="0_0_7">Host system storage requirements</span>
|
||||
|
||||
The compressed tar file is approximately 1.6 MB in size. The
|
||||
distribution source tree takes up approximately 12 MB. Each host
|
||||
target will need around 40 MB for build files, and each cross-compiled
|
||||
target around 20 MB.
|
||||
|
||||
### <span id="0_0_8">Documentation</span>
|
||||
|
||||
EPICS documentation is available through the [EPICS
|
||||
website](https://epics.anl.gov/) at Argonne.
|
||||
|
||||
Release specific documentation can also be found in the
|
||||
base/documentation directory of the distribution.
|
||||
|
||||
### <span id="0_0_10">Directory Structure</span>
|
||||
|
||||
#### Distribution directory structure:
|
||||
|
||||
```
|
||||
base Root directory of the base distribution
|
||||
base/configure Operating system independent build config files
|
||||
base/configure/os Operating system dependent build config files
|
||||
base/documentation Distribution documentation
|
||||
base/src Source code in various subdirectories
|
||||
base/startup Scripts for setting up path and environment
|
||||
```
|
||||
|
||||
#### Install directories created by the build:
|
||||
|
||||
```
|
||||
bin Installed scripts and executables in subdirs
|
||||
cfg Installed build configuration files
|
||||
db Installed data bases
|
||||
dbd Installed data base definitions
|
||||
doc Installed documentation files
|
||||
html Installed html documentation
|
||||
include Installed header files
|
||||
include/os Installed os specific header files in subdirs
|
||||
include/compiler Installed compiler-specific header files
|
||||
lib Installed libraries in arch subdirectories
|
||||
lib/perl Installed perl modules
|
||||
templates Installed templates
|
||||
```
|
||||
|
||||
### <span id="0_0_11">Build related components</span>
|
||||
|
||||
#### base/documentation directory - contains setup, build, and install documents
|
||||
|
||||
```
|
||||
README.md Instructions for setup and building epics base
|
||||
README.darwin.html Installation notes for Mac OS X (Darwin)
|
||||
RELEASE_NOTES.html Notes on release changes
|
||||
KnownProblems.html List of known problems and workarounds
|
||||
```
|
||||
|
||||
#### base/startup directory - contains scripts to set environment and path
|
||||
|
||||
```
|
||||
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
|
||||
|
||||
```
|
||||
CONFIG Includes configure files and allows variable overrides
|
||||
CONFIG.CrossCommon Cross build definitions
|
||||
CONFIG.gnuCommon Gnu compiler build definitions for all archs
|
||||
CONFIG_ADDONS Definitions for <osclass> and DEFAULT options
|
||||
CONFIG_APP_INCLUDE
|
||||
CONFIG_BASE EPICS base tool and location definitions
|
||||
CONFIG_BASE_VERSION Definitions for EPICS base version number
|
||||
CONFIG_COMMON Definitions common to all builds
|
||||
CONFIG_ENV Definitions of EPICS environment variables
|
||||
CONFIG_FILE_TYPE
|
||||
CONFIG_SITE Site specific make definitions
|
||||
CONFIG_SITE_ENV Site defaults for EPICS environment variables
|
||||
MAKEFILE Installs CONFIG* RULES* creates
|
||||
RELEASE Location of external products
|
||||
RULES Includes appropriate rules file
|
||||
RULES.Db Rules for database and database definition files
|
||||
RULES.ioc Rules for application iocBoot/ioc* directory
|
||||
RULES_ARCHS Definitions and rules for building architectures
|
||||
RULES_BUILD Build and install rules and definitions
|
||||
RULES_DIRS Definitions and rules for building subdirectories
|
||||
RULES_EXPAND
|
||||
RULES_FILE_TYPE
|
||||
RULES_TARGET
|
||||
RULES_TOP Rules specific to a <top> dir (uninstall and tar)
|
||||
Sample.Makefile Sample makefile with comments
|
||||
```
|
||||
|
||||
#### base/configure/os directory - contains os-arch specific definitions
|
||||
|
||||
```
|
||||
CONFIG.<host>.<target> Specific host-target build definitions
|
||||
CONFIG.Common.<target> Specific target definitions for all hosts
|
||||
CONFIG.<host>.Common Specific host definitions for all targets
|
||||
CONFIG.UnixCommon.Common Definitions for Unix hosts and all targets
|
||||
CONFIG.Common.UnixCommon Definitions for Unix targets and all hosts
|
||||
CONFIG.Common.vxWorksCommon Specific host definitions for all vx targets
|
||||
CONFIG_SITE.<host>.<target> Site specific host-target definitions
|
||||
CONFIG_SITE.Common.<target> Site specific target defs for all hosts
|
||||
CONFIG_SITE.<host>.Common Site specific host defs for all targets
|
||||
```
|
||||
|
||||
### <span id="0_0_12">Building EPICS base (Unix and Win32)</span>
|
||||
|
||||
#### Unpack file
|
||||
|
||||
Unzip and untar the distribution file. Use WinZip on Windows
|
||||
systems.
|
||||
|
||||
#### Set environment variables
|
||||
|
||||
Files in the base/startup directory have been provided to help set
|
||||
required path and other environment variables.
|
||||
|
||||
* `EPICS_HOST_ARCH`
|
||||
Before you can build or use EPICS R3.15, the environment variable
|
||||
`EPICS_HOST_ARCH` must be defined. A perl script EpicsHostArch.pl in
|
||||
the base/startup directory has been provided to help set
|
||||
`EPICS_HOST_ARCH.` You should have `EPICS_HOST_ARCH` set to your
|
||||
host operating system followed by a dash and then your host
|
||||
architecture, e.g. solaris-sparc. If you are not using the OS
|
||||
vendor's c/c++ compiler for host builds, you will need another dash
|
||||
followed by the alternate compiler name (e.g. "-gnu" for GNU c/c++
|
||||
compilers on a solaris host or "-mingw" for MinGW c/c++ compilers on
|
||||
a WIN32 host). See `configure/CONFIG_SITE` for a list of supported
|
||||
`EPICS_HOST_ARCH` values.
|
||||
|
||||
* `PERLLIB`
|
||||
On WIN32, some versions of Perl require that the environment
|
||||
variable PERLLIB be set to <perl directory location>.
|
||||
|
||||
* `PATH`
|
||||
As already mentioned, you must have the perl executable and you may
|
||||
need C and C++ compilers in your search path. For building base you
|
||||
also must have echo in your search path. For Unix host builds you
|
||||
also need ln, cpp, cp, rm, mv, and mkdir in your search path and
|
||||
/bin/chmod must exist. On some Unix systems you may also need ar and
|
||||
ranlib in your path, and the C compiler may require as and ld in
|
||||
your path. On solaris systems you need uname in your path.
|
||||
|
||||
* `LD_LIBRARY_PATH`
|
||||
R3.15 shared libraries and executables normally contain the full
|
||||
path to any libraries they require. However, if you move the EPICS
|
||||
files or directories from their build-time location then in order
|
||||
for the shared libraries to be found at runtime `LD_LIBRARY_PATH`
|
||||
must include the full pathname to
|
||||
`$(INSTALL_LOCATION)/lib/$(EPICS_HOST_ARCH)` when invoking
|
||||
executables, or some equivalent OS-specific mechanism (such as
|
||||
/etc/ld.so.conf on Linux) must be used. Shared libraries are now
|
||||
built by default on all Unix type hosts.
|
||||
|
||||
#### Do site-specific build configuration
|
||||
|
||||
**Site configuration**
|
||||
To configure EPICS, you may want to modify the default definitions
|
||||
in the following files:
|
||||
|
||||
```
|
||||
configure/CONFIG_SITE Build choices. Specify target archs.
|
||||
configure/CONFIG_SITE_ENV Environment variable defaults
|
||||
configure/RELEASE TORNADO2 full path location
|
||||
```
|
||||
|
||||
**Host configuration**
|
||||
To configure each host system, you may override the default
|
||||
definitions by adding a new file in the configure/os directory with
|
||||
override definitions. The new file should have the same name as the
|
||||
distribution file to be overridden except with CONFIG in the name
|
||||
changed to `CONFIG_SITE`.
|
||||
|
||||
```
|
||||
configure/os/CONFIG.<host>.<host> Host build settings
|
||||
configure/os/CONFIG.<host>.Common Host common build settings
|
||||
```
|
||||
|
||||
**Target configuration**
|
||||
To configure each target system, you may override the default
|
||||
definitions by adding a new file in the configure/os directory with
|
||||
override definitions. The new file should have the same name as the
|
||||
distribution file to be overridden except with CONFIG in the name
|
||||
replaced by `CONFIG_SITE`. This step is necessary even if the host
|
||||
system is the only target system.
|
||||
|
||||
```
|
||||
configure/os/CONFIG.Common.<target> Target common settings
|
||||
configure/os/CONFIG.<host>.<target> Host-target settings
|
||||
```
|
||||
|
||||
#### Build EPICS base
|
||||
|
||||
After configuring the build you should be able to build EPICS base
|
||||
by issuing the following commands in the distribution's root
|
||||
directory (base):
|
||||
|
||||
```
|
||||
gnumake clean uninstall
|
||||
gnumake
|
||||
```
|
||||
|
||||
The command "gnumake clean uninstall" will remove all files and
|
||||
directories generated by a previous build. The command "gnumake"
|
||||
will build and install everything for the configured host and
|
||||
targets.
|
||||
|
||||
It is recommended that you do a "gnumake clean uninstall" at the
|
||||
root directory of an EPICS directory structure before each complete
|
||||
rebuild to ensure that all components will be rebuilt.
|
||||
|
||||
### <span id="0_0_13">Example application and extension</span>
|
||||
|
||||
A perl tool, makeBaseApp.pl is included in the distribution file. This
|
||||
script will create a sample application that can be built and then
|
||||
executed to try out this release of base.
|
||||
|
||||
Instructions for building and executing the 3.15 example application
|
||||
can be found in the section "Example Application" of Chapter 2,
|
||||
"Getting Started", in the "IOC Application Developer's Guide" for this
|
||||
release. The "Example IOC Application" section briefly explains how to
|
||||
create and build an example application in a user created <top>
|
||||
directory. It also explains how to run the example application on a
|
||||
vxWorks ioc or as a process on the host system. By running the example
|
||||
application as a host-based IOC, you will be able to quickly implement
|
||||
a complete EPICS system and be able to run channel access clients on
|
||||
the host system.
|
||||
|
||||
A perl script, makeBaseExt.pl, is included in the distribution file.
|
||||
This script will create a sample extension that can be built and
|
||||
executed. The makeBaseApp.pl and makeBaseExt.pl scripts are installed
|
||||
into the install location `bin/<hostarch>` directory during the base
|
||||
build.
|
||||
|
||||
### <span id="0_0_14">Multiple host platforms</span>
|
||||
|
||||
You can build using a single EPICS directory structure on multiple
|
||||
host systems and for multiple cross target systems. The intermediate
|
||||
and binary files generated by the build will be created in separate
|
||||
subdirectories and installed into the appropriate separate host/target
|
||||
install directories. EPICS executables and perl scripts are installed
|
||||
into the `$(INSTALL_LOCATION)/bin/<arch>` directories. Libraries are
|
||||
installed into $`(INSTALL_LOCATION)/lib/<arch>`. The default
|
||||
definition for `$(INSTALL_LOCATION)` is `$(TOP)` which is the root
|
||||
directory in the distribution directory structure, base. Created
|
||||
object files are stored in `O.<arch>` source subdirectories, This
|
||||
allows objects for multiple cross target architectures to be
|
||||
maintained at the same time. To build EPICS base for a specific
|
||||
host/target combination you must have the proper host/target C/C++
|
||||
cross compiler and target header files and the base/configure/os
|
||||
directory must have the appropriate configure files.
|
||||
File diff suppressed because it is too large
Load Diff
1806
documentation/RELEASE_NOTES.md
Normal file
1806
documentation/RELEASE_NOTES.md
Normal file
File diff suppressed because it is too large
Load Diff
65
documentation/RecordReference.md
Normal file
65
documentation/RecordReference.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Record Reference Documentation
|
||||
|
||||
The following documentation for the record types and menus include with Base was
|
||||
converted from the old EPICS Wiki pages and updated. This list only includes the
|
||||
record types supplied with Base.
|
||||
|
||||
* [Fields Common to All Record Types](dbCommonRecord.html)
|
||||
* [Fields Common to Input Record Types](dbCommonInputs.html)
|
||||
* [Fields Common to Output Record Types](dbCommonOutputs.html)
|
||||
|
||||
## Record Types
|
||||
|
||||
* [Analog Array Input Record (aai)](aaiRecord.html)
|
||||
* [Analog Array Output Record (aao)](aaoRecord.html)
|
||||
* [Analog Input Record (ai)](aiRecord.html)
|
||||
* [Analog Output Record (ao)](aoRecord.html)
|
||||
* [Array Subroutine Record (aSub)](aSubRecord.html)
|
||||
* [Binary Input Record (bi)](biRecord.html)
|
||||
* [Binary Output Record (bo)](boRecord.html)
|
||||
* [Calculation Output Record (calcout)](calcoutRecord.html)
|
||||
* [Calculation Record (calc)](calcRecord.html)
|
||||
* [Compression Record (compress)](compressRecord.html)
|
||||
* [Data Fanout Record (dfanout)](dfanoutRecord.html)
|
||||
* [Event Record (event)](eventRecord.html)
|
||||
* [Fanout Record (fanout)](fanoutRecord.html)
|
||||
* [Histogram Record (histogram)](histogramRecord.html)
|
||||
* [Long Input Record (longin)](longinRecord.html)
|
||||
* [Long Output Record (longout)](longoutRecord.html)
|
||||
* [Long String Input Record (lsi)](lsiRecord.html)
|
||||
* [Long String Output Record (lso)](lsoRecord.html)
|
||||
* [Multi-Bit Binary Input Direct Record (mbbiDirect)](mbbiDirectRecord.html)
|
||||
* [Multi-Bit Binary Input Record (mbbi)](mbbiRecord.html)
|
||||
* [Multi-Bit Binary Output Direct Record (mbboDirect)](mbboDirectRecord.html)
|
||||
* [Multi-Bit Binary Output Record (mbbo)](mbboRecord.html)
|
||||
* [Permissive Record (permissive)](permissiveRecord.html)
|
||||
* [Printf Record (prinf)](printfRecord.html)
|
||||
* [Select Record (sel)](selRecord.html)
|
||||
* [Sequence Record (seq)](seqRecord.html)
|
||||
* [State Record (state)](stateRecord.html)
|
||||
* [String Input Record (stringin)](stringinRecord.html)
|
||||
* [String Output Record (stringout)](stringoutRecord.html)
|
||||
* [Sub-Array Record (subArray)](subArrayRecord.html)
|
||||
* [Subroutine Record (sub)](subRecord.html)
|
||||
* [Waveform Record (waveform)](waveformRecord.html)
|
||||
|
||||
## Menu Definitions
|
||||
|
||||
* [Alarm Severity Menu](menuAlarmSevr.html)
|
||||
* [Alarm Status Menu](menuAlarmStat.html)
|
||||
* [Analog Conversions Menu](menuConvert.html)
|
||||
* [Field Type Menu](menuFtype.html)
|
||||
* [Invalid Value Output Action Menu](menuIvoa.html)
|
||||
* [Output Mode Select Menu](menuOmsl.html)
|
||||
* [Scan Menu](menuScan.html)
|
||||
* [Simulation Mode Menu](menuSimm.html)
|
||||
* [Yes/No Menu](menuYesNo.html)
|
||||
|
||||
## Corrections and Updates
|
||||
|
||||
Corrections to these documents can be submitted as patch files to the EPICS core
|
||||
developers, or as merge requests or pull requests to the 3.15 branch of Base.
|
||||
The document sources can be found in the `src/std/rec` and `src/ioc/db`
|
||||
directories in files with extension `.dbd.pod`. The documentation source format
|
||||
is a combination of the EPICS DBD file format with an extended version of Perl's
|
||||
POD (plain old documentation); run `perldoc pod` for details of POD.
|
||||
@@ -136,17 +136,17 @@ relevent roles unless the Release Manager designates otherwise:</p>
|
||||
<td>Tag the module in Git, using these tag conventions:
|
||||
<ul>
|
||||
<li>
|
||||
<tt>R3.15.6-pre1</tt>
|
||||
<tt>R3.15.8-pre1</tt>
|
||||
— pre-release tag
|
||||
</li>
|
||||
<li>
|
||||
<tt>R3.15.6-rc1</tt>
|
||||
<tt>R3.15.8-rc1</tt>
|
||||
— release candidate tag
|
||||
</li>
|
||||
</ul>
|
||||
<blockquote><tt>
|
||||
cd base-3.15<br />
|
||||
git tag -m 'RL: Tagged for 3.15.6-rc1' R3.15.6-rc1
|
||||
git tag -m 'ANJ: Tagged for 3.15.8-rc1' R3.15.8-rc1
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -158,11 +158,11 @@ relevent roles unless the Release Manager designates otherwise:</p>
|
||||
files and directories that are only used for continuous integration:
|
||||
<blockquote><tt>
|
||||
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
|
||||
git archive --prefix=base-3.15.8-rc1/ --output=base-3.15.8-rc1.tar.gz R3.15.8-rc1 configure documentation LICENSE Makefile README src startup
|
||||
</tt></blockquote>
|
||||
Create a GPG signature file of the tarfile as follows:
|
||||
<blockquote><tt>
|
||||
gpg --armor --sign --detach-sig base-3.15.6-rc1.tar.gz
|
||||
gpg --armor --sign --detach-sig base-3.15.8-rc1.tar.gz
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -274,7 +274,7 @@ relevent roles unless the Release Manager designates otherwise:</p>
|
||||
<td>Tag the module in Git:
|
||||
<blockquote><tt>
|
||||
cd base-3.15<br />
|
||||
git tag -m 'RL: Tagged for 3.15.6' R3.15.6
|
||||
git tag -m 'ANJ: Tagged for 3.15.8' R3.15.8
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -285,11 +285,11 @@ relevent roles unless the Release Manager designates otherwise:</p>
|
||||
generates a gzipped tarfile directly from the repository:
|
||||
<blockquote><tt>
|
||||
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
|
||||
git archive --prefix=base-3.15.8/ --output=base-3.15.8.tar.gz R3.15.8 configure documentation LICENSE Makefile README src startup
|
||||
</tt></blockquote>
|
||||
Create a GPG signature file of the tarfile as follows:
|
||||
<blockquote><tt>
|
||||
gpg --armor --sign --detach-sig base-3.15.6.tar.gz
|
||||
gpg --armor --sign --detach-sig base-3.15.8.tar.gz
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -3137,7 +3137,8 @@ indicating the current state of the channel.</p>
|
||||
<dl>
|
||||
<dt><code>COUNT</code></dt>
|
||||
<dd>The element count to be read from the specified channel. A count of
|
||||
zero means use the current element count from the server.</dd>
|
||||
zero means use the current element count from the server, effectively
|
||||
resulting in a variable size array subscription.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>CHID</code></dt>
|
||||
|
||||
@@ -32,10 +32,12 @@
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
|
||||
#include "epicsAssert.h"
|
||||
#include "osiUnistd.h"
|
||||
#include "udpiiu.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
chdir ( "/" );
|
||||
ca_repeater ();
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
@@ -45,20 +45,12 @@ static epicsThreadOnceId cacOnce = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
const unsigned ca_client_context :: flushBlockThreshold = 0x58000;
|
||||
|
||||
extern "C" void cacExitHandler ( void *)
|
||||
{
|
||||
epicsThreadPrivateDelete ( caClientCallbackThreadId );
|
||||
caClientCallbackThreadId = 0;
|
||||
delete ca_client_context::pDefaultServiceInstallMutex;
|
||||
}
|
||||
|
||||
// runs once only for each process
|
||||
extern "C" void cacOnceFunc ( void * )
|
||||
{
|
||||
caClientCallbackThreadId = epicsThreadPrivateCreate ();
|
||||
assert ( caClientCallbackThreadId );
|
||||
ca_client_context::pDefaultServiceInstallMutex = newEpicsMutex;
|
||||
epicsAtExit ( cacExitHandler,0 );
|
||||
}
|
||||
|
||||
extern epicsThreadPrivateId caClientContextId;
|
||||
|
||||
@@ -288,7 +288,6 @@ private:
|
||||
};
|
||||
|
||||
extern "C" void cacOnceFunc ( void * );
|
||||
extern "C" void cacExitHandler ( void *);
|
||||
|
||||
struct ca_client_context : public cacContextNotify
|
||||
{
|
||||
@@ -428,7 +427,6 @@ private:
|
||||
ca_client_context & operator = ( const ca_client_context & );
|
||||
|
||||
friend void cacOnceFunc ( void * );
|
||||
friend void cacExitHandler ( void *);
|
||||
static cacService * pDefaultService;
|
||||
static epicsMutex * pDefaultServiceInstallMutex;
|
||||
static const unsigned flushBlockThreshold;
|
||||
|
||||
@@ -8,6 +8,18 @@
|
||||
TOP=../../../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
ifdef T_A
|
||||
PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version)
|
||||
PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname)
|
||||
PERL_ARCHPATH := $(PERL_VERSION)/$(PERL_ARCHNAME)
|
||||
|
||||
PERL_ARCHLIB := $(shell $(PERL) ../perlConfig.pl archlib)
|
||||
PERL_h = $(PERL_ARCHLIB)/CORE/perl.h
|
||||
|
||||
EXTUTILS := $(shell $(PERL) ../perlConfig.pl privlib)/ExtUtils
|
||||
PERLBIN := $(shell $(PERL) ../perlConfig.pl bin)
|
||||
XSUBPP := $(firstword $(wildcard $(PERLBIN)/xsubpp $(EXTUTILS)/xsubpp))
|
||||
|
||||
# Special settings for Darwin:
|
||||
ifeq ($(OS_CLASS),Darwin)
|
||||
# Use hdepends command (not GNU compiler flags)
|
||||
@@ -18,22 +30,23 @@ ifeq ($(OS_CLASS),Darwin)
|
||||
# Perl loadable libraries on Darwin have funny names
|
||||
LOADABLE_SHRLIB_PREFIX =
|
||||
LOADABLE_SHRLIB_SUFFIX = .$(shell $(PERL) ../perlConfig.pl dlext)
|
||||
|
||||
ifeq ($(wildcard $(PERL_h)),)
|
||||
# Perl's headers moved in Mojave
|
||||
SDK_PATH := $(shell xcodebuild -version -sdk macosx Path)
|
||||
PERL_ARCHLIB := $(SDK_PATH)/$(PERL_ARCHLIB)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef T_A
|
||||
PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version)
|
||||
PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname)
|
||||
PERL_ARCHPATH := $(PERL_VERSION)/$(PERL_ARCHNAME)
|
||||
|
||||
EXTUTILS := $(shell $(PERL) ../perlConfig.pl privlib)/ExtUtils
|
||||
PERLBIN := $(shell $(PERL) ../perlConfig.pl bin)
|
||||
XSUBPP := $(firstword $(wildcard $(PERLBIN)/xsubpp $(EXTUTILS)/xsubpp))
|
||||
|
||||
ifeq ($(T_A),$(EPICS_HOST_ARCH)) # No cross-builds (wrong Perl!)
|
||||
ifeq ($(strip $(XSUBPP)),)
|
||||
$(warning Perl's xsubpp program was not found.)
|
||||
$(warning The Perl CA module will not be built.)
|
||||
else
|
||||
ifeq ($(T_A),$(EPICS_HOST_ARCH)) # No cross-builds (wrong Perl!)
|
||||
ifeq ($(wildcard $(PERL_h)),)
|
||||
$(warning Perl's C header files were not found.)
|
||||
$(warning The Perl CA module will not be built.)
|
||||
else
|
||||
ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),) # Doesn't build on WIN32
|
||||
LOADABLE_LIBRARY_HOST = Cap5
|
||||
|
||||
@@ -52,10 +65,11 @@ endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
Cap5_SRCS = Cap5.xs
|
||||
Cap5_LIBS = ca Com
|
||||
Cap5_INCLUDES = -I$(shell $(PERL) ../perlConfig.pl archlib)/CORE
|
||||
Cap5_INCLUDES = -I$(PERL_ARCHLIB)/CORE
|
||||
Cap5_CFLAGS = $(shell $(PERL) ../perlConfig.pl ccflags)
|
||||
|
||||
CLEANS += Cap5.c
|
||||
|
||||
@@ -138,7 +138,14 @@ static void connection_handler ( struct connection_handler_args args )
|
||||
pv *ppv = ( pv * ) ca_puser ( args.chid );
|
||||
if ( args.op == CA_OP_CONN_UP ) {
|
||||
nConn++;
|
||||
if (!ppv->onceConnected) {
|
||||
|
||||
if (ppv->onceConnected && ppv->dbfType != ca_field_type(ppv->chid)) {
|
||||
/* Data type has changed. Rebuild connection with new type. */
|
||||
ca_clear_subscription(ppv->evid);
|
||||
ppv->evid = NULL;
|
||||
}
|
||||
|
||||
if (!ppv->evid) {
|
||||
ppv->onceConnected = 1;
|
||||
/* Set up pv structure */
|
||||
/* ------------------- */
|
||||
@@ -169,7 +176,7 @@ static void connection_handler ( struct connection_handler_args args )
|
||||
eventMask,
|
||||
event_handler,
|
||||
(void*)ppv,
|
||||
NULL);
|
||||
&ppv->evid);
|
||||
}
|
||||
}
|
||||
else if ( args.op == CA_OP_CONN_DOWN ) {
|
||||
|
||||
@@ -78,6 +78,7 @@ typedef struct
|
||||
epicsTimeStamp tsPreviousS;
|
||||
char firstStampPrinted;
|
||||
char onceConnected;
|
||||
evid evid;
|
||||
} pv;
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "shareLib.h"
|
||||
|
||||
typedef struct {
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
long status;
|
||||
} ASDBCALLBACK;
|
||||
|
||||
|
||||
@@ -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.
|
||||
#*************************************************************************
|
||||
|
||||
# This is a Makefile fragment, see src/ioc/Makefile.
|
||||
@@ -59,6 +59,9 @@ DBDINC += dbCommon
|
||||
|
||||
dbMenusPod = $(notdir $(wildcard ../db/menu*.dbd.pod))
|
||||
HTMLS += $(patsubst %.dbd.pod,%.html,$(dbMenusPod))
|
||||
HTMLS += dbCommonRecord.html
|
||||
HTMLS += dbCommonInput.html
|
||||
HTMLS += dbCommonOutput.html
|
||||
|
||||
dbCore_SRCS += dbLock.c
|
||||
dbCore_SRCS += dbAccess.c
|
||||
@@ -91,4 +94,3 @@ dbCore_SRCS += chfPlugin.c
|
||||
dbCore_SRCS += dbState.c
|
||||
dbCore_SRCS += dbUnitTest.c
|
||||
dbCore_SRCS += dbServer.c
|
||||
|
||||
|
||||
@@ -6,21 +6,25 @@
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
# This is a Makefile fragment, see src/ioc/Makefile.
|
||||
|
||||
dbCommon.h$(DEP): $(IOCDIR)/db/dbCommonRecord.dbd $(IOCDIR)/db/RULES
|
||||
@$(RM) $@
|
||||
@$(DBTORECORDTYPEH) -D -I ../db -o $(COMMONDEP_TARGET) $< > $@
|
||||
THESE_RULES := $(IOCDIR)/db/RULES
|
||||
|
||||
$(COMMON_DIR)/dbCommon.h: $(IOCDIR)/db/dbCommonRecord.dbd $(IOCDIR)/db/RULES
|
||||
dbCommon.h$(DEP): $(COMMON_DIR)/dbCommonRecord.dbd $(THESE_RULES)
|
||||
@$(RM) $@
|
||||
@$(DBTORECORDTYPEH) -D -I ../db -I $(COMMON_DIR) -o $(COMMONDEP_TARGET) $< > $@
|
||||
|
||||
$(COMMON_DIR)/dbCommonRecord.html: ../db/dbCommon.dbd.pod
|
||||
|
||||
$(COMMON_DIR)/dbCommon.h: $(COMMON_DIR)/dbCommonRecord.dbd $(THESE_RULES)
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBTORECORDTYPEH) -I ../db -o $(notdir $@) $<
|
||||
$(DBTORECORDTYPEH) -I ../db -I $(COMMON_DIR) -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/menuGlobal.dbd: $(IOCDIR)/db/Makefile $(IOCDIR)/db/RULES
|
||||
$(COMMON_DIR)/menuGlobal.dbd: $(IOCDIR)/db/Makefile $(THESE_RULES)
|
||||
|
||||
# This is a target-specific variable
|
||||
$(COMMON_DIR)/menuGlobal.dbd: DBDCAT_COMMAND = \
|
||||
|
||||
@@ -168,7 +168,7 @@ static void callbackTask(void *arg)
|
||||
epicsEventMustWait(mySet->semWakeUp);
|
||||
|
||||
while ((ptr = epicsRingPointerPop(mySet->queue))) {
|
||||
CALLBACK *pcallback = (CALLBACK *)ptr;
|
||||
epicsCallback *pcallback = (epicsCallback *)ptr;
|
||||
if(!epicsRingPointerIsEmpty(mySet->queue))
|
||||
epicsEventMustTrigger(mySet->semWakeUp);
|
||||
mySet->queueOverflow = FALSE;
|
||||
@@ -268,7 +268,7 @@ void callbackInit(void)
|
||||
}
|
||||
|
||||
/* This routine can be called from interrupt context */
|
||||
int callbackRequest(CALLBACK *pcallback)
|
||||
int callbackRequest(epicsCallback *pcallback)
|
||||
{
|
||||
int priority;
|
||||
int pushOK;
|
||||
@@ -297,7 +297,7 @@ int callbackRequest(CALLBACK *pcallback)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ProcessCallback(CALLBACK *pcallback)
|
||||
static void ProcessCallback(epicsCallback *pcallback)
|
||||
{
|
||||
dbCommon *pRec;
|
||||
|
||||
@@ -308,14 +308,14 @@ static void ProcessCallback(CALLBACK *pcallback)
|
||||
dbScanUnlock(pRec);
|
||||
}
|
||||
|
||||
void callbackSetProcess(CALLBACK *pcallback, int Priority, void *pRec)
|
||||
void callbackSetProcess(epicsCallback *pcallback, int Priority, void *pRec)
|
||||
{
|
||||
callbackSetCallback(ProcessCallback, pcallback);
|
||||
callbackSetPriority(Priority, pcallback);
|
||||
callbackSetUser(pRec, pcallback);
|
||||
}
|
||||
|
||||
int callbackRequestProcessCallback(CALLBACK *pcallback,
|
||||
int callbackRequestProcessCallback(epicsCallback *pcallback,
|
||||
int Priority, void *pRec)
|
||||
{
|
||||
callbackSetProcess(pcallback, Priority, pRec);
|
||||
@@ -324,11 +324,11 @@ int callbackRequestProcessCallback(CALLBACK *pcallback,
|
||||
|
||||
static void notify(void *pPrivate)
|
||||
{
|
||||
CALLBACK *pcallback = (CALLBACK *)pPrivate;
|
||||
epicsCallback *pcallback = (epicsCallback *)pPrivate;
|
||||
callbackRequest(pcallback);
|
||||
}
|
||||
|
||||
void callbackRequestDelayed(CALLBACK *pcallback, double seconds)
|
||||
void callbackRequestDelayed(epicsCallback *pcallback, double seconds)
|
||||
{
|
||||
epicsTimerId timer = (epicsTimerId)pcallback->timer;
|
||||
|
||||
@@ -339,7 +339,7 @@ void callbackRequestDelayed(CALLBACK *pcallback, double seconds)
|
||||
epicsTimerStartDelay(timer, seconds);
|
||||
}
|
||||
|
||||
void callbackCancelDelayed(CALLBACK *pcallback)
|
||||
void callbackCancelDelayed(epicsCallback *pcallback)
|
||||
{
|
||||
epicsTimerId timer = (epicsTimerId)pcallback->timer;
|
||||
|
||||
@@ -348,7 +348,7 @@ void callbackCancelDelayed(CALLBACK *pcallback)
|
||||
}
|
||||
}
|
||||
|
||||
void callbackRequestProcessCallbackDelayed(CALLBACK *pcallback,
|
||||
void callbackRequestProcessCallbackDelayed(epicsCallback *pcallback,
|
||||
int Priority, void *pRec, double seconds)
|
||||
{
|
||||
callbackSetProcess(pcallback, Priority, pRec);
|
||||
|
||||
@@ -26,7 +26,7 @@ extern "C" {
|
||||
/*
|
||||
* WINDOWS also has a "CALLBACK" type def
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(EPICS_NO_CALLBACK)
|
||||
# ifdef CALLBACK
|
||||
# undef CALLBACK
|
||||
# endif /*CALLBACK*/
|
||||
@@ -44,7 +44,9 @@ typedef struct callbackPvt {
|
||||
void *timer; /*for use by callback itself*/
|
||||
}epicsCallback;
|
||||
|
||||
#if !defined(EPICS_NO_CALLBACK)
|
||||
typedef epicsCallback CALLBACK;
|
||||
#endif
|
||||
|
||||
typedef void (*CALLBACKFUNC)(struct callbackPvt*);
|
||||
|
||||
@@ -55,21 +57,21 @@ typedef void (*CALLBACKFUNC)(struct callbackPvt*);
|
||||
#define callbackSetUser(USER,PCALLBACK)\
|
||||
( (PCALLBACK)->user = (void *)(USER) )
|
||||
#define callbackGetUser(USER,PCALLBACK)\
|
||||
( (USER) = (void *)((CALLBACK *)(PCALLBACK))->user )
|
||||
( (USER) = (void *)((epicsCallback *)(PCALLBACK))->user )
|
||||
|
||||
epicsShareFunc void callbackInit(void);
|
||||
epicsShareFunc void callbackStop(void);
|
||||
epicsShareFunc void callbackCleanup(void);
|
||||
epicsShareFunc int callbackRequest(CALLBACK *pCallback);
|
||||
epicsShareFunc int callbackRequest(epicsCallback *pCallback);
|
||||
epicsShareFunc void callbackSetProcess(
|
||||
CALLBACK *pcallback, int Priority, void *pRec);
|
||||
epicsCallback *pcallback, int Priority, void *pRec);
|
||||
epicsShareFunc int callbackRequestProcessCallback(
|
||||
CALLBACK *pCallback,int Priority, void *pRec);
|
||||
epicsCallback *pCallback,int Priority, void *pRec);
|
||||
epicsShareFunc void callbackRequestDelayed(
|
||||
CALLBACK *pCallback,double seconds);
|
||||
epicsShareFunc void callbackCancelDelayed(CALLBACK *pcallback);
|
||||
epicsCallback *pCallback,double seconds);
|
||||
epicsShareFunc void callbackCancelDelayed(epicsCallback *pcallback);
|
||||
epicsShareFunc void callbackRequestProcessCallbackDelayed(
|
||||
CALLBACK *pCallback, int Priority, void *pRec, double seconds);
|
||||
epicsCallback *pCallback, int Priority, void *pRec, double seconds);
|
||||
epicsShareFunc int callbackSetQueueSize(int size);
|
||||
epicsShareFunc int callbackParallelThreads(int count, const char *prio);
|
||||
|
||||
|
||||
@@ -730,9 +730,18 @@ int dbLoadDatabase(const char *file, const char *path, const char *subs)
|
||||
int dbLoadRecords(const char* file, const char* subs)
|
||||
{
|
||||
int status = dbReadDatabase(&pdbbase, file, 0, subs);
|
||||
|
||||
if (!status && dbLoadRecordsHook)
|
||||
dbLoadRecordsHook(file, subs);
|
||||
switch(status)
|
||||
{
|
||||
case 0:
|
||||
if(dbLoadRecordsHook)
|
||||
dbLoadRecordsHook(file, subs);
|
||||
break;
|
||||
case -2:
|
||||
errlogPrintf("dbLoadRecords: failed to load %s - cannot load records after running iocBuild!\n", file);
|
||||
break;
|
||||
default:
|
||||
errlogPrintf("dbLoadRecords: failed to load %s\n", file);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -898,6 +907,11 @@ long dbGet(DBADDR *paddr, short dbrType,
|
||||
} else {
|
||||
DBADDR localAddr = *paddr; /* Structure copy */
|
||||
|
||||
if (pfl->no_elements < 1) {
|
||||
status = S_db_badField;
|
||||
goto done;
|
||||
}
|
||||
|
||||
localAddr.field_type = pfl->field_type;
|
||||
localAddr.field_size = pfl->field_size;
|
||||
localAddr.no_elements = pfl->no_elements;
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
%#include "epicsTypes.h"
|
||||
%#include "link.h"
|
||||
field(NAME,DBF_STRING) {
|
||||
prompt("Record Name")
|
||||
special(SPC_NOMOD)
|
||||
size(61)
|
||||
}
|
||||
field(DESC,DBF_STRING) {
|
||||
prompt("Descriptor")
|
||||
promptgroup("10 - Common")
|
||||
size(41)
|
||||
}
|
||||
field(ASG,DBF_STRING) {
|
||||
prompt("Access Security Group")
|
||||
promptgroup("10 - Common")
|
||||
special(SPC_AS)
|
||||
size(29)
|
||||
}
|
||||
field(SCAN,DBF_MENU) {
|
||||
prompt("Scan Mechanism")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
}
|
||||
field(PINI,DBF_MENU) {
|
||||
prompt("Process at iocInit")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
menu(menuPini)
|
||||
}
|
||||
field(PHAS,DBF_SHORT) {
|
||||
prompt("Scan Phase")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
}
|
||||
field(EVNT,DBF_STRING) {
|
||||
prompt("Event Name")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
size(40)
|
||||
interest(1)
|
||||
}
|
||||
field(TSE,DBF_SHORT) {
|
||||
prompt("Time Stamp Event")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
field(TSEL,DBF_INLINK) {
|
||||
prompt("Time Stamp Link")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
field(DTYP,DBF_DEVICE) {
|
||||
prompt("Device Type")
|
||||
promptgroup("10 - Common")
|
||||
interest(1)
|
||||
}
|
||||
field(DISV,DBF_SHORT) {
|
||||
prompt("Disable Value")
|
||||
promptgroup("20 - Scan")
|
||||
initial("1")
|
||||
}
|
||||
field(DISA,DBF_SHORT) {
|
||||
prompt("Disable")
|
||||
}
|
||||
field(SDIS,DBF_INLINK) {
|
||||
prompt("Scanning Disable")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
%#include "epicsMutex.h"
|
||||
field(MLOK,DBF_NOACCESS) {
|
||||
prompt("Monitor lock")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("epicsMutexId mlok")
|
||||
}
|
||||
%#include "ellLib.h"
|
||||
field(MLIS,DBF_NOACCESS) {
|
||||
prompt("Monitor List")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("ELLLIST mlis")
|
||||
}
|
||||
field(DISP,DBF_UCHAR) {
|
||||
prompt("Disable putField")
|
||||
}
|
||||
field(PROC,DBF_UCHAR) {
|
||||
prompt("Force Processing")
|
||||
pp(TRUE)
|
||||
interest(3)
|
||||
}
|
||||
field(STAT,DBF_MENU) {
|
||||
prompt("Alarm Status")
|
||||
special(SPC_NOMOD)
|
||||
menu(menuAlarmStat)
|
||||
initial("UDF")
|
||||
}
|
||||
field(SEVR,DBF_MENU) {
|
||||
prompt("Alarm Severity")
|
||||
special(SPC_NOMOD)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(NSTA,DBF_MENU) {
|
||||
prompt("New Alarm Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmStat)
|
||||
}
|
||||
field(NSEV,DBF_MENU) {
|
||||
prompt("New Alarm Severity")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(ACKS,DBF_MENU) {
|
||||
prompt("Alarm Ack Severity")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(ACKT,DBF_MENU) {
|
||||
prompt("Alarm Ack Transient")
|
||||
promptgroup("70 - Alarm")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuYesNo)
|
||||
initial("YES")
|
||||
}
|
||||
field(DISS,DBF_MENU) {
|
||||
prompt("Disable Alarm Sevrty")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LCNT,DBF_UCHAR) {
|
||||
prompt("Lock Count")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
}
|
||||
field(PACT,DBF_UCHAR) {
|
||||
prompt("Record active")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(PUTF,DBF_UCHAR) {
|
||||
prompt("dbPutField process")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(RPRO,DBF_UCHAR) {
|
||||
prompt("Reprocess ")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(ASP,DBF_NOACCESS) {
|
||||
prompt("Access Security Pvt")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct asgMember *asp")
|
||||
}
|
||||
field(PPN,DBF_NOACCESS) {
|
||||
prompt("pprocessNotify")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct processNotify *ppn")
|
||||
}
|
||||
field(PPNR,DBF_NOACCESS) {
|
||||
prompt("pprocessNotifyRecord")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct processNotifyRecord *ppnr")
|
||||
}
|
||||
field(SPVT,DBF_NOACCESS) {
|
||||
prompt("Scan Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct scan_element *spvt")
|
||||
}
|
||||
field(RSET,DBF_NOACCESS) {
|
||||
prompt("Address of RSET")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct rset *rset")
|
||||
}
|
||||
field(DSET,DBF_NOACCESS) {
|
||||
prompt("DSET address")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct dset *dset")
|
||||
}
|
||||
field(DPVT,DBF_NOACCESS) {
|
||||
prompt("Device Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("void *dpvt")
|
||||
}
|
||||
field(RDES,DBF_NOACCESS) {
|
||||
prompt("Address of dbRecordType")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct dbRecordType *rdes")
|
||||
}
|
||||
field(LSET,DBF_NOACCESS) {
|
||||
prompt("Lock Set")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct lockRecord *lset")
|
||||
}
|
||||
field(PRIO,DBF_MENU) {
|
||||
prompt("Scheduling Priority")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
menu(menuPriority)
|
||||
}
|
||||
field(TPRO,DBF_UCHAR) {
|
||||
prompt("Trace Processing")
|
||||
}
|
||||
field(BKPT,DBF_NOACCESS) {
|
||||
prompt("Break Point")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
extra("char bkpt")
|
||||
}
|
||||
field(UDF,DBF_UCHAR) {
|
||||
prompt("Undefined")
|
||||
promptgroup("10 - Common")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
initial("1")
|
||||
}
|
||||
field(UDFS,DBF_MENU) {
|
||||
prompt("Undefined Alarm Sevrty")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
initial("INVALID")
|
||||
}
|
||||
%#include "epicsTime.h"
|
||||
field(TIME,DBF_NOACCESS) {
|
||||
prompt("Time")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
extra("epicsTimeStamp time")
|
||||
}
|
||||
field(FLNK,DBF_FWDLINK) {
|
||||
prompt("Forward Process Link")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
514
src/ioc/db/dbCommon.dbd.pod
Normal file
514
src/ioc/db/dbCommon.dbd.pod
Normal file
@@ -0,0 +1,514 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
The B<NAME> field contains the record name which must be unique within an
|
||||
EPICS Channel Access name space. The name is supplied by the application
|
||||
developer and is the means of identifying a specific record. The name has a
|
||||
maximum length of 60 characters and should use only this limited set of
|
||||
characters:
|
||||
|
||||
a-z A-Z 0-9 _ - : [ ] < > ;
|
||||
|
||||
The B<DESC> field may be set to provide a meaningful description of the
|
||||
record's purpose. Maximum length is 40 characters.
|
||||
|
||||
=fields NAME, DESC
|
||||
|
||||
=cut
|
||||
|
||||
%#include "epicsTypes.h"
|
||||
%#include "link.h"
|
||||
field(NAME,DBF_STRING) {
|
||||
prompt("Record Name")
|
||||
special(SPC_NOMOD)
|
||||
size(61)
|
||||
}
|
||||
field(DESC,DBF_STRING) {
|
||||
prompt("Descriptor")
|
||||
promptgroup("10 - Common")
|
||||
size(41)
|
||||
}
|
||||
field(ASG,DBF_STRING) {
|
||||
prompt("Access Security Group")
|
||||
promptgroup("10 - Common")
|
||||
special(SPC_AS)
|
||||
size(29)
|
||||
}
|
||||
|
||||
=head3 Scan Fields
|
||||
|
||||
These fields contain information related to how and when a record processes. A
|
||||
few records have unique fields that also affect how they process. These
|
||||
fields, if any, will be listed and explained in the section for each record.
|
||||
|
||||
The B<SCAN> field specifies the scanning period for periodic record scans or the
|
||||
scan type for non-periodic record scans. The default set of values for SCAN can
|
||||
be found in L<menuScan.dbd|menuScan>.
|
||||
|
||||
The choices provided by this menu are:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
C<Passive> for the record scan to be triggered by other records or Channel
|
||||
Access
|
||||
|
||||
=item *
|
||||
|
||||
C<Event> for event-driven scan
|
||||
|
||||
=item *
|
||||
|
||||
C<I/O Intr> for interrupt-driven scan
|
||||
|
||||
=item *
|
||||
|
||||
A set of periodic scan intervals
|
||||
|
||||
=back
|
||||
|
||||
Additional periodic scan rates may be defined for individual IOCs by making a
|
||||
local copy of menuScan.dbd and adding more choices as required. Scan rates
|
||||
should normally be defined in order, with the fastest rates appearing first.
|
||||
Scan periods may now be specified in seconds, minutes, hours or Hertz/Hz, and
|
||||
plural time units will also be accepted (seconds are used if no unit is
|
||||
mentioned in the choice string). For example the rates given below are all
|
||||
valid:
|
||||
|
||||
1 hour
|
||||
0.5 hours
|
||||
15 minutes
|
||||
3 seconds
|
||||
1 second
|
||||
2 Hertz
|
||||
|
||||
The B<PINI> field specifies record processing at initialization. If it is set
|
||||
to YES during database configuration, the record is processed once at IOC
|
||||
initialization (before the normal scan tasks are started).
|
||||
|
||||
The B<PHAS> field orders the records within a specific SCAN group. This is not
|
||||
meaningful for passive records. All records of a specified phase are processed
|
||||
before those with higher phase number. Whenever possible it is better to use
|
||||
linked passive records to enforce the order of processing rather than a phase
|
||||
number.
|
||||
|
||||
The B<EVNT> field specifies an event number. This event number is used if the
|
||||
SCAN field is set to C<Event>. All records with scan type C<Event> and the
|
||||
same EVNT value will be processed when a call to post_event for EVNT is made.
|
||||
The call to post_event is: post_event(short event_number).
|
||||
|
||||
The B<PRIO> field specifies the scheduling priority for processing records
|
||||
with SCAN=C<I/O Event> and asynchronous record completion tasks.
|
||||
|
||||
The B<DISV> field specifies a "disable value". Record processing is
|
||||
immediately terminated if the value of this field is equal to the value of the
|
||||
DISA field, i.e. the record is disabled. Note that field values of a record
|
||||
can be changed by database put or Channel Access, even if a record is
|
||||
disabled.
|
||||
|
||||
The B<DISA> field contains the value that is compared with DISV to determine
|
||||
if the record is disabled. The value of the DISA field is obtained via SDIS if
|
||||
SDIS is a database or channel access link. If SDIS is not a database or
|
||||
channel access link, then DISA can be set via dbPutField or dbPutLink.
|
||||
|
||||
If the B<PROC> field of a record is written to, the record is processed.
|
||||
|
||||
The B<DISS> field defines the record's "disable severity". If this field is
|
||||
not NO_ALARM and the record is disabled, the record will be put into alarm
|
||||
with this severity and a status of DISABLE_ALARM.
|
||||
|
||||
The B<LSET> field contains the lock set to which this record belongs. All
|
||||
records linked in any way via input, output, or forward database links belong
|
||||
to the same lock set. Lock sets are determined at IOC initialization time, and
|
||||
are updated whenever a database link is added, removed or altered.
|
||||
|
||||
The B<LCNT> field counts the number of times dbProcess finds the record active
|
||||
during successive scans, i.e. PACT is TRUE. If dbProcess finds the record
|
||||
active MAX_LOCK times (currently set to 10) it raises a SCAN_ALARM.
|
||||
|
||||
The B<PACT> field is TRUE while the record is being processed. For
|
||||
asynchronous records PACT can be TRUE from the time record processing is
|
||||
started until the asynchronous completion occurs. As long as PACT is TRUE,
|
||||
dbProcess will not call the record processing routine. See Application
|
||||
Developers Guide for details on usage of PACT.
|
||||
|
||||
The B<FLNK> field is a database link to another record (the "target" record).
|
||||
Processing a record with a specified FLNK field will force processing of the
|
||||
target record, provided the target record's SCAN field is set to C<Passive>.
|
||||
|
||||
The B<SPVT> field is for internal use by the scanning system.
|
||||
|
||||
=fields SCAN, PINI, PHAS, EVNT, PRIO, DISV, DISA, SDIS, PROC, DISS, LCNT, PACT, FLNK, SPVT
|
||||
|
||||
=cut
|
||||
|
||||
field(SCAN,DBF_MENU) {
|
||||
prompt("Scan Mechanism")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
}
|
||||
field(PINI,DBF_MENU) {
|
||||
prompt("Process at iocInit")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
menu(menuPini)
|
||||
}
|
||||
field(PHAS,DBF_SHORT) {
|
||||
prompt("Scan Phase")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
}
|
||||
field(EVNT,DBF_STRING) {
|
||||
prompt("Event Name")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
size(40)
|
||||
interest(1)
|
||||
}
|
||||
field(TSE,DBF_SHORT) {
|
||||
prompt("Time Stamp Event")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
field(TSEL,DBF_INLINK) {
|
||||
prompt("Time Stamp Link")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
field(DTYP,DBF_DEVICE) {
|
||||
prompt("Device Type")
|
||||
promptgroup("10 - Common")
|
||||
interest(1)
|
||||
}
|
||||
field(DISV,DBF_SHORT) {
|
||||
prompt("Disable Value")
|
||||
promptgroup("20 - Scan")
|
||||
initial("1")
|
||||
}
|
||||
field(DISA,DBF_SHORT) {
|
||||
prompt("Disable")
|
||||
}
|
||||
field(SDIS,DBF_INLINK) {
|
||||
prompt("Scanning Disable")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
%#include "epicsMutex.h"
|
||||
field(MLOK,DBF_NOACCESS) {
|
||||
prompt("Monitor lock")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("epicsMutexId mlok")
|
||||
}
|
||||
%#include "ellLib.h"
|
||||
field(MLIS,DBF_NOACCESS) {
|
||||
prompt("Monitor List")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("ELLLIST mlis")
|
||||
}
|
||||
field(DISP,DBF_UCHAR) {
|
||||
prompt("Disable putField")
|
||||
}
|
||||
field(PROC,DBF_UCHAR) {
|
||||
prompt("Force Processing")
|
||||
pp(TRUE)
|
||||
interest(3)
|
||||
}
|
||||
|
||||
=head3 Alarm Fields
|
||||
|
||||
These fields indicate the status and severity of alarms, or else determine the
|
||||
how and when alarms are triggered. Of course, many records have alarm-related
|
||||
fields not common to all records. These fields are listed and explained in the
|
||||
appropriate section on each record.
|
||||
|
||||
The B<STAT> field contains the current alarm status.
|
||||
|
||||
The B<SEVR> field contains the current alarm severity.
|
||||
|
||||
These two fields are seen outside database access. The B<NSTA> and B<NSEV>
|
||||
fields are used by the database access, record support, and device support
|
||||
routines to set new alarm status and severity values. Whenever any software
|
||||
component discovers an alarm condition, it uses the following macro function:
|
||||
recGblSetSevr(precord,new_status,new_severity) This ensures that the current
|
||||
alarm severity is set equal to the highest outstanding alarm. The file alarm.h
|
||||
defines all allowed alarm status and severity values.
|
||||
|
||||
The B<ACKS> field contains the highest unacknowledged alarm severity.
|
||||
|
||||
The B<ACKT> field specifies if it is necessary to acknowledge transient
|
||||
alarms.
|
||||
|
||||
The B<UDF> indicates if the record's value is B<U>nB<D>eB<F>ined. Typically
|
||||
this is caused by a failure in device support, the fact that the record has
|
||||
never been processed, or that the VAL field currently contains a NaN (not a
|
||||
number). UDF is initialized to TRUE at IOC initialization. Record and device
|
||||
support routines which write to the VAL field are responsible for setting UDF.
|
||||
|
||||
=fields STAT, SEVR, NSTA, NSEV, ACKS, ACKT, UDF
|
||||
|
||||
=cut
|
||||
|
||||
field(STAT,DBF_MENU) {
|
||||
prompt("Alarm Status")
|
||||
special(SPC_NOMOD)
|
||||
menu(menuAlarmStat)
|
||||
initial("UDF")
|
||||
}
|
||||
field(SEVR,DBF_MENU) {
|
||||
prompt("Alarm Severity")
|
||||
special(SPC_NOMOD)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(NSTA,DBF_MENU) {
|
||||
prompt("New Alarm Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmStat)
|
||||
}
|
||||
field(NSEV,DBF_MENU) {
|
||||
prompt("New Alarm Severity")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(ACKS,DBF_MENU) {
|
||||
prompt("Alarm Ack Severity")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(ACKT,DBF_MENU) {
|
||||
prompt("Alarm Ack Transient")
|
||||
promptgroup("70 - Alarm")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuYesNo)
|
||||
initial("YES")
|
||||
}
|
||||
field(DISS,DBF_MENU) {
|
||||
prompt("Disable Alarm Sevrty")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LCNT,DBF_UCHAR) {
|
||||
prompt("Lock Count")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
}
|
||||
field(PACT,DBF_UCHAR) {
|
||||
prompt("Record active")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(PUTF,DBF_UCHAR) {
|
||||
prompt("dbPutField process")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(RPRO,DBF_UCHAR) {
|
||||
prompt("Reprocess ")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(ASP,DBF_NOACCESS) {
|
||||
prompt("Access Security Pvt")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct asgMember *asp")
|
||||
}
|
||||
field(PPN,DBF_NOACCESS) {
|
||||
prompt("pprocessNotify")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct processNotify *ppn")
|
||||
}
|
||||
field(PPNR,DBF_NOACCESS) {
|
||||
prompt("pprocessNotifyRecord")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct processNotifyRecord *ppnr")
|
||||
}
|
||||
field(SPVT,DBF_NOACCESS) {
|
||||
prompt("Scan Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct scan_element *spvt")
|
||||
}
|
||||
|
||||
=head3 Device Fields
|
||||
|
||||
The B<RSET> field contains the address of the Record Support Entry Table. See
|
||||
the Application Developers Guide for details on usage.
|
||||
|
||||
The B<DSET> field contains the address of Device Support Entry Table. The
|
||||
value of this field is determined at IOC initialization time. Record support
|
||||
routines use this field to locate their device support routines.
|
||||
|
||||
The B<DPVT> field is is for private use of the device support modules.
|
||||
|
||||
=fields RSET, DSET, DPVT
|
||||
|
||||
=cut
|
||||
|
||||
field(RSET,DBF_NOACCESS) {
|
||||
prompt("Address of RSET")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct rset *rset")
|
||||
}
|
||||
field(DSET,DBF_NOACCESS) {
|
||||
prompt("DSET address")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct dset *dset")
|
||||
}
|
||||
field(DPVT,DBF_NOACCESS) {
|
||||
prompt("Device Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("void *dpvt")
|
||||
}
|
||||
field(RDES,DBF_NOACCESS) {
|
||||
prompt("Address of dbRecordType")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct dbRecordType *rdes")
|
||||
}
|
||||
field(LSET,DBF_NOACCESS) {
|
||||
prompt("Lock Set")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct lockRecord *lset")
|
||||
}
|
||||
field(PRIO,DBF_MENU) {
|
||||
prompt("Scheduling Priority")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
menu(menuPriority)
|
||||
}
|
||||
|
||||
=head3 Debugging Fields
|
||||
|
||||
The B<TPRO> field is used for trace processing. If this field is non-zero a
|
||||
message is printed whenever this record is processed, and when any other
|
||||
record in the same lock-set is processed by a database link from this record.
|
||||
|
||||
The B<BKPT> field indicates if there is a breakpoint set at this record. This
|
||||
supports setting a debug breakpoint in the record processing. STEP through
|
||||
database processing can be supported using this.
|
||||
|
||||
=fields TPRO, BKPT
|
||||
|
||||
|
||||
=head3 Miscellaneous Fields
|
||||
|
||||
The B<ASG> field contains a character string value defining the access
|
||||
security group for this record. If left empty, the record is placed in group
|
||||
DEFAULT.
|
||||
|
||||
The B<ASP> field is a field for private use of the access security system.
|
||||
|
||||
The B<DISP> field controls dbPutFields to this record which are normally
|
||||
issued by channel access. If the field is set to TRUE all dbPutFields
|
||||
directed to this record are ignored except to the field DISP itself.
|
||||
|
||||
The B<DTYP> field specifies the device type for the record. Each record type
|
||||
has its own set of device support routines which are specified in
|
||||
devSup.ASCII. If a record type does not have any associated device support,
|
||||
DTYP and DSET are meaningless.
|
||||
|
||||
The B<MLOK> field contains the monitor lock. The lock used by the monitor
|
||||
routines when the monitor list is being used. The list is locked whenever
|
||||
monitors are being scheduled, invoked, or when monitors are being added to or
|
||||
removed from the list. This field is accessed only by the dbEvent routines.
|
||||
|
||||
The B<MLIS> field is the head of the list of monitors connected to this
|
||||
record. Each record support module is responsible for triggering monitors for
|
||||
any fields that change as a result of record processing. Monitors are present
|
||||
if mlis count is greater than zero. The call to trigger monitors is:
|
||||
db_post_event(precord,&data,mask), where "mask" is some combination of
|
||||
DBE_ALARM, DBE_VALUE, and DBE_LOG.
|
||||
|
||||
The B<PPN> field contains the address of a putNotify callback.
|
||||
|
||||
The B<PPNR> field contains the next record for PutNotify.
|
||||
|
||||
The B<PUTF> field is set to TRUE if dbPutField caused the current record
|
||||
processing.
|
||||
|
||||
The B<RDES> field contains the address of dbRecordType
|
||||
|
||||
The B<RPRO> field specifies a reprocessing of the record when current
|
||||
processing completes.
|
||||
|
||||
The B<TIME> field contains the time when this record was last processed in
|
||||
standard format.
|
||||
|
||||
The B<TSE> field indicates the mechanism to use to get the time stamp. '0' -
|
||||
call get time as before '-1' - call the time stamp driver and use the best
|
||||
source available. '-2' - the device support provides the time stamp from the
|
||||
hardware. Values between 1-255 request the time of the last occurance of a
|
||||
generalTime event.
|
||||
|
||||
The B<TSEL> field contains an input link for obtaining the time stamp. If this
|
||||
link references the .TIME field of a record then the time stamp of the
|
||||
referenced record becomes the time stamp for this record as well. In this
|
||||
case, an internal flag is set and ".TIME" is then overwritten by ".VAL". If
|
||||
any other field is referenced, the field value is read and stored in the .TSE
|
||||
field which is then used to acquire a timestamp.
|
||||
|
||||
=fields ASG, ASP, DISP, DTYP, MLOK, MLIS, PPN, PPNR, PUTF, RDES, RPRO, TIME, TSE, TSEL
|
||||
|
||||
=cut
|
||||
|
||||
field(TPRO,DBF_UCHAR) {
|
||||
prompt("Trace Processing")
|
||||
}
|
||||
field(BKPT,DBF_NOACCESS) {
|
||||
prompt("Break Point")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
extra("char bkpt")
|
||||
}
|
||||
field(UDF,DBF_UCHAR) {
|
||||
prompt("Undefined")
|
||||
promptgroup("10 - Common")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
initial("1")
|
||||
}
|
||||
field(UDFS,DBF_MENU) {
|
||||
prompt("Undefined Alarm Sevrty")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
initial("INVALID")
|
||||
}
|
||||
%#include "epicsTime.h"
|
||||
field(TIME,DBF_NOACCESS) {
|
||||
prompt("Time")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
extra("epicsTimeStamp time")
|
||||
}
|
||||
field(FLNK,DBF_FWDLINK) {
|
||||
prompt("Forward Process Link")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
181
src/ioc/db/dbCommonInput.pod
Normal file
181
src/ioc/db/dbCommonInput.pod
Normal file
@@ -0,0 +1,181 @@
|
||||
#*************************************************************************
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Fields Common to Input Record Types
|
||||
|
||||
This section describes fields that are found in many input record types.
|
||||
These fields usually have the same meaning whenever they are used.
|
||||
|
||||
See also L<Fields Common to All Record Types|dbCommonRecord> and L<Fields Common
|
||||
to Output Record Types|dbCommonOutput>.
|
||||
|
||||
=head3 Input and Value Fields
|
||||
|
||||
The B<INP> field specifies an input link. It is used by the device support
|
||||
routines to obtain input. For soft analog records it can be a constant, a
|
||||
database link, or a channel access link.
|
||||
|
||||
The B<DTYP> field specifies the name of the device support module that will
|
||||
input values. Each record type has its own set of device support routines. If
|
||||
a record type does not have any associated device support, DTYP is
|
||||
meaningless.
|
||||
|
||||
The B<RVAL> field contains - whenever possible - the raw data value exactly as
|
||||
it is obtained from the hardware or from the associated device driver and
|
||||
before it undergoes any conversions. The Soft Channel device support module
|
||||
reads values directly into VAL, bypassing this field.
|
||||
|
||||
The B<VAL> field contains the record's final value, after any needed
|
||||
conversions have been performed.
|
||||
|
||||
=head3 Device Input
|
||||
|
||||
A device input routine normally returns one of the following values to its
|
||||
associated record support routine:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
0: Success and convert. The input value is in RVAL. The record support module
|
||||
will compute VAL from RVAL.
|
||||
|
||||
=item *
|
||||
|
||||
2: Success, but don't convert. The device support module can specify this
|
||||
value if it does not want any conversions. It might do this for two reasons:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
A hardware error is detected (in this case, it should also raise an alarm
|
||||
condition).
|
||||
|
||||
=item *
|
||||
|
||||
The device support routine reads values directly into the VAL field and then
|
||||
sets UDF to FALSE. For some record types the device support routine may have to
|
||||
do other record-specific processing as well such as applying a smoothing filter
|
||||
to the engineering units value.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
=head3 Device Support for Soft Records
|
||||
|
||||
In most cases, two soft output device support modules are provided: Soft Channel
|
||||
and Raw Soft Channel. Both allow INP to be a constant, a database link, or a
|
||||
channel access link. The Soft Channel device support module reads input directly
|
||||
into the VAL field and specifies that no value conversion should be performed.
|
||||
This allows the record to store values in the data type of its VAL field. Note
|
||||
that for Soft Channel input, the RVAL field is not used. The Raw Soft Channel
|
||||
support module reads input into RVAL and indicates that any specified unit
|
||||
conversions be performed.
|
||||
|
||||
The device support read routine normally calls C<dbGetLink()> which
|
||||
fetches a value from the link.
|
||||
|
||||
If a value was returned by the link the UDF field is set to FALSE. The device
|
||||
support read routine normally returns the status from C<dbGetLink()>.
|
||||
|
||||
|
||||
=head3 Input Simulation Fields
|
||||
|
||||
The B<SIMM> field controls simulation mode. It has either the value YES or NO.
|
||||
By setting this field to YES, the record can be switched into simulation mode
|
||||
of operation. While in simulation mode, input will be obtained from SIOL
|
||||
instead of INP.
|
||||
|
||||
Ths B<SIML> specifies the simulation mode location. This field can be a
|
||||
constant, a database link, or a channel access link. If SIML is a database or
|
||||
channel access link, then SIMM is read from SIML. If SIML is a constant link
|
||||
then SIMM is initialized with the constant value but can be changed via
|
||||
dbPuts.
|
||||
|
||||
Ths B<SVAL> field contains the simulation value. This is the record's input
|
||||
value, in engineering units, when the record is switched into simulation mode,
|
||||
i.e. when SIMM is set to YES.
|
||||
|
||||
The B<SIOL> field is a link that can be used to fetch the simulation value. The
|
||||
link can be a constant, a database link, or a channel access link. If SIOL is a
|
||||
database or channel access link, then SVAL is read from SIOL. If SIOL is a
|
||||
constant link then SVAL is initialized with the constant value but can be
|
||||
changed via dbPuts.
|
||||
|
||||
The B<SIMS> field specifies the simulation mode alarm severity. When this
|
||||
field is set to a value other than NO_ALARM and the record is in simulation
|
||||
mode, it will be put into alarm with this severity and a status of SIMM.
|
||||
|
||||
=head3 Simulation Mode for Input Records
|
||||
|
||||
An input record can be switched into simulation mode of operation by setting
|
||||
the value of SIMM to YES or RAW. During simulation, the record will be put
|
||||
into alarm with a severity of SIMS and a status of SIMM_ALARM. While in
|
||||
simulation mode, input values will be read from SIOL instead of INP:
|
||||
|
||||
-- (SIMM = NO?) INP (if supported and directed by device support, -> RVAL -- convert -> VAL), (else -> VAL)
|
||||
/
|
||||
|
||||
SIML -> SIMM
|
||||
|
||||
\
|
||||
-- (SIMM = YES?) SIOL -> SVAL -> VAL
|
||||
\
|
||||
-- (SIMM = RAW?) SIOL -> SVAL -> RVAL -- convert -> VAL
|
||||
|
||||
A record can be switched into simulation mode of operation by setting the
|
||||
value of SIMM to YES. During simulation, the record will be put into alarm
|
||||
with a severity of SIMS and a status of SIMM_ALARM. While in simulation mode,
|
||||
input values, in engineering units, will be obtained from SIOL instead of INP.
|
||||
Also, while the record is in simulation mode, there will be no raw value
|
||||
conversion and no calls to device support when the record is processed.
|
||||
|
||||
Normally input records contain a private readValue() routine which performs
|
||||
the following steps:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If PACT is TRUE, the device support read routine is called, status is set to
|
||||
its return code, and readValue returns.
|
||||
|
||||
=item *
|
||||
|
||||
Call C<dbGetLink()> to get a new value for SIMM from SIML.
|
||||
|
||||
=item *
|
||||
|
||||
Check value of SIMM.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is NO, then call the device support read routine, set status to its
|
||||
return code, and return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is YES, then call C<dbGetLink()> to read the input value from SIOL
|
||||
into SVAL. If success, then set VAL to SVAL and UDF to FALSE and set status to
|
||||
2 (don't convert) if input record supports conversion. If SIMS is greater than
|
||||
zero, set alarm status to SIMM and severity to SIMS. Set status to the return
|
||||
code from recGblGetLinkValue and return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is RAW, then call C<dbGetLink()> to read the input value from SIOL
|
||||
into SVAL. If success, then set RVAL to SVAL and UDF to FALSE and set status
|
||||
to 0 (convert) if input record supports conversion. If SIMS is greater than
|
||||
zero, set alarm status to SIMM and severity to SIMS. Set status to the return
|
||||
code from recGblGetLinkValue and return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is not YES, NO or RAW, a SOFT alarm with a severity of INVALID is
|
||||
raised, and return status is set to -1.
|
||||
|
||||
=back
|
||||
211
src/ioc/db/dbCommonOutput.pod
Normal file
211
src/ioc/db/dbCommonOutput.pod
Normal file
@@ -0,0 +1,211 @@
|
||||
#*************************************************************************
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Fields Common to Output Record Types
|
||||
|
||||
This section describes fields that are found in many output record types.
|
||||
These fields usually have the same meaning whenever they are used.
|
||||
|
||||
See also L<Fields Common to All Record Types|dbCommonRecord> and L<Fields Common to
|
||||
Input Records|dbCommonInput>.
|
||||
|
||||
=head3 Output and Value Fields
|
||||
|
||||
The B<OUT> field specifies an output link. It is used by the device support
|
||||
routines to decide where to send output. For soft records, it can be a
|
||||
constant, a database link, or a channel access link. If the link is a
|
||||
constant, the result is no output.
|
||||
|
||||
The B<DTYP> field specifies the name of the device support module that will
|
||||
input values. Each record type has its own set of device support routines. If
|
||||
a record type does not have any associated device support, DTYP is
|
||||
meaningless.
|
||||
|
||||
The B<VAL> field contains the desired value before any conversions to raw
|
||||
output have been performed.
|
||||
|
||||
The B<OVAL> field is used to decide when to invoke monitors. Archive and value
|
||||
change monitors are invoked if OVAL is not equal to VAL. If a record type
|
||||
needs to make adjustments, OVAL is used to enforce the maximum rate of change
|
||||
limit before converting the desired value to a raw value.
|
||||
|
||||
The B<RVAL> field contains - whenever possible - the actual value sent to the
|
||||
hardware itself or to the associated device driver.
|
||||
|
||||
The B<RBV> field contains - whenever possible - the actual read back value
|
||||
obtained from the hardware itself or from the associated device driver.
|
||||
|
||||
|
||||
=head3 Device Support for Soft Records
|
||||
|
||||
Normally two soft output device support modules are provided, Soft Channel and
|
||||
and Raw Soft Channel. Both write a value through the output link OUT.
|
||||
The Soft Channel module writes output from the value associated with OVAL or
|
||||
VAL (if OVAL does not exist). The Raw Soft Channel support module writes the
|
||||
value associated with the RVAL field after conversion has been performed.
|
||||
|
||||
The device support write routine normally calls C<dbPutLink()> which writes a
|
||||
value through the OUT link, and returns the status from that call.
|
||||
|
||||
|
||||
=head3 Input and Mode Select Fields
|
||||
|
||||
The B<DOL> field is a link from which the desired output value can be fetched.
|
||||
DOL can be a constant, a database link, or a channel access link. If DOL is a
|
||||
database or channel access link and OMSL is closed_loop, then VAL is obtained
|
||||
from DOL.
|
||||
|
||||
The B<OMSL> field selects the output mode. This field has either the value
|
||||
C<supervisory> or C<closed_loop>. DOL is used to fetch VAL only if OMSL has the
|
||||
value C<closed_loop>. By setting this field a record can be switched between
|
||||
supervisory and closed loop mode of operation. While in closed loop mode, the
|
||||
VAL field cannot be set via dbPuts.
|
||||
|
||||
=head3 Output Mode Selection
|
||||
|
||||
The fields DOL and OMSL are used to allow the output record to be part of a
|
||||
closed loop control algorithm. OMSL is meaningful only if DOL refers to a
|
||||
database or channel access link. It can have the values C<supervisory> or
|
||||
C<closed_loop>. If the mode is C<supervisory>, then nothing is done to VAL. If
|
||||
the mode is C<closed_loop> and the record type does not contain an OIF field,
|
||||
then each time the record is processed, VAL is set equal to the value obtained
|
||||
from the location referenced by DOL. If the mode is C<closed_loop> in record
|
||||
types with an OIF field and OIF is Full, VAL is set equal to the value obtained
|
||||
from the location referenced by DOL; if OIF is Incremental VAL is incremented by
|
||||
the value obtained from DOL.
|
||||
|
||||
=head3 Invalid Output Action Fields
|
||||
|
||||
The B<IVOA> field specifies the output action for the case that the record is
|
||||
put into an INVALID alarm severity. IVOA can be one of the following actions:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
C<Continue normally>
|
||||
|
||||
=item *
|
||||
|
||||
C<Don't drive outputs>
|
||||
|
||||
=item *
|
||||
|
||||
C<Set output to IVOV>
|
||||
|
||||
=back
|
||||
|
||||
The B<IVOV> field contains the value for the IVOA action C<Set output to IVOV>
|
||||
in engineering units. If a new severity has been set to INVALID and IVOA is
|
||||
C<Set output to IVOV>, then VAL is set to IVOV and converted to RVAL before
|
||||
device support is called.
|
||||
|
||||
=head3 Invalid Alarm Output Action
|
||||
|
||||
Whenever an output record is put into INVALID alarm severity, IVOA specifies
|
||||
an action to take. The record support process routine for each output record
|
||||
contains code which performs the following steps.
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If new severity is less than INVALID, then call C<writeValue()>:
|
||||
|
||||
=item *
|
||||
|
||||
Else do the following:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If IVOA is C<Continue normally> then call C<writeValue()>.
|
||||
|
||||
=item *
|
||||
|
||||
If IVOA is C<Don't drive outputs> then do not write output.
|
||||
|
||||
=item *
|
||||
|
||||
If IVOA is C<Set output to IVOV> then set VAL to IVOV, call C<convert()> if
|
||||
necessary, and then call C<writeValue()>.
|
||||
|
||||
=item *
|
||||
|
||||
If IVOA not one of the above, an error message is generated.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head3 Simulation Fields
|
||||
|
||||
The B<SIMM> field controls simulation mode. It has either the value YES or NO.
|
||||
By setting this field to YES, the record can be switched into simulation mode
|
||||
of operation. While in simulation mode, output will be forwarded through SIOL
|
||||
instead of OUT.
|
||||
|
||||
Ths B<SIML> specifies the simulation mode location. This field can be a
|
||||
constant, a database link, or a channel access link. If SIML is a database or
|
||||
channel access link, then SIMM is read from SIML. If SIML is a constant link
|
||||
then SIMM is initialized with the constant value but can be changed via
|
||||
dbPuts.
|
||||
|
||||
The B<SIOL> field is a link that the output value is written to when the record
|
||||
is in simulation mode.
|
||||
|
||||
The B<SIMS> field specifies the simulation mode alarm severity. When this
|
||||
field is set to a value other than NO_ALARM and the record is in simulation
|
||||
mode, it will be put into alarm with this severity and a status of SIMM.
|
||||
|
||||
=head3 Simulation Mode
|
||||
|
||||
An output record can be switched into simulation mode of operation by setting
|
||||
the value of SIMM to YES. During simulation, the record will be put into alarm
|
||||
with a severity of SIMS and a status of SIMM_ALARM. While in simulation mode,
|
||||
output values, in engineering units, will be written to SIOL instead of OUT.
|
||||
However, the output values are never converted. Also, while the record is in
|
||||
simulation mode, there will be no calls to device support during record
|
||||
processing.
|
||||
|
||||
Normally output records contain a private C<writeValue()> routine which performs
|
||||
the following steps:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If PACT is TRUE, the device support write routine is called, status is set to
|
||||
its return code, and readValue returns.
|
||||
|
||||
=item *
|
||||
|
||||
Call C<dbGetLink()> to get a new value for SIMM if SIML is a DB_LINK or a
|
||||
CA_LINK.
|
||||
|
||||
=item *
|
||||
|
||||
Check value of SIMM.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is NO, then call the device support write routine, set status to its
|
||||
return code, and return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is YES, then call C<dbPutLink()> to write the output value from VAL or
|
||||
OVAL to SIOL. Set alarm status to SIMM and severity to SIMS, if SIMS is
|
||||
greater than zero. Set status to the return code from C<dbPutLink()> and
|
||||
return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM not one of the above, a SOFT alarm with a severity of INVALID is
|
||||
raised, and return status is set to -1.
|
||||
|
||||
=back
|
||||
@@ -1,12 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(dbCommon) {
|
||||
include "dbCommon.dbd"
|
||||
}
|
||||
20
src/ioc/db/dbCommonRecord.dbd.pod
Normal file
20
src/ioc/db/dbCommonRecord.dbd.pod
Normal file
@@ -0,0 +1,20 @@
|
||||
#*************************************************************************
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Fields Common to All Record Types
|
||||
|
||||
This section contains a description of the fields that are common to all record
|
||||
types. These fields are defined in dbCommon.dbd.
|
||||
|
||||
See also L<Fields Common to Input Record Types|dbCommonInput> and L<Fields
|
||||
Common to Output Record Types|dbCommonOutput>.
|
||||
|
||||
=recordtype dbCommon
|
||||
|
||||
=cut
|
||||
|
||||
recordtype(dbCommon) {
|
||||
include "dbCommon.dbd.pod"
|
||||
}
|
||||
@@ -1165,3 +1165,8 @@ void db_delete_field_log (db_field_log *pfl)
|
||||
freeListFree(dbevFieldLogFreeList, pfl);
|
||||
}
|
||||
}
|
||||
|
||||
int db_available_logs(void)
|
||||
{
|
||||
return (int) freeListItemsAvail(dbevFieldLogFreeList);
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ epicsShareFunc void db_event_disable (dbEventSubscription es);
|
||||
epicsShareFunc struct db_field_log* db_create_event_log (struct evSubscrip *pevent);
|
||||
epicsShareFunc struct db_field_log* db_create_read_log (struct dbChannel *chan);
|
||||
epicsShareFunc void db_delete_field_log (struct db_field_log *pfl);
|
||||
epicsShareFunc int db_available_logs(void);
|
||||
|
||||
#define DB_EVENT_OK 0
|
||||
#define DB_EVENT_ERROR (-1)
|
||||
@@ -87,4 +88,3 @@ epicsShareFunc void db_delete_field_log (struct db_field_log *pfl);
|
||||
#endif
|
||||
|
||||
#endif /*INCLdbEventh*/
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ typedef struct notifyPvt {
|
||||
ELLNODE node; /*For free list*/
|
||||
long magic;
|
||||
short state;
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
ELLLIST waitList; /*list of records for current processNotify*/
|
||||
short cancelWait;
|
||||
short userCallbackWait;
|
||||
@@ -93,7 +93,7 @@ static void notifyCleanup(processNotify *ppn);
|
||||
static void restartCheck(processNotifyRecord *ppnr);
|
||||
static void callDone(dbCommon *precord,processNotify *ppn);
|
||||
static void processNotifyCommon(processNotify *ppn,dbCommon *precord);
|
||||
static void notifyCallback(CALLBACK *pcallback);
|
||||
static void notifyCallback(epicsCallback *pcallback);
|
||||
|
||||
#define ellSafeAdd(list,listnode) \
|
||||
{ \
|
||||
@@ -265,7 +265,7 @@ static void processNotifyCommon(processNotify *ppn,dbCommon *precord)
|
||||
callDone(precord, ppn);
|
||||
}
|
||||
|
||||
static void notifyCallback(CALLBACK *pcallback)
|
||||
static void notifyCallback(epicsCallback *pcallback)
|
||||
{
|
||||
processNotify *ppn = NULL;
|
||||
dbCommon *precord;
|
||||
|
||||
@@ -109,7 +109,7 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = {
|
||||
/* EVENT */
|
||||
|
||||
typedef struct event_list {
|
||||
CALLBACK callback[NUM_CALLBACK_PRIORITIES];
|
||||
epicsCallback callback[NUM_CALLBACK_PRIORITIES];
|
||||
scan_list scan_list[NUM_CALLBACK_PRIORITIES];
|
||||
struct event_list *next;
|
||||
char eventname[1]; /* actually arbitrary size */
|
||||
@@ -120,7 +120,7 @@ static epicsMutexId event_lock;
|
||||
/* IO_EVENT*/
|
||||
|
||||
typedef struct io_scan_list {
|
||||
CALLBACK callback;
|
||||
epicsCallback callback;
|
||||
scan_list scan_list;
|
||||
} io_scan_list;
|
||||
|
||||
@@ -141,9 +141,9 @@ static void periodicTask(void *arg);
|
||||
static void initPeriodic(void);
|
||||
static void deletePeriodic(void);
|
||||
static void spawnPeriodic(int ind);
|
||||
static void eventCallback(CALLBACK *pcallback);
|
||||
static void eventCallback(epicsCallback *pcallback);
|
||||
static void ioscanInit(void);
|
||||
static void ioscanCallback(CALLBACK *pcallback);
|
||||
static void ioscanCallback(epicsCallback *pcallback);
|
||||
static void ioscanDestroy(void);
|
||||
static void printList(scan_list *psl, char *message);
|
||||
static void scanList(scan_list *psl);
|
||||
@@ -448,7 +448,7 @@ int scanpiol(void) /* print pioscan_list */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void eventCallback(CALLBACK *pcallback)
|
||||
static void eventCallback(epicsCallback *pcallback)
|
||||
{
|
||||
scan_list *psl;
|
||||
|
||||
@@ -863,7 +863,7 @@ static void spawnPeriodic(int ind)
|
||||
epicsEventWait(startStopEvent);
|
||||
}
|
||||
|
||||
static void ioscanCallback(CALLBACK *pcallback)
|
||||
static void ioscanCallback(epicsCallback *pcallback)
|
||||
{
|
||||
ioscan_head *piosh = (ioscan_head *) pcallback->user;
|
||||
int prio = pcallback->priority;
|
||||
|
||||
@@ -54,7 +54,7 @@ typedef struct msgBuff TAB_BUFFER;
|
||||
# define MIN(x,y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
# define MAX(x,y) (((x) < (y)) ? (x) : (y))
|
||||
# define MAX(x,y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
/* Local Routines */
|
||||
|
||||
@@ -7,6 +7,17 @@
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuAlarmStat
|
||||
|
||||
This menu defines the possible alarm statuses that EPICS records can exhibit
|
||||
which is used for C<STAT> and C<NSTA> fields of all record types.
|
||||
See L<Alarm Status> for more information.
|
||||
|
||||
=menu menuAlarmStat
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuAlarmStat) {
|
||||
choice(menuAlarmStatNO_ALARM,"NO_ALARM")
|
||||
choice(menuAlarmStatREAD,"READ")
|
||||
@@ -7,6 +7,15 @@
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuFtype
|
||||
|
||||
This menu is used for the C<FTVL> and similar fields of many record types.
|
||||
|
||||
=menu menuFtype
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuFtype) {
|
||||
choice(menuFtypeSTRING,"STRING")
|
||||
choice(menuFtypeCHAR,"CHAR")
|
||||
@@ -3,10 +3,19 @@
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuIvoa
|
||||
|
||||
This menu specifies the possibile actions to take when the INVALID alarm is
|
||||
triggered. See individual record types for more information.
|
||||
|
||||
=menu menuIvoa
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuIvoa) {
|
||||
choice(menuIvoaContinue_normally,"Continue normally")
|
||||
choice(menuIvoaDon_t_drive_outputs,"Don't drive outputs")
|
||||
@@ -1,13 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
menu(menuOmsl) {
|
||||
choice(menuOmslsupervisory,"supervisory")
|
||||
choice(menuOmslclosed_loop,"closed_loop")
|
||||
}
|
||||
@@ -6,19 +6,20 @@
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(state) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_STRING) {
|
||||
prompt("Value")
|
||||
promptgroup("40 - Input")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
size(20)
|
||||
}
|
||||
field(OVAL,DBF_STRING) {
|
||||
prompt("Prev Value")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
size(20)
|
||||
}
|
||||
|
||||
=head1 Menu menuOmsl
|
||||
|
||||
This menu is used for the C<OMSL> field of many output record types. It controls
|
||||
whether the record will fetch an input value from its C<DOL> input link when
|
||||
processed, which is useful when it is part of a closed loop control algorithm.
|
||||
The C<supervisory> state means the input link will not be used, C<closed_loop>
|
||||
enables the input link.
|
||||
|
||||
=menu menuOmsl
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuOmsl) {
|
||||
choice(menuOmslsupervisory,"supervisory")
|
||||
choice(menuOmslclosed_loop,"closed_loop")
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
menu(menuYesNo) {
|
||||
choice(menuYesNoNO,"NO")
|
||||
choice(menuYesNoYES,"YES")
|
||||
}
|
||||
29
src/ioc/db/menuYesNo.dbd.pod
Normal file
29
src/ioc/db/menuYesNo.dbd.pod
Normal file
@@ -0,0 +1,29 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuYesNo
|
||||
|
||||
This menu is used by many record types to specify simple C<NO> or C<YES>
|
||||
options for record-specific purposes.
|
||||
|
||||
Note that no other values for a field that uses menuYesNo are possible, e.g.
|
||||
C<MAYBE> or C<NO WAY> would not be accepted as choices for the field.
|
||||
Also, the choices C<yes>, C<No>, and C<Yes> are not valid choices since they
|
||||
don't match the case of C<NO> or C<YES>.
|
||||
The integer values C<0> and C<1> may often be used instead however, they are
|
||||
used as an index into the choices so C<0> becomes C<NO> and C<1> becomes <YES>.
|
||||
|
||||
=menu menuYesNo
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuYesNo) {
|
||||
choice(menuYesNoNO,"NO")
|
||||
choice(menuYesNoYES,"YES")
|
||||
}
|
||||
@@ -44,8 +44,8 @@
|
||||
#define TEST_DELAY(i) ((i / NUM_CALLBACK_PRIORITIES) * DELAY_QUANTUM)
|
||||
|
||||
typedef struct myPvt {
|
||||
CALLBACK cb1;
|
||||
CALLBACK cb2;
|
||||
epicsCallback cb1;
|
||||
epicsCallback cb2;
|
||||
epicsTimeStamp pass1Time;
|
||||
epicsTimeStamp pass2Time;
|
||||
double delay;
|
||||
@@ -55,7 +55,7 @@ typedef struct myPvt {
|
||||
|
||||
epicsEventId finished;
|
||||
|
||||
static void myCallback(CALLBACK *pCallback)
|
||||
static void myCallback(epicsCallback *pCallback)
|
||||
{
|
||||
myPvt *pmyPvt;
|
||||
|
||||
@@ -74,7 +74,7 @@ static void myCallback(CALLBACK *pCallback)
|
||||
}
|
||||
}
|
||||
|
||||
static void finalCallback(CALLBACK *pCallback)
|
||||
static void finalCallback(epicsCallback *pCallback)
|
||||
{
|
||||
myCallback(pCallback);
|
||||
epicsEventSignal(finished);
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
#define TEST_DELAY(i) ((i / NUM_CALLBACK_PRIORITIES) * DELAY_QUANTUM)
|
||||
|
||||
typedef struct myPvt {
|
||||
CALLBACK cb1;
|
||||
CALLBACK cb2;
|
||||
epicsCallback cb1;
|
||||
epicsCallback cb2;
|
||||
epicsTimeStamp pass1Time;
|
||||
epicsTimeStamp pass2Time;
|
||||
double delay;
|
||||
@@ -56,7 +56,7 @@ typedef struct myPvt {
|
||||
epicsEventId finished;
|
||||
|
||||
|
||||
static void myCallback(CALLBACK *pCallback)
|
||||
static void myCallback(epicsCallback *pCallback)
|
||||
{
|
||||
myPvt *pmyPvt;
|
||||
|
||||
@@ -75,7 +75,7 @@ static void myCallback(CALLBACK *pCallback)
|
||||
}
|
||||
}
|
||||
|
||||
static void finalCallback(CALLBACK *pCallback)
|
||||
static void finalCallback(epicsCallback *pCallback)
|
||||
{
|
||||
myCallback(pCallback);
|
||||
epicsEventSignal(finished);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "epicsExport.h"
|
||||
#include "link.h"
|
||||
#include "special.h"
|
||||
#include "iocInit.h"
|
||||
|
||||
|
||||
|
||||
@@ -215,6 +216,9 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
|
||||
char *penv;
|
||||
char **macPairs;
|
||||
|
||||
if(getIocState() != iocVoid)
|
||||
return -2;
|
||||
|
||||
if(*ppdbbase == 0) *ppdbbase = dbAllocBase();
|
||||
pdbbase = *ppdbbase;
|
||||
if(path && strlen(path)>0) {
|
||||
@@ -428,6 +432,10 @@ static void dbMenuHead(char *name)
|
||||
dbMenu *pdbMenu;
|
||||
GPHENTRY *pgphentry;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbMenuHead: Menu name can't be empty");
|
||||
return;
|
||||
}
|
||||
pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->menuList);
|
||||
if(pgphentry) {
|
||||
duplicate = TRUE;
|
||||
@@ -441,6 +449,10 @@ static void dbMenuHead(char *name)
|
||||
|
||||
static void dbMenuChoice(char *name,char *value)
|
||||
{
|
||||
if (!*name) {
|
||||
yyerror("dbMenuChoice: Menu choice name can't be empty");
|
||||
return;
|
||||
}
|
||||
if(duplicate) return;
|
||||
allocTemp(epicsStrDup(name));
|
||||
allocTemp(epicsStrDup(value));
|
||||
@@ -488,6 +500,10 @@ static void dbRecordtypeHead(char *name)
|
||||
dbRecordType *pdbRecordType;
|
||||
GPHENTRY *pgphentry;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbRecordtypeHead: Recordtype name can't be empty");
|
||||
return;
|
||||
}
|
||||
pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->recordTypeList);
|
||||
if(pgphentry) {
|
||||
duplicate = TRUE;
|
||||
@@ -505,7 +521,11 @@ static void dbRecordtypeFieldHead(char *name,char *type)
|
||||
{
|
||||
dbFldDes *pdbFldDes;
|
||||
int i;
|
||||
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbRecordtypeFieldHead: Field name can't be empty");
|
||||
return;
|
||||
}
|
||||
if(duplicate) return;
|
||||
pdbFldDes = dbCalloc(1,sizeof(dbFldDes));
|
||||
allocTemp(pdbFldDes);
|
||||
@@ -572,7 +592,7 @@ static void dbRecordtypeFieldItem(char *name,char *value)
|
||||
if(sscanf(value,"%hd",&pdbFldDes->special)==1) {
|
||||
return;
|
||||
}
|
||||
yyerror("Illegal special value.");
|
||||
yyerror("Illegal 'special' value.");
|
||||
return;
|
||||
}
|
||||
if(strcmp(name,"pp")==0) {
|
||||
@@ -581,13 +601,13 @@ static void dbRecordtypeFieldItem(char *name,char *value)
|
||||
} else if((strcmp(value,"NO")==0) || (strcmp(value,"FALSE")==0)) {
|
||||
pdbFldDes->process_passive = FALSE;
|
||||
} else {
|
||||
yyerror("Illegal value. Must be NO or YES");
|
||||
yyerror("Illegal 'pp' value, must be YES/NO/TRUE/FALSE");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(strcmp(name,"interest")==0) {
|
||||
if(sscanf(value,"%hd",&pdbFldDes->interest)!=1)
|
||||
yyerror("Illegal value. Must be integer");
|
||||
yyerror("Illegal 'interest' value, must be integer");
|
||||
return;
|
||||
}
|
||||
if(strcmp(name,"base")==0) {
|
||||
@@ -596,13 +616,13 @@ static void dbRecordtypeFieldItem(char *name,char *value)
|
||||
} else if(strcmp(value,"HEX")==0) {
|
||||
pdbFldDes->base = CT_HEX;
|
||||
} else {
|
||||
yyerror("Illegal value. Must be CT_DECIMAL or CT_HEX");
|
||||
yyerror("Illegal 'base' value, must be DECIMAL/HEX");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(strcmp(name,"size")==0) {
|
||||
if(sscanf(value,"%hd",&pdbFldDes->size)!=1)
|
||||
yyerror("Illegal value. Must be integer");
|
||||
yyerror("Illegal 'size' value, must be integer");
|
||||
return;
|
||||
}
|
||||
if(strcmp(name,"extra")==0) {
|
||||
@@ -794,6 +814,10 @@ static void dbDriver(char *name)
|
||||
drvSup *pdrvSup;
|
||||
GPHENTRY *pgphentry;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbDriver: Driver name can't be empty");
|
||||
return;
|
||||
}
|
||||
pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->drvList);
|
||||
if(pgphentry) {
|
||||
return;
|
||||
@@ -813,6 +837,10 @@ static void dbRegistrar(char *name)
|
||||
dbText *ptext;
|
||||
GPHENTRY *pgphentry;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbRegistrar: Registrar name can't be empty");
|
||||
return;
|
||||
}
|
||||
pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->registrarList);
|
||||
if(pgphentry) {
|
||||
return;
|
||||
@@ -832,6 +860,10 @@ static void dbFunction(char *name)
|
||||
dbText *ptext;
|
||||
GPHENTRY *pgphentry;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbFunction: Function name can't be empty");
|
||||
return;
|
||||
}
|
||||
pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->functionList);
|
||||
if(pgphentry) {
|
||||
return;
|
||||
@@ -851,6 +883,10 @@ static void dbVariable(char *name, char *type)
|
||||
dbVariableDef *pvar;
|
||||
GPHENTRY *pgphentry;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbVariable: Variable name can't be empty");
|
||||
return;
|
||||
}
|
||||
pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->variableList);
|
||||
if(pgphentry) {
|
||||
return;
|
||||
@@ -871,6 +907,10 @@ static void dbBreakHead(char *name)
|
||||
brkTable *pbrkTable;
|
||||
GPHENTRY *pgphentry;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbBreakHead: Breaktable name can't be empty");
|
||||
return;
|
||||
}
|
||||
pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->bptList);
|
||||
if(pgphentry) {
|
||||
duplicate = TRUE;
|
||||
@@ -973,6 +1013,10 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
DBENTRY *pdbentry;
|
||||
long status;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbRecordHead: Record name can't be empty");
|
||||
return;
|
||||
}
|
||||
badch = strpbrk(name, " \"'.$");
|
||||
if (badch) {
|
||||
epicsPrintf("Bad character '%c' in record name \"%s\"\n",
|
||||
@@ -1072,6 +1116,10 @@ static void dbRecordInfo(char *name, char *value)
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbRecordInfo: Info item name can't be empty");
|
||||
return;
|
||||
}
|
||||
if (duplicate) return;
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbentry = ptempListNode->item;
|
||||
@@ -1091,6 +1139,10 @@ static void dbRecordAlias(char *name)
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
|
||||
if (!*name) {
|
||||
yyerrorAbort("dbRecordAlias: Alias name can't be empty");
|
||||
return;
|
||||
}
|
||||
if (duplicate) return;
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbentry = ptempListNode->item;
|
||||
@@ -1108,6 +1160,10 @@ static void dbAlias(char *name, char *alias)
|
||||
DBENTRY dbEntry;
|
||||
DBENTRY *pdbEntry = &dbEntry;
|
||||
|
||||
if (!*alias) {
|
||||
yyerrorAbort("dbAlias: Alias name can't be empty");
|
||||
return;
|
||||
}
|
||||
dbInitEntry(pdbbase, pdbEntry);
|
||||
if (dbFindRecord(pdbEntry, name)) {
|
||||
epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n",
|
||||
|
||||
@@ -13,7 +13,7 @@ SRC_DIRS += $(IOCDIR)/dbtemplate
|
||||
|
||||
PROD_HOST += msi
|
||||
|
||||
msi_SRCS = msi.c
|
||||
msi_SRCS = msi.cpp
|
||||
msi_LIBS += Com
|
||||
HTMLS += msi.html
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
/* msi - macro substitutions and include */
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
@@ -18,7 +21,6 @@
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <macLib.h>
|
||||
#include <ellLib.h>
|
||||
#include <errlog.h>
|
||||
#include <epicsString.h>
|
||||
#include <osiFileName.h>
|
||||
@@ -56,32 +58,35 @@ int din = 0;
|
||||
typedef struct inputData inputData;
|
||||
|
||||
static void inputConstruct(inputData **ppvt);
|
||||
static void inputDestruct(inputData *pvt);
|
||||
static void inputAddPath(inputData *pvt, char *pval);
|
||||
static void inputBegin(inputData *pvt, char *fileName);
|
||||
static char *inputNextLine(inputData *pvt);
|
||||
static void inputNewIncludeFile(inputData *pvt, char *name);
|
||||
static void inputErrPrint(inputData *pvt);
|
||||
static void inputDestruct(inputData * const pvt);
|
||||
static void inputAddPath(inputData * const pvt, const char * const pval);
|
||||
static void inputBegin(inputData * const pvt, const char * const fileName);
|
||||
static char *inputNextLine(inputData * const pvt);
|
||||
static void inputNewIncludeFile(inputData * const pvt, const char * const name);
|
||||
static void inputErrPrint(const inputData * const pvt);
|
||||
|
||||
/* Module to read the substitution file */
|
||||
typedef struct subInfo subInfo;
|
||||
|
||||
static void substituteOpen(subInfo **ppvt, char *substitutionName);
|
||||
static void substituteDestruct(subInfo *pvt);
|
||||
static int substituteGetNextSet(subInfo *pvt, char **filename);
|
||||
static int substituteGetGlobalSet(subInfo *pvt);
|
||||
static char *substituteGetReplacements(subInfo *pvt);
|
||||
static char *substituteGetGlobalReplacements(subInfo *pvt);
|
||||
static void substituteOpen(subInfo **ppvt, const std::string& substitutionName);
|
||||
static void substituteDestruct(subInfo * const pvt);
|
||||
static bool substituteGetNextSet(subInfo * const pvt, char **filename);
|
||||
static bool substituteGetGlobalSet(subInfo * const pvt);
|
||||
static const char *substituteGetReplacements(subInfo * const pvt);
|
||||
static const char *substituteGetGlobalReplacements(subInfo * const pvt);
|
||||
|
||||
/* Forward references to local routines */
|
||||
static void usageExit(int status);
|
||||
static void abortExit(int status);
|
||||
static void addMacroReplacements(MAC_HANDLE *macPvt, char *pval);
|
||||
static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *templateName);
|
||||
static void usageExit(const int status);
|
||||
static void abortExit(const int status);
|
||||
static void addMacroReplacements(MAC_HANDLE * const macPvt,
|
||||
const char * const pval);
|
||||
static void makeSubstitutions(inputData * const inputPvt,
|
||||
MAC_HANDLE * const macPvt,
|
||||
const char * const templateName);
|
||||
|
||||
/*Global variables */
|
||||
static int opt_V = 0;
|
||||
static int opt_D = 0;
|
||||
static bool opt_D = false;
|
||||
|
||||
static char *outFile = 0;
|
||||
static int numDeps = 0, depHashes[MAX_DEPS];
|
||||
@@ -92,23 +97,21 @@ int main(int argc,char **argv)
|
||||
inputData *inputPvt;
|
||||
MAC_HANDLE *macPvt;
|
||||
char *pval;
|
||||
int narg;
|
||||
char *substitutionName = 0;
|
||||
std::string substitutionName;
|
||||
char *templateName = 0;
|
||||
int i;
|
||||
int localScope = 1;
|
||||
bool localScope = true;
|
||||
|
||||
inputConstruct(&inputPvt);
|
||||
macCreateHandle(&macPvt, 0);
|
||||
while ((argc > 1) && (argv[1][0] == '-')) {
|
||||
narg = (strlen(argv[1]) == 2) ? 2 : 1;
|
||||
int narg = (strlen(argv[1]) == 2) ? 2 : 1;
|
||||
pval = (narg == 1) ? (argv[1] + 2) : argv[2];
|
||||
|
||||
if (strncmp(argv[1], "-I", 2) == 0) {
|
||||
inputAddPath(inputPvt, pval);
|
||||
}
|
||||
else if (strcmp(argv[1], "-D") == 0) {
|
||||
opt_D = 1;
|
||||
opt_D = true;
|
||||
narg = 1; /* no argument for this option */
|
||||
}
|
||||
else if(strncmp(argv[1], "-o", 2) == 0) {
|
||||
@@ -118,14 +121,14 @@ int main(int argc,char **argv)
|
||||
addMacroReplacements(macPvt, pval);
|
||||
}
|
||||
else if(strncmp(argv[1], "-S", 2) == 0) {
|
||||
substitutionName = epicsStrDup(pval);
|
||||
substitutionName = pval;
|
||||
}
|
||||
else if (strcmp(argv[1], "-V") == 0) {
|
||||
opt_V = 1;
|
||||
narg = 1; /* no argument for this option */
|
||||
}
|
||||
else if (strcmp(argv[1], "-g") == 0) {
|
||||
localScope = 0;
|
||||
localScope = false;
|
||||
narg = 1; /* no argument for this option */
|
||||
}
|
||||
else if (strcmp(argv[1], "-h") == 0) {
|
||||
@@ -137,7 +140,7 @@ int main(int argc,char **argv)
|
||||
}
|
||||
|
||||
argc -= narg;
|
||||
for (i = 1; i < argc; i++)
|
||||
for (int i = 1; i < argc; i++)
|
||||
argv[i] = argv[i + narg];
|
||||
}
|
||||
|
||||
@@ -165,24 +168,24 @@ int main(int argc,char **argv)
|
||||
if (argc == 2)
|
||||
templateName = epicsStrDup(argv[1]);
|
||||
|
||||
if (!substitutionName) {
|
||||
if (substitutionName.empty()) {
|
||||
STEP("Single template+substitutions file");
|
||||
makeSubstitutions(inputPvt, macPvt, templateName);
|
||||
}
|
||||
else {
|
||||
subInfo *substitutePvt;
|
||||
char *filename = 0;
|
||||
int isGlobal, isFile;
|
||||
bool isGlobal, isFile;
|
||||
|
||||
STEPS("Substitutions from file", substitutionName);
|
||||
STEPS("Substitutions from file", substitutionName.c_str());
|
||||
substituteOpen(&substitutePvt, substitutionName);
|
||||
do {
|
||||
isGlobal = substituteGetGlobalSet(substitutePvt);
|
||||
if (isGlobal) {
|
||||
STEP("Handling global macros");
|
||||
pval = substituteGetGlobalReplacements(substitutePvt);
|
||||
if (pval)
|
||||
addMacroReplacements(macPvt, pval);
|
||||
const char *macStr = substituteGetGlobalReplacements(substitutePvt);
|
||||
if (macStr)
|
||||
addMacroReplacements(macPvt, macStr);
|
||||
}
|
||||
else if ((isFile = substituteGetNextSet(substitutePvt, &filename))) {
|
||||
if (templateName)
|
||||
@@ -193,11 +196,12 @@ int main(int argc,char **argv)
|
||||
}
|
||||
|
||||
STEPS("Handling template file", filename);
|
||||
while ((pval = substituteGetReplacements(substitutePvt))) {
|
||||
const char *macStr;
|
||||
while ((macStr = substituteGetReplacements(substitutePvt))) {
|
||||
if (localScope)
|
||||
macPushScope(macPvt);
|
||||
|
||||
addMacroReplacements(macPvt, pval);
|
||||
addMacroReplacements(macPvt, macStr);
|
||||
makeSubstitutions(inputPvt, macPvt, filename);
|
||||
|
||||
if (localScope)
|
||||
@@ -207,18 +211,18 @@ int main(int argc,char **argv)
|
||||
} while (isGlobal || isFile);
|
||||
substituteDestruct(substitutePvt);
|
||||
}
|
||||
errlogFlush();
|
||||
macDeleteHandle(macPvt);
|
||||
errlogFlush(); // macLib calls errlogPrintf()
|
||||
inputDestruct(inputPvt);
|
||||
if (opt_D) {
|
||||
printf("\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
free(templateName);
|
||||
free(substitutionName);
|
||||
return opt_V & 2;
|
||||
}
|
||||
|
||||
void usageExit(int status)
|
||||
void usageExit(const int status)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: msi [options] [template]\n"
|
||||
@@ -236,7 +240,7 @@ void usageExit(int status)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
void abortExit(int status)
|
||||
void abortExit(const int status)
|
||||
{
|
||||
if (outFile) {
|
||||
fclose(stdout);
|
||||
@@ -245,7 +249,8 @@ void abortExit(int status)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static void addMacroReplacements(MAC_HANDLE *macPvt, char *pval)
|
||||
static void addMacroReplacements(MAC_HANDLE * const macPvt,
|
||||
const char * const pval)
|
||||
{
|
||||
char **pairs;
|
||||
long status;
|
||||
@@ -268,7 +273,9 @@ static void addMacroReplacements(MAC_HANDLE *macPvt, char *pval)
|
||||
typedef enum {cmdInclude,cmdSubstitute} cmdType;
|
||||
static const char *cmdNames[] = {"include","substitute"};
|
||||
|
||||
static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *templateName)
|
||||
static void makeSubstitutions(inputData * const inputPvt,
|
||||
MAC_HANDLE * const macPvt,
|
||||
const char * const templateName)
|
||||
{
|
||||
char *input;
|
||||
static char buffer[MAX_BUFFER_SIZE];
|
||||
@@ -292,7 +299,6 @@ static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *tem
|
||||
if (command) {
|
||||
char *pstart;
|
||||
char *pend;
|
||||
char *copy;
|
||||
int cmdind=-1;
|
||||
int i;
|
||||
|
||||
@@ -325,16 +331,15 @@ static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *tem
|
||||
/*skip quote and any trailing blanks*/
|
||||
while (*++p == ' ') ;
|
||||
if (*p != '\n' && *p != 0) goto endcmd;
|
||||
copy = calloc(pend-pstart + 1, sizeof(char));
|
||||
strncpy(copy, pstart, pend-pstart);
|
||||
std::string copy = std::string(pstart, pend);
|
||||
|
||||
switch(cmdind) {
|
||||
case cmdInclude:
|
||||
inputNewIncludeFile(inputPvt,copy);
|
||||
inputNewIncludeFile(inputPvt, copy.c_str());
|
||||
break;
|
||||
|
||||
case cmdSubstitute:
|
||||
addMacroReplacements(macPvt,copy);
|
||||
addMacroReplacements(macPvt, copy.c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -342,7 +347,6 @@ static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *tem
|
||||
inputErrPrint(inputPvt);
|
||||
abortExit(1);
|
||||
}
|
||||
free(copy);
|
||||
expand = 0;
|
||||
}
|
||||
|
||||
@@ -361,94 +365,72 @@ endcmd:
|
||||
}
|
||||
|
||||
typedef struct inputFile {
|
||||
ELLNODE node;
|
||||
char *filename;
|
||||
std::string filename;
|
||||
FILE *fp;
|
||||
int lineNum;
|
||||
} inputFile;
|
||||
|
||||
typedef struct pathNode {
|
||||
ELLNODE node;
|
||||
char *directory;
|
||||
} pathNode;
|
||||
|
||||
struct inputData {
|
||||
ELLLIST inputFileList;
|
||||
ELLLIST pathList;
|
||||
std::list<inputFile> inputFileList;
|
||||
std::list<std::string> pathList;
|
||||
char inputBuffer[MAX_BUFFER_SIZE];
|
||||
inputData() { memset(inputBuffer, 0, sizeof(inputBuffer) * sizeof(inputBuffer[0])); };
|
||||
};
|
||||
|
||||
static void inputOpenFile(inputData *pinputData, char *filename);
|
||||
static void inputOpenFile(inputData *pinputData, const char * const filename);
|
||||
static void inputCloseFile(inputData *pinputData);
|
||||
static void inputCloseAllFiles(inputData *pinputData);
|
||||
|
||||
static void inputConstruct(inputData **ppvt)
|
||||
{
|
||||
inputData *pinputData;
|
||||
|
||||
pinputData = calloc(1, sizeof(inputData));
|
||||
ellInit(&pinputData->inputFileList);
|
||||
ellInit(&pinputData->pathList);
|
||||
*ppvt = pinputData;
|
||||
*ppvt = new inputData;
|
||||
}
|
||||
|
||||
static void inputDestruct(inputData *pinputData)
|
||||
static void inputDestruct(inputData * const pinputData)
|
||||
{
|
||||
pathNode *ppathNode;
|
||||
|
||||
inputCloseAllFiles(pinputData);
|
||||
while ((ppathNode = (pathNode *) ellFirst(&pinputData->pathList))) {
|
||||
ellDelete(&pinputData->pathList, &ppathNode->node);
|
||||
free(ppathNode->directory);
|
||||
free(ppathNode);
|
||||
}
|
||||
free(pinputData);
|
||||
delete(pinputData);
|
||||
}
|
||||
|
||||
static void inputAddPath(inputData *pinputData, char *path)
|
||||
static void inputAddPath(inputData * const pinputData, const char * const path)
|
||||
{
|
||||
ELLLIST *ppathList = &pinputData->pathList;
|
||||
pathNode *ppathNode;
|
||||
const char *pcolon;
|
||||
const char *pdir;
|
||||
size_t len;
|
||||
int emptyName;
|
||||
const char sep = *OSI_PATH_LIST_SEPARATOR;
|
||||
|
||||
ENTER;
|
||||
pdir = path;
|
||||
/*an empty name at beginning, middle, or end means current directory*/
|
||||
while (pdir && *pdir) {
|
||||
emptyName = ((*pdir == sep) ? 1 : 0);
|
||||
bool emptyName = (*pdir == sep);
|
||||
if (emptyName) ++pdir;
|
||||
|
||||
ppathNode = (pathNode *) calloc(1, sizeof(pathNode));
|
||||
ellAdd(ppathList, &ppathNode->node);
|
||||
|
||||
std::string directory;
|
||||
if (!emptyName) {
|
||||
pcolon = strchr(pdir, sep);
|
||||
len = (pcolon ? (pcolon - pdir) : strlen(pdir));
|
||||
if (len > 0) {
|
||||
ppathNode->directory = (char *) calloc(len + 1, sizeof(char));
|
||||
strncpy(ppathNode->directory, pdir, len);
|
||||
directory = std::string(pdir, len);
|
||||
pdir = pcolon;
|
||||
/*unless at end skip past first colon*/
|
||||
if (pdir && *(pdir + 1) != 0) ++pdir;
|
||||
}
|
||||
else { /*must have been trailing : */
|
||||
emptyName = 1;
|
||||
emptyName = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (emptyName) {
|
||||
ppathNode->directory = (char *) calloc(2, sizeof(char));
|
||||
strcpy(ppathNode->directory, ".");
|
||||
directory = ".";
|
||||
}
|
||||
|
||||
pinputData->pathList.push_back(directory);
|
||||
}
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputBegin(inputData *pinputData, char *fileName)
|
||||
static void inputBegin(inputData * const pinputData, const char * const fileName)
|
||||
{
|
||||
ENTER;
|
||||
inputCloseAllFiles(pinputData);
|
||||
@@ -456,16 +438,16 @@ static void inputBegin(inputData *pinputData, char *fileName)
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static char *inputNextLine(inputData *pinputData)
|
||||
static char *inputNextLine(inputData * const pinputData)
|
||||
{
|
||||
inputFile *pinputFile;
|
||||
char *pline;
|
||||
std::list<inputFile>& inFileList = pinputData->inputFileList;
|
||||
|
||||
ENTER;
|
||||
while ((pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList))) {
|
||||
pline = fgets(pinputData->inputBuffer, MAX_BUFFER_SIZE, pinputFile->fp);
|
||||
while (!inFileList.empty()) {
|
||||
inputFile& inFile = inFileList.front();
|
||||
char *pline = fgets(pinputData->inputBuffer, MAX_BUFFER_SIZE, inFile.fp);
|
||||
if (pline) {
|
||||
++pinputFile->lineNum;
|
||||
++inFile.lineNum;
|
||||
EXITS(pline);
|
||||
return pline;
|
||||
}
|
||||
@@ -475,32 +457,31 @@ static char *inputNextLine(inputData *pinputData)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void inputNewIncludeFile(inputData *pinputData, char *name)
|
||||
static void inputNewIncludeFile(inputData * const pinputData,
|
||||
const char * const name)
|
||||
{
|
||||
ENTER;
|
||||
inputOpenFile(pinputData,name);
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputErrPrint(inputData *pinputData)
|
||||
static void inputErrPrint(const inputData *const pinputData)
|
||||
{
|
||||
inputFile *pinputFile;
|
||||
|
||||
ENTER;
|
||||
fprintf(stderr, "input: '%s' at ", pinputData->inputBuffer);
|
||||
pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList);
|
||||
while (pinputFile) {
|
||||
fprintf(stderr, "line %d of ", pinputFile->lineNum);
|
||||
const std::list<inputFile>& inFileList = pinputData->inputFileList;
|
||||
std::list<inputFile>::const_iterator inFileIt = inFileList.begin();
|
||||
while (inFileIt != inFileList.end()) {
|
||||
fprintf(stderr, "line %d of ", inFileIt->lineNum);
|
||||
|
||||
if (pinputFile->filename) {
|
||||
fprintf(stderr, " file %s\n", pinputFile->filename);
|
||||
if (!inFileIt->filename.empty()) {
|
||||
fprintf(stderr, " file %s\n", inFileIt->filename.c_str());
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "stdin:\n");
|
||||
}
|
||||
|
||||
pinputFile = (inputFile *) ellNext(&pinputFile->node);
|
||||
if (pinputFile) {
|
||||
if (++inFileIt != inFileList.end()) {
|
||||
fprintf(stderr, " included from ");
|
||||
}
|
||||
else {
|
||||
@@ -511,12 +492,11 @@ static void inputErrPrint(inputData *pinputData)
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
static void inputOpenFile(inputData *pinputData, const char * const filename)
|
||||
{
|
||||
ELLLIST *ppathList = &pinputData->pathList;
|
||||
pathNode *ppathNode = 0;
|
||||
inputFile *pinputFile;
|
||||
char *fullname = 0;
|
||||
std::list<std::string>& pathList = pinputData->pathList;
|
||||
std::list<std::string>::iterator pathIt = pathList.end();
|
||||
std::string fullname;
|
||||
FILE *fp = 0;
|
||||
|
||||
ENTER;
|
||||
@@ -524,24 +504,19 @@ static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
STEP("Using stdin");
|
||||
fp = stdin;
|
||||
}
|
||||
else if ((ellCount(ppathList) == 0) || strchr(filename, '/')){
|
||||
else if (pathList.empty() || strchr(filename, '/')){
|
||||
STEPS("Opening ", filename);
|
||||
fp = fopen(filename, "r");
|
||||
}
|
||||
else {
|
||||
ppathNode = (pathNode *) ellFirst(ppathList);
|
||||
while (ppathNode) {
|
||||
fullname = calloc(strlen(filename) + strlen(ppathNode->directory) + 2,
|
||||
sizeof(char));
|
||||
strcpy(fullname, ppathNode->directory);
|
||||
strcat(fullname, "/");
|
||||
strcat(fullname, filename);
|
||||
pathIt = pathList.begin();
|
||||
while(pathIt != pathList.end()) {
|
||||
fullname = *pathIt + "/" + filename;
|
||||
STEPS("Trying", filename);
|
||||
fp = fopen(fullname, "r");
|
||||
fp = fopen(fullname.c_str(), "r");
|
||||
if (fp)
|
||||
break;
|
||||
free(fullname);
|
||||
ppathNode = (pathNode *) ellNext(&ppathNode->node);
|
||||
++pathIt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,20 +527,20 @@ static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
}
|
||||
|
||||
STEP("File opened");
|
||||
pinputFile = calloc(1, sizeof(inputFile));
|
||||
inputFile inFile = inputFile();
|
||||
|
||||
if (ppathNode) {
|
||||
pinputFile->filename = fullname;
|
||||
if (pathIt != pathList.end()) {
|
||||
inFile.filename = fullname;
|
||||
}
|
||||
else if (filename) {
|
||||
pinputFile->filename = epicsStrDup(filename);
|
||||
inFile.filename = filename;
|
||||
}
|
||||
else {
|
||||
pinputFile->filename = epicsStrDup("stdin");
|
||||
inFile.filename = "stdin";
|
||||
}
|
||||
|
||||
if (opt_D) {
|
||||
int hash = epicsStrHash(pinputFile->filename, 12345);
|
||||
int hash = epicsStrHash(inFile.filename.c_str(), 12345);
|
||||
int i = 0;
|
||||
int match = 0;
|
||||
|
||||
@@ -578,7 +553,7 @@ static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
if (!match) {
|
||||
const char *wrap = numDeps ? " \\\n" : "";
|
||||
|
||||
printf("%s %s", wrap, pinputFile->filename);
|
||||
printf("%s %s", wrap, inFile.filename.c_str());
|
||||
if (numDeps < MAX_DEPS) {
|
||||
depHashes[numDeps++] = hash;
|
||||
}
|
||||
@@ -589,33 +564,29 @@ static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
pinputFile->fp = fp;
|
||||
ellInsert(&pinputData->inputFileList, 0, &pinputFile->node);
|
||||
inFile.fp = fp;
|
||||
pinputData->inputFileList.push_front(inFile);
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputCloseFile(inputData *pinputData)
|
||||
{
|
||||
inputFile *pinputFile;
|
||||
|
||||
std::list<inputFile>& inFileList = pinputData->inputFileList;
|
||||
ENTER;
|
||||
pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList);
|
||||
if (pinputFile) {
|
||||
ellDelete(&pinputData->inputFileList, &pinputFile->node);
|
||||
if (fclose(pinputFile->fp))
|
||||
fprintf(stderr, "msi: Can't close input file '%s'\n", pinputFile->filename);
|
||||
free(pinputFile->filename);
|
||||
free(pinputFile);
|
||||
if(!inFileList.empty()) {
|
||||
inputFile& inFile = inFileList.front();
|
||||
if (fclose(inFile.fp))
|
||||
fprintf(stderr, "msi: Can't close input file '%s'\n", inFile.filename.c_str());
|
||||
inFileList.erase(inFileList.begin());
|
||||
}
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputCloseAllFiles(inputData *pinputData)
|
||||
{
|
||||
inputFile *pinputFile;
|
||||
|
||||
ENTER;
|
||||
while ((pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList))) {
|
||||
const std::list<inputFile>& inFileList = pinputData->inputFileList;
|
||||
while(!inFileList.empty()) {
|
||||
inputCloseFile(pinputData);
|
||||
}
|
||||
EXIT;
|
||||
@@ -627,7 +598,7 @@ typedef enum {
|
||||
} tokenType;
|
||||
|
||||
typedef struct subFile {
|
||||
char *substitutionName;
|
||||
std::string substitutionName;
|
||||
FILE *fp;
|
||||
int lineNum;
|
||||
char inputBuffer[MAX_BUFFER_SIZE];
|
||||
@@ -636,25 +607,20 @@ typedef struct subFile {
|
||||
char string[MAX_BUFFER_SIZE];
|
||||
} subFile;
|
||||
|
||||
typedef struct patternNode {
|
||||
ELLNODE node;
|
||||
char *var;
|
||||
} patternNode;
|
||||
|
||||
struct subInfo {
|
||||
subFile *psubFile;
|
||||
int isFile;
|
||||
bool isFile;
|
||||
char *filename;
|
||||
int isPattern;
|
||||
ELLLIST patternList;
|
||||
size_t size;
|
||||
size_t curLength;
|
||||
char *macroReplacements;
|
||||
bool isPattern;
|
||||
std::list<std::string> patternList;
|
||||
std::string macroReplacements;
|
||||
subInfo() : psubFile(NULL), isFile(false), filename(NULL),
|
||||
isPattern(false) {};
|
||||
};
|
||||
|
||||
static char *subGetNextLine(subFile *psubFile);
|
||||
static tokenType subGetNextToken(subFile *psubFile);
|
||||
static void subFileErrPrint(subFile *psubFile,char * message);
|
||||
static void subFileErrPrint(subFile *psubFile, const char * message);
|
||||
static void freeSubFile(subInfo *psubInfo);
|
||||
static void freePattern(subInfo *psubInfo);
|
||||
static void catMacroReplacements(subInfo *psubInfo,const char *value);
|
||||
@@ -668,7 +634,7 @@ void freeSubFile(subInfo *psubInfo)
|
||||
if (fclose(psubFile->fp))
|
||||
fprintf(stderr, "msi: Can't close substitution file\n");
|
||||
}
|
||||
free(psubFile);
|
||||
delete(psubFile);
|
||||
free(psubInfo->filename);
|
||||
psubInfo->psubFile = 0;
|
||||
EXIT;
|
||||
@@ -676,43 +642,36 @@ void freeSubFile(subInfo *psubInfo)
|
||||
|
||||
void freePattern(subInfo *psubInfo)
|
||||
{
|
||||
patternNode *ppatternNode;
|
||||
|
||||
ENTER;
|
||||
while ((ppatternNode = (patternNode *) ellFirst(&psubInfo->patternList))) {
|
||||
ellDelete(&psubInfo->patternList, &ppatternNode->node);
|
||||
free(ppatternNode->var);
|
||||
free(ppatternNode);
|
||||
}
|
||||
psubInfo->isPattern = 0;
|
||||
psubInfo->patternList.clear();
|
||||
psubInfo->isPattern = false;
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void substituteDestruct(subInfo *psubInfo)
|
||||
static void substituteDestruct(subInfo * const psubInfo)
|
||||
{
|
||||
ENTER;
|
||||
freeSubFile(psubInfo);
|
||||
freePattern(psubInfo);
|
||||
free(psubInfo);
|
||||
delete(psubInfo);
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void substituteOpen(subInfo **ppvt, char *substitutionName)
|
||||
static void substituteOpen(subInfo **ppvt, const std::string& substitutionName)
|
||||
{
|
||||
subInfo *psubInfo;
|
||||
subFile *psubFile;
|
||||
FILE *fp;
|
||||
|
||||
ENTER;
|
||||
psubInfo = calloc(1, sizeof(subInfo));
|
||||
psubInfo = new subInfo;
|
||||
*ppvt = psubInfo;
|
||||
psubFile = calloc(1, sizeof(subFile));
|
||||
psubFile = new subFile;
|
||||
psubInfo->psubFile = psubFile;
|
||||
ellInit(&psubInfo->patternList);
|
||||
|
||||
fp = fopen(substitutionName, "r");
|
||||
fp = fopen(substitutionName.c_str(), "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "msi: Can't open file '%s'\n", substitutionName);
|
||||
fprintf(stderr, "msi: Can't open file '%s'\n", substitutionName.c_str());
|
||||
abortExit(1);
|
||||
}
|
||||
|
||||
@@ -725,7 +684,7 @@ static void substituteOpen(subInfo **ppvt, char *substitutionName)
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static int substituteGetGlobalSet(subInfo *psubInfo)
|
||||
static bool substituteGetGlobalSet(subInfo * const psubInfo)
|
||||
{
|
||||
subFile *psubFile = psubInfo->psubFile;
|
||||
|
||||
@@ -737,17 +696,16 @@ static int substituteGetGlobalSet(subInfo *psubInfo)
|
||||
strcmp(psubFile->string, "global") == 0) {
|
||||
subGetNextToken(psubFile);
|
||||
EXITD(1);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
EXITD(0);
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
static bool substituteGetNextSet(subInfo * const psubInfo,char **filename)
|
||||
{
|
||||
subFile *psubFile = psubInfo->psubFile;
|
||||
patternNode *ppatternNode;
|
||||
|
||||
ENTER;
|
||||
*filename = 0;
|
||||
@@ -756,7 +714,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
|
||||
if (psubFile->token == tokenEOF) {
|
||||
EXITD(0);
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (psubFile->token == tokenString &&
|
||||
@@ -764,7 +722,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
size_t len;
|
||||
|
||||
STEP("Parsed 'file'");
|
||||
psubInfo->isFile = 1;
|
||||
psubInfo->isFile = true;
|
||||
if (subGetNextToken(psubFile) != tokenString) {
|
||||
subFileErrPrint(psubFile, "Parse error, expecting a filename");
|
||||
abortExit(1);
|
||||
@@ -799,7 +757,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
|
||||
if (psubFile->token == tokenLBrace) {
|
||||
EXITD(1);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (psubFile->token == tokenRBrace) {
|
||||
@@ -815,7 +773,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
|
||||
STEP("Parsed 'pattern'");
|
||||
freePattern(psubInfo);
|
||||
psubInfo->isPattern = 1;
|
||||
psubInfo->isPattern = true;
|
||||
|
||||
while (subGetNextToken(psubFile) == tokenSeparator);
|
||||
|
||||
@@ -825,15 +783,13 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
}
|
||||
STEP("Parsed '{'");
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
while (subGetNextToken(psubFile) == tokenSeparator);
|
||||
|
||||
if (psubFile->token != tokenString)
|
||||
break;
|
||||
|
||||
ppatternNode = calloc(1, sizeof(patternNode));
|
||||
ellAdd(&psubInfo->patternList, &ppatternNode->node);
|
||||
ppatternNode->var = epicsStrDup(psubFile->string);
|
||||
psubInfo->patternList.push_back(psubFile->string);
|
||||
}
|
||||
|
||||
if (psubFile->token != tokenRBrace) {
|
||||
@@ -843,23 +799,21 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
|
||||
subGetNextToken(psubFile);
|
||||
EXITD(1);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *substituteGetGlobalReplacements(subInfo *psubInfo)
|
||||
static const char *substituteGetGlobalReplacements(subInfo * const psubInfo)
|
||||
{
|
||||
subFile *psubFile = psubInfo->psubFile;
|
||||
|
||||
ENTER;
|
||||
if (psubInfo->macroReplacements)
|
||||
psubInfo->macroReplacements[0] = 0;
|
||||
psubInfo->curLength = 0;
|
||||
psubInfo->macroReplacements.clear();
|
||||
|
||||
while (psubFile->token == tokenSeparator)
|
||||
subGetNextToken(psubFile);
|
||||
|
||||
if (psubFile->token == tokenRBrace && psubInfo->isFile) {
|
||||
psubInfo->isFile = 0;
|
||||
psubInfo->isFile = false;
|
||||
free(psubInfo->filename);
|
||||
psubInfo->filename = 0;
|
||||
freePattern(psubInfo);
|
||||
@@ -877,12 +831,12 @@ static char *substituteGetGlobalReplacements(subInfo *psubInfo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
switch(subGetNextToken(psubFile)) {
|
||||
case tokenRBrace:
|
||||
subGetNextToken(psubFile);
|
||||
EXITS(psubInfo->macroReplacements);
|
||||
return psubInfo->macroReplacements;
|
||||
EXITS(psubInfo->macroReplacements.c_str());
|
||||
return psubInfo->macroReplacements.c_str();
|
||||
|
||||
case tokenSeparator:
|
||||
catMacroReplacements(psubInfo, ",");
|
||||
@@ -902,21 +856,18 @@ static char *substituteGetGlobalReplacements(subInfo *psubInfo)
|
||||
}
|
||||
}
|
||||
|
||||
static char *substituteGetReplacements(subInfo *psubInfo)
|
||||
static const char *substituteGetReplacements(subInfo * const psubInfo)
|
||||
{
|
||||
subFile *psubFile = psubInfo->psubFile;
|
||||
patternNode *ppatternNode;
|
||||
|
||||
ENTER;
|
||||
if (psubInfo->macroReplacements)
|
||||
psubInfo->macroReplacements[0] = 0;
|
||||
psubInfo->curLength = 0;
|
||||
psubInfo->macroReplacements.clear();
|
||||
|
||||
while (psubFile->token == tokenSeparator)
|
||||
subGetNextToken(psubFile);
|
||||
|
||||
if (psubFile->token==tokenRBrace && psubInfo->isFile) {
|
||||
psubInfo->isFile = 0;
|
||||
psubInfo->isFile = false;
|
||||
free(psubInfo->filename);
|
||||
psubInfo->filename = 0;
|
||||
freePattern(psubInfo);
|
||||
@@ -936,15 +887,16 @@ static char *substituteGetReplacements(subInfo *psubInfo)
|
||||
}
|
||||
|
||||
if (psubInfo->isPattern) {
|
||||
int gotFirstPattern = 0;
|
||||
bool gotFirstPattern = false;
|
||||
|
||||
while (subGetNextToken(psubFile) == tokenSeparator);
|
||||
ppatternNode = (patternNode *) ellFirst(&psubInfo->patternList);
|
||||
while (1) {
|
||||
std::list<std::string>& patternList = psubInfo->patternList;
|
||||
std::list<std::string>::iterator patternIt = patternList.begin();
|
||||
while (true) {
|
||||
if (psubFile->token == tokenRBrace) {
|
||||
subGetNextToken(psubFile);
|
||||
EXITS(psubInfo->macroReplacements);
|
||||
return psubInfo->macroReplacements;
|
||||
EXITS(psubInfo->macroReplacements.c_str());
|
||||
return psubInfo->macroReplacements.c_str();
|
||||
}
|
||||
|
||||
if (psubFile->token != tokenString) {
|
||||
@@ -954,13 +906,13 @@ static char *substituteGetReplacements(subInfo *psubInfo)
|
||||
|
||||
if (gotFirstPattern)
|
||||
catMacroReplacements(psubInfo, ",");
|
||||
gotFirstPattern = 1;
|
||||
gotFirstPattern = true;
|
||||
|
||||
if (ppatternNode) {
|
||||
catMacroReplacements(psubInfo, ppatternNode->var);
|
||||
if (patternIt != patternList.end()) {
|
||||
catMacroReplacements(psubInfo, patternIt->c_str());
|
||||
catMacroReplacements(psubInfo, "=");
|
||||
catMacroReplacements(psubInfo, psubFile->string);
|
||||
ppatternNode = (patternNode *) ellNext(&ppatternNode->node);
|
||||
++patternIt;
|
||||
}
|
||||
else {
|
||||
subFileErrPrint(psubFile, "Warning, too many values given");
|
||||
@@ -969,12 +921,12 @@ static char *substituteGetReplacements(subInfo *psubInfo)
|
||||
while (subGetNextToken(psubFile) == tokenSeparator);
|
||||
}
|
||||
}
|
||||
else while(1) {
|
||||
else while(true) {
|
||||
switch(subGetNextToken(psubFile)) {
|
||||
case tokenRBrace:
|
||||
subGetNextToken(psubFile);
|
||||
EXITS(psubInfo->macroReplacements);
|
||||
return psubInfo->macroReplacements;
|
||||
EXITS(psubInfo->macroReplacements.c_str());
|
||||
return psubInfo->macroReplacements.c_str();
|
||||
|
||||
case tokenSeparator:
|
||||
catMacroReplacements(psubInfo, ",");
|
||||
@@ -1017,11 +969,12 @@ static char *subGetNextLine(subFile *psubFile)
|
||||
return &psubFile->inputBuffer[0];
|
||||
}
|
||||
|
||||
static void subFileErrPrint(subFile *psubFile,char * message)
|
||||
static void subFileErrPrint(subFile *psubFile, const char * message)
|
||||
{
|
||||
fprintf(stderr, "msi: %s\n",message);
|
||||
fprintf(stderr, " in substitution file '%s' at line %d:\n %s",
|
||||
psubFile->substitutionName, psubFile->lineNum, psubFile->inputBuffer);
|
||||
psubFile->substitutionName.c_str(), psubFile->lineNum,
|
||||
psubFile->inputBuffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1107,32 +1060,8 @@ done:
|
||||
|
||||
static void catMacroReplacements(subInfo *psubInfo, const char *value)
|
||||
{
|
||||
size_t len = strlen(value);
|
||||
|
||||
ENTER;
|
||||
if (psubInfo->size <= (psubInfo->curLength + len)) {
|
||||
size_t newsize = psubInfo->size + MAX_BUFFER_SIZE;
|
||||
char *newbuf;
|
||||
|
||||
STEP("Enlarging buffer");
|
||||
if (newsize <= psubInfo->curLength + len)
|
||||
newsize = psubInfo->curLength + len + 1;
|
||||
newbuf = calloc(1, newsize);
|
||||
if (!newbuf) {
|
||||
fprintf(stderr, "calloc failed for size %lu\n",
|
||||
(unsigned long) newsize);
|
||||
abortExit(1);
|
||||
}
|
||||
if (psubInfo->macroReplacements) {
|
||||
memcpy(newbuf, psubInfo->macroReplacements, psubInfo->curLength);
|
||||
free(psubInfo->macroReplacements);
|
||||
}
|
||||
psubInfo->size = newsize;
|
||||
psubInfo->macroReplacements = newbuf;
|
||||
}
|
||||
|
||||
STEPS("Appending", value);
|
||||
strcat(psubInfo->macroReplacements, value);
|
||||
psubInfo->curLength += len;
|
||||
psubInfo->macroReplacements += value;
|
||||
EXIT;
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
use strict;
|
||||
use Test;
|
||||
|
||||
BEGIN {plan tests => 9}
|
||||
BEGIN {plan tests => 12}
|
||||
|
||||
# Check include/substitute command model
|
||||
ok(msi('-I .. ../t1-template.txt'), slurp('../t1-result.txt'));
|
||||
@@ -33,16 +33,9 @@ ok(msi('-S../t6-substitute.txt ../t6-template.txt'), slurp('../t6-result.txt'));
|
||||
|
||||
# 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.. -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('../t7-result.txt'));
|
||||
unlink $out;
|
||||
msi("-I.. -V -o $out ../t1-template.txt");
|
||||
ok(slurp($out), slurp('../t7-result.txt'));
|
||||
|
||||
# Dependency generation, include/substitute model
|
||||
ok(msi('-I.. -D -o t8.txt ../t1-template.txt'), slurp('../t8-result.txt'));
|
||||
@@ -50,6 +43,17 @@ ok(msi('-I.. -D -o t8.txt ../t1-template.txt'), slurp('../t8-result.txt'));
|
||||
# Dependency generation, dbLoadTemplate format
|
||||
ok(msi('-I.. -D -ot9.txt -S ../t2-substitution.txt'), slurp('../t9-result.txt'));
|
||||
|
||||
# Substitution file, variable format, with 0 variable definitions
|
||||
ok(msi('-I. -I.. -S ../t10-substitute.txt'), slurp('../t10-result.txt'));
|
||||
|
||||
# Substitution file, pattern format, with 0 pattern definitions
|
||||
ok(msi('-I. -I.. -S ../t11-substitute.txt'), slurp('../t11-result.txt'));
|
||||
|
||||
# Substitution file, environment variable macros in template filename
|
||||
my %envs = (TEST_NO => 12, PREFIX => 't');
|
||||
@ENV{ keys %envs } = values %envs;
|
||||
ok(msi('-I. -I.. -S ../t12-substitute.txt'), slurp('../t12-result.txt'));
|
||||
delete @ENV{ keys %envs }; # Not really needed
|
||||
|
||||
# Test support routines
|
||||
|
||||
@@ -63,21 +67,7 @@ sub slurp {
|
||||
|
||||
sub msi {
|
||||
my ($args) = @_;
|
||||
my $exe = ($^O eq 'MSWin32') || ($^O eq 'cygwin') ? '.exe' : '';
|
||||
my $msi = "./msi-copy$exe";
|
||||
my $result;
|
||||
if ($args =~ m/-o / && $args !~ m/-D/) {
|
||||
# An empty result is expected
|
||||
$result = `$msi $args`;
|
||||
}
|
||||
else {
|
||||
# Try up to 5 times, sometimes msi fails on Windows
|
||||
my $count = 5;
|
||||
do {
|
||||
$result = `$msi $args`;
|
||||
print "# result of '$msi $args' empty, retrying\n"
|
||||
if $result eq '';
|
||||
} while ($result eq '') && (--$count > 0);
|
||||
}
|
||||
return $result;
|
||||
my $nul = ($^O eq 'MSWin32') ? 'NUL' : '/dev/null';
|
||||
my $msi = ($^O eq 'MSWin32') ? 'msi-copy.exe' : './msi-copy';
|
||||
return `$msi $args 2>$nul`;
|
||||
}
|
||||
|
||||
4
src/ioc/dbtemplate/test/t10-result.txt
Normal file
4
src/ioc/dbtemplate/test/t10-result.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
# comment line
|
||||
a=gbl
|
||||
8
src/ioc/dbtemplate/test/t10-substitute.txt
Normal file
8
src/ioc/dbtemplate/test/t10-substitute.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
file t10-template.txt {
|
||||
{}
|
||||
}
|
||||
|
||||
global { a=gbl }
|
||||
file t10-template.txt {
|
||||
{}
|
||||
}
|
||||
2
src/ioc/dbtemplate/test/t10-template.txt
Normal file
2
src/ioc/dbtemplate/test/t10-template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
4
src/ioc/dbtemplate/test/t11-result.txt
Normal file
4
src/ioc/dbtemplate/test/t11-result.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
# comment line
|
||||
a=gbl
|
||||
10
src/ioc/dbtemplate/test/t11-substitute.txt
Normal file
10
src/ioc/dbtemplate/test/t11-substitute.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
file t11-template.txt {
|
||||
pattern {}
|
||||
{}
|
||||
}
|
||||
|
||||
global { a=gbl }
|
||||
file t11-template.txt {
|
||||
pattern {}
|
||||
{}
|
||||
}
|
||||
2
src/ioc/dbtemplate/test/t11-template.txt
Normal file
2
src/ioc/dbtemplate/test/t11-template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
2
src/ioc/dbtemplate/test/t12-result.txt
Normal file
2
src/ioc/dbtemplate/test/t12-result.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=foo
|
||||
3
src/ioc/dbtemplate/test/t12-substitute.txt
Normal file
3
src/ioc/dbtemplate/test/t12-substitute.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
file $(PREFIX)$(TEST_NO)-template.txt {
|
||||
{ a=foo }
|
||||
}
|
||||
2
src/ioc/dbtemplate/test/t12-template.txt
Normal file
2
src/ioc/dbtemplate/test/t12-template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
@@ -25,3 +25,6 @@ variable(callbackParallelThreadsDefault,int)
|
||||
|
||||
# Real-time operation
|
||||
variable(dbThreadRealtimeLock,int)
|
||||
|
||||
# show logClient network activity
|
||||
variable(logClientDebug,int)
|
||||
|
||||
@@ -70,9 +70,7 @@
|
||||
#include "registryRecordType.h"
|
||||
#include "rsrv.h"
|
||||
|
||||
static enum {
|
||||
iocVirgin, iocBuilding, iocBuilt, iocRunning, iocPaused, iocStopped
|
||||
} iocState = iocVirgin;
|
||||
static enum iocStateEnum iocState = iocVoid;
|
||||
static enum {
|
||||
buildRSRV, buildIsolated
|
||||
} iocBuildMode;
|
||||
@@ -91,6 +89,11 @@ static void exitDatabase(void *dummy);
|
||||
int dbThreadRealtimeLock = 1;
|
||||
epicsExportAddress(int, dbThreadRealtimeLock);
|
||||
|
||||
enum iocStateEnum getIocState(void)
|
||||
{
|
||||
return iocState;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize EPICS on the IOC.
|
||||
*/
|
||||
@@ -101,7 +104,7 @@ int iocInit(void)
|
||||
|
||||
static int iocBuild_1(void)
|
||||
{
|
||||
if (iocState != iocVirgin && iocState != iocStopped) {
|
||||
if (iocState != iocVoid) {
|
||||
errlogPrintf("iocBuild: IOC can only be initialized from uninitialized or stopped state\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -701,7 +704,7 @@ static void doFreeRecord(dbRecordType *pdbRecordType, dbCommon *precord,
|
||||
|
||||
int iocShutdown(void)
|
||||
{
|
||||
if (iocState == iocVirgin || iocState == iocStopped) return 0;
|
||||
if (iocState == iocVoid) return 0;
|
||||
iterateRecords(doCloseLinks, NULL);
|
||||
if (iocBuildMode==buildIsolated) {
|
||||
/* stop and "join" threads */
|
||||
@@ -720,7 +723,7 @@ int iocShutdown(void)
|
||||
dbProcessNotifyExit();
|
||||
iocshFree();
|
||||
}
|
||||
iocState = iocStopped;
|
||||
iocState = iocVoid;
|
||||
iocBuildMode = buildRSRV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,10 +13,15 @@
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
enum iocStateEnum {
|
||||
iocVoid, iocBuilding, iocBuilt, iocRunning, iocPaused
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
epicsShareFunc enum iocStateEnum getIocState(void);
|
||||
epicsShareFunc int iocInit(void);
|
||||
epicsShareFunc int iocBuild(void);
|
||||
epicsShareFunc int iocBuildIsolated(void);
|
||||
|
||||
@@ -66,17 +66,6 @@ static void req_server (void *pParm)
|
||||
|
||||
IOC_sock = conf->tcp;
|
||||
|
||||
/* listen and accept new connections */
|
||||
if ( listen ( IOC_sock, 20 ) < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf ( "CAS: Listen error: %s\n",
|
||||
sockErrBuf );
|
||||
epicsSocketDestroy (IOC_sock);
|
||||
epicsThreadSuspendSelf ();
|
||||
}
|
||||
|
||||
epicsEventSignal(castcp_startStopEvent);
|
||||
|
||||
while (TRUE) {
|
||||
@@ -194,7 +183,7 @@ SOCKET* rsrv_grab_tcp(unsigned short *port)
|
||||
|
||||
epicsSocketEnableAddressReuseDuringTimeWaitState ( tcpsock );
|
||||
|
||||
if(bind(tcpsock, &scratch.sa, sizeof(scratch))==0) {
|
||||
if(bind(tcpsock, &scratch.sa, sizeof(scratch))==0 && listen(tcpsock, 20)==0) {
|
||||
if(scratch.ia.sin_port==0) {
|
||||
/* use first socket to pick a random port */
|
||||
osiSocklen_t alen = sizeof(ifaceAddr);
|
||||
|
||||
@@ -581,25 +581,11 @@ Init (rtems_task_argument ignored)
|
||||
printf ("***** Can't set time: %s\n", rtems_status_text (sc));
|
||||
}
|
||||
if (getenv("TZ") == NULL) {
|
||||
const char *tzp = envGetConfigParamPtr(&EPICS_TIMEZONE);
|
||||
if (tzp == NULL) {
|
||||
printf("Warning -- no timezone information available -- times will be displayed as GMT.\n");
|
||||
}
|
||||
else {
|
||||
char tz[10];
|
||||
int minWest, toDst = 0, fromDst = 0;
|
||||
if(sscanf(tzp, "%9[^:]::%d:%d:%d", tz, &minWest, &toDst, &fromDst) < 2) {
|
||||
printf("Warning: EPICS_TIMEZONE (%s) unrecognizable -- times will be displayed as GMT.\n", tzp);
|
||||
}
|
||||
else {
|
||||
char posixTzBuf[40];
|
||||
char *p = posixTzBuf;
|
||||
p += sprintf(p, "%cST%d:%.2d", tz[0], minWest/60, minWest%60);
|
||||
if (toDst != fromDst)
|
||||
p += sprintf(p, "%cDT", tz[0]);
|
||||
epicsEnvSet("TZ", posixTzBuf);
|
||||
}
|
||||
}
|
||||
const char *tzp = envGetConfigParamPtr(&EPICS_TZ);
|
||||
if (!tzp || *tzp)
|
||||
printf("Warning: No timezone information, times will be displayed in UTC.\n");
|
||||
else
|
||||
epicsEnvSet("TZ", tzp);
|
||||
}
|
||||
tzset();
|
||||
osdTimeRegister();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "postfix.h"
|
||||
#include "postfixPvt.h"
|
||||
|
||||
|
||||
static double calcRandom(void);
|
||||
static int cond_search(const char **ppinst, int match);
|
||||
|
||||
@@ -48,7 +49,6 @@ epicsShareFunc long
|
||||
double *ptop; /* stack pointer */
|
||||
double top; /* value from top of stack */
|
||||
epicsInt32 itop; /* integer from top of stack */
|
||||
epicsUInt32 utop; /* unsigned integer from top of stack */
|
||||
int op;
|
||||
int nargs;
|
||||
|
||||
@@ -287,45 +287,60 @@ epicsShareFunc long
|
||||
*ptop = ! *ptop;
|
||||
break;
|
||||
|
||||
/* For bitwise operations on values with bit 31 set, double values
|
||||
* must first be cast to unsigned to correctly set that bit; the
|
||||
* double value must be negative in that case. The result must be
|
||||
* cast to a signed integer before converting to the double result.
|
||||
/* Be VERY careful converting double to int in case bit 31 is set!
|
||||
* Out-of-range errors give very different results on different sytems.
|
||||
* Convert negative doubles to signed and positive doubles to unsigned
|
||||
* first to avoid overflows if bit 32 is set.
|
||||
* The result is always signed, values with bit 31 set are negative
|
||||
* to avoid problems when writing the value to signed integer fields
|
||||
* like longout.VAL or ao.RVAL. However unsigned fields may give
|
||||
* problems on some architectures. (Fewer than giving problems with
|
||||
* signed integer. Maybe the conversion functions should handle
|
||||
* overflows better.)
|
||||
*/
|
||||
#define d2i(x) ((x)<0?(epicsInt32)(x):(epicsInt32)(epicsUInt32)(x))
|
||||
#define d2ui(x) ((x)<0?(epicsUInt32)(epicsInt32)(x):(epicsUInt32)(x))
|
||||
|
||||
case BIT_OR:
|
||||
utop = *ptop--;
|
||||
*ptop = (epicsInt32) ((epicsUInt32) *ptop | utop);
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) | d2i(top));
|
||||
break;
|
||||
|
||||
case BIT_AND:
|
||||
utop = *ptop--;
|
||||
*ptop = (epicsInt32) ((epicsUInt32) *ptop & utop);
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) & d2i(top));
|
||||
break;
|
||||
|
||||
case BIT_EXCL_OR:
|
||||
utop = *ptop--;
|
||||
*ptop = (epicsInt32) ((epicsUInt32) *ptop ^ utop);
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) ^ d2i(top));
|
||||
break;
|
||||
|
||||
case BIT_NOT:
|
||||
utop = *ptop;
|
||||
*ptop = (epicsInt32) ~utop;
|
||||
*ptop = (double)~d2i(*ptop);
|
||||
break;
|
||||
|
||||
/* The shift operators use signed integers, so a right-shift will
|
||||
* extend the sign bit into the left-hand end of the value. The
|
||||
* double-casting through unsigned here is important, see above.
|
||||
/* In C the shift operators decide on an arithmetic or logical shift
|
||||
* based on whether the integer is signed or unsigned.
|
||||
* With signed integers, a right-shift is arithmetic and will
|
||||
* extend the sign bit into the left-hand end of the value. When used
|
||||
* with unsigned values a logical shift is performed. The
|
||||
* double-casting through signed/unsigned here is important, see above.
|
||||
*/
|
||||
|
||||
case RIGHT_SHIFT:
|
||||
utop = *ptop--;
|
||||
*ptop = ((epicsInt32) (epicsUInt32) *ptop) >> (utop & 31);
|
||||
case RIGHT_SHIFT_ARITH:
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) >> (d2i(top) & 31));
|
||||
break;
|
||||
|
||||
case LEFT_SHIFT:
|
||||
utop = *ptop--;
|
||||
*ptop = ((epicsInt32) (epicsUInt32) *ptop) << (utop & 31);
|
||||
case LEFT_SHIFT_ARITH:
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) << (d2i(top) & 31));
|
||||
break;
|
||||
|
||||
case RIGHT_SHIFT_LOGIC:
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2ui(*ptop) >> (d2ui(top) & 31u));
|
||||
break;
|
||||
|
||||
case NOT_EQ:
|
||||
@@ -382,11 +397,11 @@ epicsShareFunc long
|
||||
*presult = *ptop;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW)
|
||||
# pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
|
||||
epicsShareFunc long
|
||||
calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
|
||||
{
|
||||
|
||||
@@ -148,13 +148,14 @@ static const ELEMENT operators[] = {
|
||||
{":=", 0, 0, -1, STORE_OPERATOR, STORE_A},
|
||||
{";", 0, 0, 0, EXPR_TERMINATOR,NOT_GENERATED},
|
||||
{"<", 3, 3, -1, BINARY_OPERATOR,LESS_THAN},
|
||||
{"<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT},
|
||||
{"<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT_ARITH},
|
||||
{"<=", 3, 3, -1, BINARY_OPERATOR,LESS_OR_EQ},
|
||||
{"=", 3, 3, -1, BINARY_OPERATOR,EQUAL},
|
||||
{"==", 3, 3, -1, BINARY_OPERATOR,EQUAL},
|
||||
{">", 3, 3, -1, BINARY_OPERATOR,GR_THAN},
|
||||
{">=", 3, 3, -1, BINARY_OPERATOR,GR_OR_EQ},
|
||||
{">>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT},
|
||||
{">>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT_ARITH},
|
||||
{">>>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT_LOGIC},
|
||||
{"?", 0, 0, -1, CONDITIONAL, COND_IF},
|
||||
{"AND", 2, 2, -1, BINARY_OPERATOR,BIT_AND},
|
||||
{"OR", 1, 1, -1, BINARY_OPERATOR,BIT_OR},
|
||||
@@ -579,8 +580,9 @@ epicsShareFunc void
|
||||
"BIT_AND",
|
||||
"BIT_EXCL_OR",
|
||||
"BIT_NOT",
|
||||
"RIGHT_SHIFT",
|
||||
"LEFT_SHIFT",
|
||||
"RIGHT_SHIFT_ARITH",
|
||||
"LEFT_SHIFT_ARITH",
|
||||
"RIGHT_SHIFT_LOGIC",
|
||||
/* Relationals */
|
||||
"NOT_EQ",
|
||||
"LESS_THAN",
|
||||
|
||||
@@ -84,8 +84,9 @@ typedef enum {
|
||||
BIT_AND,
|
||||
BIT_EXCL_OR,
|
||||
BIT_NOT,
|
||||
RIGHT_SHIFT,
|
||||
LEFT_SHIFT,
|
||||
RIGHT_SHIFT_ARITH,
|
||||
LEFT_SHIFT_ARITH,
|
||||
RIGHT_SHIFT_LOGIC,
|
||||
/* Relationals */
|
||||
NOT_EQ,
|
||||
LESS_THAN,
|
||||
|
||||
@@ -9,6 +9,5 @@
|
||||
|
||||
SRC_DIRS += $(LIBCOM)/cppStd
|
||||
INC += epicsAlgorithm.h
|
||||
INC += epicsExcept.h
|
||||
INC += epicsMemory.h
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
// Author: Andrew Johnson & Jeff Hill
|
||||
// Date: December 2000
|
||||
|
||||
#ifndef __EPICS_EXCEPT_H__
|
||||
#define __EPICS_EXCEPT_H__
|
||||
|
||||
#define epicsThrowHere(exc) \
|
||||
throw locationException(exc, __FILE__, __LINE__)
|
||||
|
||||
class sourceLocation {
|
||||
public: // Functions
|
||||
sourceLocation(const char *fileName, int lineNumber);
|
||||
// sourceLocation(const sourceLocation&); Copy constructable
|
||||
// sourceLocation& operator=(const sourceLocation&); Assignable
|
||||
|
||||
const char *fileName() const;
|
||||
int lineNumber() const;
|
||||
|
||||
private: // Hide compiler-generated member functions
|
||||
sourceLocation(); // default constructor
|
||||
|
||||
private: // Data
|
||||
const char *file;
|
||||
int line;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class locationException : public T, public sourceLocation {
|
||||
public:
|
||||
locationException(const T& exc, const char *fileName, int lineNumber);
|
||||
};
|
||||
|
||||
|
||||
/* Example:
|
||||
* if (status) epicsThrowHere(std::logic_error("operation failed!"));
|
||||
* try { ... } catch(sourceLocation& where) { ... }
|
||||
*/
|
||||
|
||||
// END OF DECLARATIONS
|
||||
|
||||
// INLINE FUNCTIONS
|
||||
|
||||
// sourceFileLocation
|
||||
inline sourceLocation::sourceLocation (const char *fileName, int lineNumber) :
|
||||
file(fileName), line(lineNumber) {}
|
||||
|
||||
inline const char* sourceLocation::fileName () const {
|
||||
return this->file;
|
||||
}
|
||||
|
||||
inline int sourceLocation::lineNumber () const {
|
||||
return this->line;
|
||||
}
|
||||
|
||||
// locationException<T>
|
||||
template <class T>
|
||||
inline locationException<T>::locationException
|
||||
(const char *fileName, int lineNumber, const E& exc) :
|
||||
T(exc), sourceLocation(fileName, lineNumber) {}
|
||||
|
||||
|
||||
#endif // __EPICS_EXCEPT_H__
|
||||
2
src/libCom/env/envDefs.h
vendored
2
src/libCom/env/envDefs.h
vendored
@@ -61,7 +61,7 @@ epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PORT;
|
||||
epicsShareExtern const ENV_PARAM EPICS_BUILD_COMPILER_CLASS;
|
||||
epicsShareExtern const ENV_PARAM EPICS_BUILD_OS_CLASS;
|
||||
epicsShareExtern const ENV_PARAM EPICS_BUILD_TARGET_ARCH;
|
||||
epicsShareExtern const ENV_PARAM EPICS_TIMEZONE;
|
||||
epicsShareExtern const ENV_PARAM EPICS_TZ;
|
||||
epicsShareExtern const ENV_PARAM EPICS_TS_NTP_INET;
|
||||
epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_PORT;
|
||||
epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_INET;
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "envDefs.h"
|
||||
#include "errlog.h"
|
||||
#include "logClient.h"
|
||||
#include "iocLog.h"
|
||||
#include "epicsExit.h"
|
||||
|
||||
int iocLogDisable = 0;
|
||||
|
||||
@@ -74,6 +76,24 @@ void epicsShareAPI epicsShareAPI iocLogFlush (void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* logClientSendMessage ()
|
||||
*/
|
||||
static void logClientSendMessage ( logClientId id, const char * message )
|
||||
{
|
||||
if ( !iocLogDisable ) {
|
||||
logClientSend (id, message);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* iocLogClientDestroy()
|
||||
*/
|
||||
static void iocLogClientDestroy (logClientId id)
|
||||
{
|
||||
errlogRemoveListeners (logClientSendMessage, id);
|
||||
}
|
||||
|
||||
/*
|
||||
* iocLogClientInit()
|
||||
*/
|
||||
@@ -89,6 +109,10 @@ static logClientId iocLogClientInit (void)
|
||||
return NULL;
|
||||
}
|
||||
id = logClientCreate (addr, port);
|
||||
if (id != NULL) {
|
||||
errlogAddListener (logClientSendMessage, id);
|
||||
epicsAtExit (iocLogClientDestroy, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -135,3 +159,4 @@ logClientId epicsShareAPI logClientInit (void)
|
||||
{
|
||||
return iocLogClientInit ();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
static unsigned short ioc_log_port;
|
||||
static long ioc_log_file_limit;
|
||||
static char ioc_log_file_name[256];
|
||||
static char ioc_log_file_name[512];
|
||||
static char ioc_log_file_command[256];
|
||||
|
||||
|
||||
@@ -866,7 +866,12 @@ static int setupSIGHUP(struct ioc_log_server *pserver)
|
||||
*/
|
||||
static void sighupHandler(int signo)
|
||||
{
|
||||
(void) write(sighupPipe[1], "SIGHUP\n", 7);
|
||||
const char msg[] = "SIGHUP\n";
|
||||
const ssize_t bytesWritten = write(sighupPipe[1], msg, sizeof(msg));
|
||||
if (bytesWritten != sizeof(msg)) {
|
||||
fprintf(stderr, "iocLogServer: failed to write to SIGHUP pipe because "
|
||||
"`%s'\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -884,7 +889,10 @@ static void serviceSighupRequest(void *pParam)
|
||||
/*
|
||||
* Read and discard message from pipe.
|
||||
*/
|
||||
(void) read(sighupPipe[0], buff, sizeof buff);
|
||||
if (read(sighupPipe[0], buff, sizeof buff) <= 0) {
|
||||
fprintf(stderr, "iocLogServer: failed to read from SIGHUP pipe because "
|
||||
"`%s'\n", strerror(errno));
|
||||
};
|
||||
|
||||
/*
|
||||
* Determine new log file name.
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
#define epicsExportSharedSymbols
|
||||
#include "dbDefs.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "iocLog.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsTime.h"
|
||||
@@ -33,9 +33,13 @@
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsExit.h"
|
||||
#include "epicsSignal.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
#include "logClient.h"
|
||||
|
||||
int logClientDebug = 0;
|
||||
epicsExportAddress (int, logClientDebug);
|
||||
|
||||
typedef struct {
|
||||
char msgBuf[0x4000];
|
||||
struct sockaddr_in addr;
|
||||
@@ -44,8 +48,10 @@ typedef struct {
|
||||
SOCKET sock;
|
||||
epicsThreadId restartThreadId;
|
||||
epicsEventId stateChangeNotify;
|
||||
epicsEventId shutdownNotify;
|
||||
unsigned connectCount;
|
||||
unsigned nextMsgIndex;
|
||||
unsigned backlog;
|
||||
unsigned connected;
|
||||
unsigned shutdown;
|
||||
unsigned shutdownConfirm;
|
||||
@@ -53,7 +59,6 @@ typedef struct {
|
||||
} logClient;
|
||||
|
||||
static const double LOG_RESTART_DELAY = 5.0; /* sec */
|
||||
static const double LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT = 5.0; /* sec */
|
||||
static const double LOG_SERVER_SHUTDOWN_TIMEOUT = 30.0; /* sec */
|
||||
|
||||
/*
|
||||
@@ -66,10 +71,10 @@ static char* logClientPrefix = NULL;
|
||||
*/
|
||||
static void logClientClose ( logClient *pClient )
|
||||
{
|
||||
# ifdef DEBUG
|
||||
if (logClientDebug) {
|
||||
fprintf (stderr, "log client: lingering for connection close...");
|
||||
fflush (stderr);
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
* mutex on
|
||||
@@ -84,8 +89,6 @@ static void logClientClose ( logClient *pClient )
|
||||
pClient->sock = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
pClient->nextMsgIndex = 0u;
|
||||
memset ( pClient->msgBuf, '\0', sizeof ( pClient->msgBuf ) );
|
||||
pClient->connected = 0u;
|
||||
|
||||
/*
|
||||
@@ -93,9 +96,8 @@ static void logClientClose ( logClient *pClient )
|
||||
*/
|
||||
epicsMutexUnlock (pClient->mutex);
|
||||
|
||||
# ifdef DEBUG
|
||||
if (logClientDebug)
|
||||
fprintf (stderr, "done\n");
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -113,6 +115,7 @@ static void logClientDestroy (logClientId id)
|
||||
epicsMutexMustLock ( pClient->mutex );
|
||||
pClient->shutdown = 1u;
|
||||
epicsMutexUnlock ( pClient->mutex );
|
||||
epicsEventSignal ( pClient->shutdownNotify );
|
||||
|
||||
/* unblock log client thread blocking in send() or connect() */
|
||||
interruptInfo =
|
||||
@@ -154,13 +157,11 @@ static void logClientDestroy (logClientId id)
|
||||
return;
|
||||
}
|
||||
|
||||
errlogRemoveListeners ( logClientSendMessage, (void *) pClient );
|
||||
|
||||
logClientClose ( pClient );
|
||||
|
||||
epicsMutexDestroy ( pClient->mutex );
|
||||
|
||||
epicsEventDestroy ( pClient->stateChangeNotify );
|
||||
epicsEventDestroy ( pClient->shutdownNotify );
|
||||
|
||||
free ( pClient );
|
||||
}
|
||||
@@ -176,61 +177,26 @@ static void sendMessageChunk(logClient * pClient, const char * message) {
|
||||
unsigned msgBufBytesLeft =
|
||||
sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex;
|
||||
|
||||
if ( strSize > msgBufBytesLeft ) {
|
||||
int status;
|
||||
|
||||
if ( ! pClient->connected ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( msgBufBytesLeft > 0u ) {
|
||||
memcpy ( & pClient->msgBuf[pClient->nextMsgIndex],
|
||||
message, msgBufBytesLeft );
|
||||
pClient->nextMsgIndex += msgBufBytesLeft;
|
||||
strSize -= msgBufBytesLeft;
|
||||
message += msgBufBytesLeft;
|
||||
}
|
||||
|
||||
status = send ( pClient->sock, pClient->msgBuf,
|
||||
pClient->nextMsgIndex, 0 );
|
||||
if ( status > 0 ) {
|
||||
unsigned nSent = (unsigned) status;
|
||||
if ( nSent < pClient->nextMsgIndex ) {
|
||||
unsigned newNextMsgIndex = pClient->nextMsgIndex - nSent;
|
||||
memmove ( pClient->msgBuf, & pClient->msgBuf[nSent],
|
||||
newNextMsgIndex );
|
||||
pClient->nextMsgIndex = newNextMsgIndex;
|
||||
}
|
||||
else {
|
||||
pClient->nextMsgIndex = 0u;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( ! pClient->shutdown ) {
|
||||
char sockErrBuf[64];
|
||||
if ( status ) {
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
}
|
||||
else {
|
||||
strcpy ( sockErrBuf, "server initiated disconnect" );
|
||||
}
|
||||
fprintf ( stderr, "log client: lost contact with log server at \"%s\" because \"%s\"\n",
|
||||
pClient->name, sockErrBuf );
|
||||
}
|
||||
logClientClose ( pClient );
|
||||
break;
|
||||
}
|
||||
if ( msgBufBytesLeft < strSize && pClient->nextMsgIndex != 0u && pClient->connected)
|
||||
{
|
||||
/* buffer is full, thus flush it */
|
||||
logClientFlush ( pClient );
|
||||
msgBufBytesLeft = sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex;
|
||||
}
|
||||
else {
|
||||
memcpy ( & pClient->msgBuf[pClient->nextMsgIndex],
|
||||
message, strSize );
|
||||
pClient->nextMsgIndex += strSize;
|
||||
if ( msgBufBytesLeft == 0u ) {
|
||||
fprintf ( stderr, "log client: messages to \"%s\" are lost\n",
|
||||
pClient->name );
|
||||
break;
|
||||
}
|
||||
if ( msgBufBytesLeft > strSize) msgBufBytesLeft = strSize;
|
||||
memcpy ( & pClient->msgBuf[pClient->nextMsgIndex],
|
||||
message, msgBufBytesLeft );
|
||||
pClient->nextMsgIndex += msgBufBytesLeft;
|
||||
strSize -= msgBufBytesLeft;
|
||||
message += msgBufBytesLeft;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* logClientSend ()
|
||||
*/
|
||||
@@ -255,43 +221,54 @@ void epicsShareAPI logClientSend ( logClientId id, const char * message )
|
||||
|
||||
void epicsShareAPI logClientFlush ( logClientId id )
|
||||
{
|
||||
unsigned nSent;
|
||||
int status = 0;
|
||||
|
||||
logClient * pClient = ( logClient * ) id;
|
||||
|
||||
if ( ! pClient ) {
|
||||
if ( ! pClient || ! pClient->connected ) {
|
||||
return;
|
||||
}
|
||||
|
||||
epicsMutexMustLock ( pClient->mutex );
|
||||
|
||||
while ( pClient->nextMsgIndex && pClient->connected ) {
|
||||
int status = send ( pClient->sock, pClient->msgBuf,
|
||||
pClient->nextMsgIndex, 0 );
|
||||
if ( status > 0 ) {
|
||||
unsigned nSent = (unsigned) status;
|
||||
if ( nSent < pClient->nextMsgIndex ) {
|
||||
unsigned newNextMsgIndex = pClient->nextMsgIndex - nSent;
|
||||
memmove ( pClient->msgBuf, & pClient->msgBuf[nSent],
|
||||
newNextMsgIndex );
|
||||
pClient->nextMsgIndex = newNextMsgIndex;
|
||||
}
|
||||
else {
|
||||
pClient->nextMsgIndex = 0u;
|
||||
}
|
||||
nSent = pClient->backlog;
|
||||
while ( nSent < pClient->nextMsgIndex && pClient->connected ) {
|
||||
status = send ( pClient->sock, pClient->msgBuf + nSent,
|
||||
pClient->nextMsgIndex - nSent, 0 );
|
||||
if ( status < 0 ) break;
|
||||
nSent += status;
|
||||
}
|
||||
|
||||
if ( pClient->backlog > 0 && status >= 0 )
|
||||
{
|
||||
/* On Linux send 0 bytes can detect EPIPE */
|
||||
/* NOOP on Windows, fails on vxWorks */
|
||||
errno = 0;
|
||||
status = send ( pClient->sock, NULL, 0, 0 );
|
||||
if (!(errno == ECONNRESET || errno == EPIPE)) status = 0;
|
||||
}
|
||||
|
||||
if ( status < 0 ) {
|
||||
if ( ! pClient->shutdown ) {
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf ( stderr, "log client: lost contact with log server at \"%s\" because \"%s\"\n",
|
||||
pClient->name, sockErrBuf );
|
||||
}
|
||||
else {
|
||||
if ( ! pClient->shutdown ) {
|
||||
char sockErrBuf[64];
|
||||
if ( status ) {
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
}
|
||||
else {
|
||||
strcpy ( sockErrBuf, "server initiated disconnect" );
|
||||
}
|
||||
fprintf ( stderr, "log client: lost contact with log server at \"%s\" because \"%s\"\n",
|
||||
pClient->name, sockErrBuf );
|
||||
}
|
||||
logClientClose ( pClient );
|
||||
break;
|
||||
pClient->backlog = 0;
|
||||
logClientClose ( pClient );
|
||||
}
|
||||
else if ( nSent > 0 && pClient->nextMsgIndex > 0 ) {
|
||||
int backlog = epicsSocketUnsentCount ( pClient->sock );
|
||||
if (backlog >= 0) {
|
||||
pClient->backlog = backlog;
|
||||
nSent -= backlog;
|
||||
}
|
||||
pClient->nextMsgIndex -= nSent;
|
||||
if ( nSent > 0 && pClient->nextMsgIndex > 0 ) {
|
||||
memmove ( pClient->msgBuf, & pClient->msgBuf[nSent],
|
||||
pClient->nextMsgIndex );
|
||||
}
|
||||
}
|
||||
epicsMutexUnlock ( pClient->mutex );
|
||||
@@ -302,10 +279,10 @@ void epicsShareAPI logClientFlush ( logClientId id )
|
||||
*/
|
||||
static void logClientMakeSock (logClient *pClient)
|
||||
{
|
||||
|
||||
# ifdef DEBUG
|
||||
if (logClientDebug) {
|
||||
fprintf (stderr, "log client: creating socket...");
|
||||
# endif
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
epicsMutexMustLock (pClient->mutex);
|
||||
|
||||
@@ -314,7 +291,7 @@ static void logClientMakeSock (logClient *pClient)
|
||||
*/
|
||||
pClient->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, 0 );
|
||||
if ( pClient->sock == INVALID_SOCKET ) {
|
||||
char sockErrBuf[64];
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf ( stderr, "log client: no socket error %s\n",
|
||||
@@ -323,10 +300,8 @@ static void logClientMakeSock (logClient *pClient)
|
||||
|
||||
epicsMutexUnlock (pClient->mutex);
|
||||
|
||||
# ifdef DEBUG
|
||||
if (logClientDebug)
|
||||
fprintf (stderr, "done\n");
|
||||
# endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -366,7 +341,7 @@ static void logClientConnect (logClient *pClient)
|
||||
}
|
||||
else {
|
||||
if ( pClient->connFailStatus != errnoCpy && ! pClient->shutdown ) {
|
||||
char sockErrBuf[64];
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf (stderr,
|
||||
@@ -392,7 +367,7 @@ static void logClientConnect (logClient *pClient)
|
||||
optval = TRUE;
|
||||
status = setsockopt (pClient->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval));
|
||||
if (status<0) {
|
||||
char sockErrBuf[64];
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf (stderr, "log client: unable to enable keepalive option because \"%s\"\n", sockErrBuf);
|
||||
@@ -404,11 +379,11 @@ static void logClientConnect (logClient *pClient)
|
||||
*/
|
||||
status = shutdown (pClient->sock, SHUT_RD);
|
||||
if (status < 0) {
|
||||
char sockErrBuf[64];
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf (stderr, "%s:%d shutdown(%d,SHUT_RD) error was \"%s\"\n",
|
||||
__FILE__, __LINE__, pClient->sock, sockErrBuf);
|
||||
fprintf (stderr, "%s:%d shutdown(sock,SHUT_RD) error was \"%s\"\n",
|
||||
__FILE__, __LINE__, sockErrBuf);
|
||||
/* not fatal (although it shouldn't happen) */
|
||||
}
|
||||
|
||||
@@ -425,7 +400,7 @@ static void logClientConnect (logClient *pClient)
|
||||
lingerval.l_linger = 60*5;
|
||||
status = setsockopt (pClient->sock, SOL_SOCKET, SO_LINGER, (char *) &lingerval, sizeof(lingerval));
|
||||
if (status<0) {
|
||||
char sockErrBuf[64];
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf (stderr, "log client: unable to set linger options because \"%s\"\n", sockErrBuf);
|
||||
@@ -457,14 +432,10 @@ static void logClientRestart ( logClientId id )
|
||||
|
||||
epicsMutexUnlock ( pClient->mutex );
|
||||
|
||||
if ( isConn ) {
|
||||
logClientFlush ( pClient );
|
||||
}
|
||||
else {
|
||||
logClientConnect ( pClient );
|
||||
}
|
||||
|
||||
epicsThreadSleep ( LOG_RESTART_DELAY );
|
||||
if ( ! isConn ) logClientConnect ( pClient );
|
||||
logClientFlush ( pClient );
|
||||
|
||||
epicsEventWaitWithTimeout ( pClient->shutdownNotify, LOG_RESTART_DELAY);
|
||||
|
||||
epicsMutexMustLock ( pClient->mutex );
|
||||
}
|
||||
@@ -480,9 +451,7 @@ static void logClientRestart ( logClientId id )
|
||||
logClientId epicsShareAPI logClientCreate (
|
||||
struct in_addr server_addr, unsigned short server_port)
|
||||
{
|
||||
epicsTimeStamp begin, current;
|
||||
logClient *pClient;
|
||||
double diff;
|
||||
|
||||
pClient = calloc (1, sizeof (*pClient));
|
||||
if (pClient==NULL) {
|
||||
@@ -507,14 +476,22 @@ logClientId epicsShareAPI logClientCreate (
|
||||
pClient->shutdownConfirm = 0;
|
||||
|
||||
epicsAtExit (logClientDestroy, (void*) pClient);
|
||||
|
||||
|
||||
pClient->stateChangeNotify = epicsEventCreate (epicsEventEmpty);
|
||||
if ( ! pClient->stateChangeNotify ) {
|
||||
epicsMutexDestroy ( pClient->mutex );
|
||||
free ( pClient );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
pClient->shutdownNotify = epicsEventCreate (epicsEventEmpty);
|
||||
if ( ! pClient->shutdownNotify ) {
|
||||
epicsMutexDestroy ( pClient->mutex );
|
||||
epicsEventDestroy ( pClient->stateChangeNotify );
|
||||
free ( pClient );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pClient->restartThreadId = epicsThreadCreate (
|
||||
"logRestart", epicsThreadPriorityLow,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
@@ -522,35 +499,12 @@ logClientId epicsShareAPI logClientCreate (
|
||||
if ( pClient->restartThreadId == NULL ) {
|
||||
epicsMutexDestroy ( pClient->mutex );
|
||||
epicsEventDestroy ( pClient->stateChangeNotify );
|
||||
epicsEventDestroy ( pClient->shutdownNotify );
|
||||
free (pClient);
|
||||
fprintf(stderr, "log client: unable to start log client connection watch dog thread\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* attempt to synchronize with circuit connect
|
||||
*/
|
||||
epicsTimeGetCurrent ( & begin );
|
||||
epicsMutexMustLock ( pClient->mutex );
|
||||
do {
|
||||
epicsMutexUnlock ( pClient->mutex );
|
||||
epicsEventWaitWithTimeout (
|
||||
pClient->stateChangeNotify,
|
||||
LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT / 10.0 );
|
||||
epicsTimeGetCurrent ( & current );
|
||||
diff = epicsTimeDiffInSeconds ( & current, & begin );
|
||||
epicsMutexMustLock ( pClient->mutex );
|
||||
}
|
||||
while ( ! pClient->connected && diff < LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT );
|
||||
epicsMutexUnlock ( pClient->mutex );
|
||||
|
||||
if ( ! pClient->connected ) {
|
||||
fprintf (stderr, "log client create: timed out synchronizing with circuit connect to \"%s\" after %.1f seconds\n",
|
||||
pClient->name, LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT );
|
||||
}
|
||||
|
||||
errlogAddListener ( logClientSendMessage, (void *) pClient );
|
||||
|
||||
return (void *) pClient;
|
||||
}
|
||||
|
||||
@@ -568,24 +522,21 @@ void epicsShareAPI logClientShow (logClientId id, unsigned level)
|
||||
printf ("log client: disconnected from log server at \"%s\"\n", pClient->name);
|
||||
}
|
||||
|
||||
if (level>1) {
|
||||
printf ("log client: sock=%s, connect cycles = %u\n",
|
||||
pClient->sock==INVALID_SOCKET?"INVALID":"OK",
|
||||
pClient->connectCount);
|
||||
}
|
||||
|
||||
if (logClientPrefix) {
|
||||
printf ("log client: prefix is \"%s\"\n", logClientPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* logClientSendMessage (); deprecated
|
||||
*/
|
||||
void logClientSendMessage ( logClientId id, const char * message )
|
||||
{
|
||||
if ( !iocLogDisable ) {
|
||||
logClientSend (id, message);
|
||||
if (level>0) {
|
||||
printf ("log client: sock %s, connect cycles = %u\n",
|
||||
pClient->sock==INVALID_SOCKET?"INVALID":"OK",
|
||||
pClient->connectCount);
|
||||
}
|
||||
if (level>1) {
|
||||
printf ("log client: %u bytes in buffer\n", pClient->nextMsgIndex);
|
||||
if (pClient->nextMsgIndex)
|
||||
printf("-------------------------\n"
|
||||
"%.*s-------------------------\n",
|
||||
(int)(pClient->nextMsgIndex), pClient->msgBuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ epicsShareFunc void epicsShareAPI iocLogPrefix(const char* prefix);
|
||||
/* deprecated interface; retained for backward compatibility */
|
||||
/* note: implementations are in iocLog.c, not logClient.c */
|
||||
epicsShareFunc logClientId epicsShareAPI logClientInit (void);
|
||||
epicsShareFunc void logClientSendMessage (logClientId id, const char *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ Com_SRCS += epicsGeneralTime.c
|
||||
|
||||
# Time providers
|
||||
Com_SRCS += osiClockTime.c
|
||||
Com_SRCS_vxWorks += osiNTPTime.c
|
||||
Com_SRCS_vxWorks += osiNTPTime.c tz2timezone.c
|
||||
Com_SRCS_RTEMS += osiNTPTime.c
|
||||
|
||||
ifeq ($(OS_CLASS),vxWorks)
|
||||
@@ -86,6 +86,7 @@ endif
|
||||
|
||||
Com_SRCS += osdSock.c
|
||||
Com_SRCS += osdSockAddrReuse.cpp
|
||||
Com_SRCS += osdSockUnsentCount.c
|
||||
Com_SRCS += osiSock.c
|
||||
Com_SRCS += systemCallIntMech.cpp
|
||||
Com_SRCS += epicsSocketConvertErrnoToString.cpp
|
||||
|
||||
@@ -350,5 +350,11 @@ extern "C" {
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
// Ensure the main thread gets a unique ID
|
||||
epicsThreadId epicsThreadMainId = epicsThreadGetIdSelf();
|
||||
static epicsThreadId initMainThread(void) {
|
||||
epicsThreadId main = epicsThreadGetIdSelf();
|
||||
epicsThreadSetOkToBlock(1);
|
||||
return main;
|
||||
}
|
||||
|
||||
// Ensure the main thread gets a unique ID and allows blocking I/O
|
||||
epicsThreadId epicsThreadMainId = initMainThread();
|
||||
|
||||
@@ -205,9 +205,6 @@ epicsTime::epicsTime (const epicsTimeStamp &ts)
|
||||
epicsTime::epicsTime () :
|
||||
secPastEpoch(0u), nSec(0u) {}
|
||||
|
||||
epicsTime::epicsTime (const epicsTime &t) :
|
||||
secPastEpoch (t.secPastEpoch), nSec (t.nSec) {}
|
||||
|
||||
epicsTime epicsTime::getCurrent ()
|
||||
{
|
||||
epicsTimeStamp current;
|
||||
@@ -955,7 +952,8 @@ extern "C" {
|
||||
try {
|
||||
local_tm_nano_sec tmns = epicsTime (*pSrc);
|
||||
*pDest = tmns.ansi_tm;
|
||||
*pNSecDest = tmns.nSec;
|
||||
if (pNSecDest)
|
||||
*pNSecDest = tmns.nSec;
|
||||
}
|
||||
catch (...) {
|
||||
return epicsTimeERROR;
|
||||
@@ -967,7 +965,8 @@ extern "C" {
|
||||
try {
|
||||
gm_tm_nano_sec gmtmns = epicsTime (*pSrc);
|
||||
*pDest = gmtmns.ansi_tm;
|
||||
*pNSecDest = gmtmns.nSec;
|
||||
if (pNSecDest)
|
||||
*pNSecDest = gmtmns.nSec;
|
||||
}
|
||||
catch (...) {
|
||||
return epicsTimeERROR;
|
||||
|
||||
@@ -81,7 +81,6 @@ public:
|
||||
class formatProblemWithStructTM {};
|
||||
|
||||
epicsTime ();
|
||||
epicsTime ( const epicsTime & t );
|
||||
|
||||
static epicsTime getEvent ( const epicsTimeEvent & );
|
||||
static epicsTime getCurrent ();
|
||||
|
||||
19
src/libCom/osi/os/Darwin/osdSockUnsentCount.c
Normal file
19
src/libCom/osi/os/Darwin/osdSockUnsentCount.c
Normal file
@@ -0,0 +1,19 @@
|
||||
/*************************************************************************\
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
#include "osiSock.h"
|
||||
|
||||
/*
|
||||
* epicsSocketUnsentCount ()
|
||||
* See https://www.unix.com/man-page/osx/2/setsockopt
|
||||
*/
|
||||
int epicsSocketUnsentCount(SOCKET sock) {
|
||||
int unsent;
|
||||
socklen_t len = sizeof(unsent);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_NWRITE, &unsent, &len) == 0)
|
||||
return unsent;
|
||||
return -1;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user