new features
This commit is contained in:
428
externalLinks
Executable file
428
externalLinks
Executable file
@@ -0,0 +1,428 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Author: Dirk Zimoch
|
||||
|
||||
version () {
|
||||
echo '$Author: zimoch $' >&2
|
||||
echo '$Date: 2008/12/22 17:11:32 $' >&2
|
||||
echo '$Revision: 1.1 $' >&2
|
||||
echo '$Source: /cvs/G/EPICS/App/scripts/externalLinks,v $' >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "usage: externalLinks [options] <substitutionFiles>" >&2
|
||||
echo "returns list of link targets that are not resolved internally" >&2
|
||||
echo "optionally returns list of required modules" >&2
|
||||
echo "also does some plausibility checks" >&2
|
||||
echo "options are:" >&2
|
||||
echo " -h | -? | --help print this text and exit" >&2
|
||||
echo " -v | --version print version and exit" >&2
|
||||
echo " -d | --debug print additional debug messages" >&2
|
||||
echo " -w | --where show record.link and target" >&2
|
||||
echo " -r | --require show required modules" >&2
|
||||
echo " --3.13 use EPICS 3.13 (default for SLS)" >&2
|
||||
echo " --3.14 use EPICS 3.14 (default for XFEL)" >&2
|
||||
echo " -- next argument is file, even if starting with -" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
shopt -s nullglob
|
||||
shopt -s extglob
|
||||
|
||||
export LANG=en_US.iso885915
|
||||
if [ "${INSTBASE%/*}" == "/psi-xfel" ]
|
||||
then
|
||||
EPICS=3.14.8
|
||||
else
|
||||
EPICS=3.13.10
|
||||
fi
|
||||
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
( -h | -\? | ?(-)-help ) usage ;;
|
||||
( -v | ?(-)-version ) version ;;
|
||||
( -d | ?(-)-debug ) DEBUG=1 ;;
|
||||
( -r | ?(-)-require ) REQUIRE=1 ;;
|
||||
( -w | ?(-)-where ) WHERE=1 ;;
|
||||
( ?(-)-3.13 ) EPICS=3.13.10 ;;
|
||||
( ?(-)-3.14 ) EPICS=3.14.8 ;;
|
||||
( -- | - ) shift; break ;;
|
||||
( -* ) echo "unknown option $1 ignored" >&2 ;;
|
||||
( * ) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ $# = 0 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
function expandFile () {
|
||||
if [ ! -r $1 ]
|
||||
then
|
||||
echo "can't read $1" >&2
|
||||
return
|
||||
fi
|
||||
while read line
|
||||
do
|
||||
case $line in
|
||||
( include* ) eval expandFile ${line#include} ;;
|
||||
( * ) echo $line
|
||||
esac
|
||||
done < $1
|
||||
}
|
||||
|
||||
{
|
||||
CONVERT=dbd/slsConvert.dbd
|
||||
if [ ! -r $CONVERT ]
|
||||
then
|
||||
CONVERT=$SLSBASE/epics/base/bin/R${EPICS}/slsConvert.dbd
|
||||
fi
|
||||
if [ -r $CONVERT ]
|
||||
then
|
||||
echo "FILENAME $CONVERT"
|
||||
cat $CONVERT
|
||||
fi
|
||||
MAINDBD=$INSTBASE/iocBoot/R${EPICS}/dbd/base.dbd
|
||||
if [ ! -r $MAINDBD ]
|
||||
then
|
||||
echo "can't find $MAINDBD" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "FILENAME $MAINDBD base"
|
||||
cat $MAINDBD
|
||||
|
||||
for dbd in dbd/*.dbd
|
||||
do
|
||||
case $dbd in
|
||||
( */dbCommon.dbd ) ;;
|
||||
( */*_conv.dbd ) ;;
|
||||
( */slsConvert.dbd ) ;;
|
||||
( */slsMain.dbd ) ;;
|
||||
( */exampleApp.dbd ) ;;
|
||||
( * ) echo "FILENAME $dbd"; expandFile $dbd ;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo $INSTBASE/iocBoot/R${EPICS}/dbd/+([^-]).dbd
|
||||
|
||||
for dbd in $INSTBASE/iocBoot/R${EPICS}/dbd/+([^-]).dbd
|
||||
do
|
||||
if [ -L $dbd ]
|
||||
then
|
||||
module=$(basename $dbd)
|
||||
module=${module%.dbd}
|
||||
if [ $module != base -a $module != slsMain -a $module != sls ]
|
||||
then
|
||||
echo "FILENAME $dbd $module"; cat $dbd
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
for subs in $@
|
||||
do
|
||||
echo "FILENAME $subs"
|
||||
dbLoadTemplate $subs
|
||||
done
|
||||
} | awk -v where=$WHERE -v require=$REQUIRE -v debug=$DEBUG '
|
||||
/FILENAME/ {
|
||||
filename = $2
|
||||
line = 0
|
||||
module = $3
|
||||
if (debug) {
|
||||
print "reading file " filename > "/dev/stderr"
|
||||
}
|
||||
}
|
||||
{line ++}
|
||||
/^[ \t]*#/ { next }
|
||||
/\{/ {context++}
|
||||
/\}/ {context--}
|
||||
/choice[ \t]*([ \t]*.*[ \t]*,[ \t]*".*"[ \t]*)/ {
|
||||
if (valid) {
|
||||
match($0,/\([ \t]*(.*)[ \t]*,[ \t]*"(.*)"/,a)
|
||||
choice = a[2]
|
||||
if (ischoice[menu,choice])
|
||||
{
|
||||
if (debug) {
|
||||
printf("duplicate choice %s for menu %s\n\t%s line %d\n\t%s\n",
|
||||
choice, menu, filename, line, definition[menu,choice]) > "/dev/stderr"
|
||||
}
|
||||
} else {
|
||||
ischoice[menu,choice] = 1
|
||||
enum[menu,choicenum[menu]++] = choice
|
||||
choices[menu] = choices[menu] "\n\t\"" choice "\""
|
||||
modulename[menu,choice] = module
|
||||
definition[menu,choice] = filename " line " line
|
||||
}
|
||||
}
|
||||
}
|
||||
/breaktable[ \t]*([ \t]*.*[ \t]*)/ {
|
||||
if (valid) {
|
||||
match($0,/\([ \t]*(.*)[ \t]*)/,a)
|
||||
choice = a[1]
|
||||
menu = "menuConvert"
|
||||
if (ischoice[menu,choice])
|
||||
{
|
||||
if (debug) {
|
||||
printf("duplicate choice %s for menu %s\n\t%s line %d\n\t%s\n",
|
||||
choice, menu, filename, line, definition[menu,choice]) > "/dev/stderr"
|
||||
}
|
||||
} else {
|
||||
ischoice[menu,choice] = 1
|
||||
enum[menu,choicenum[menu]++] = choice
|
||||
choices[menu] = choices[menu] "\n\t\"" choice "\""
|
||||
modulename[menu,choice] = module
|
||||
definition[menu,choice] = filename " line " line
|
||||
}
|
||||
}
|
||||
}
|
||||
/recordtype\(.*\)/ {
|
||||
match($0,/\((.*)\)/,a)
|
||||
rtype = a[1]
|
||||
if (isdefined[rtype]) {
|
||||
if (debug) {
|
||||
printf("duplicate recordtype %s\n\t%s line %d\n\t%s\n",
|
||||
rtype, filename, line, definition[rtype]) > "/dev/stderr"
|
||||
}
|
||||
modulename[rtype] = modulename[rtype] "\" or \"" module
|
||||
valid = 0
|
||||
} else {
|
||||
isdefined[rtype] = 1
|
||||
modulename[rtype] = module
|
||||
definition[rtype] = filename " line " line
|
||||
valid = 1
|
||||
}
|
||||
}
|
||||
/field\(.*,DBF_.*\)/ {if (!valid) next }
|
||||
/field\(.*,DBF_.*\)/ {
|
||||
match($0,/\((.*),/,a)
|
||||
field = a[1]
|
||||
}
|
||||
/field\(.*,DBF_NOACCESS\)/ {
|
||||
isnoaccess[rtype,field] = 1
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_.*\)/ {
|
||||
if (field != "NAME") {
|
||||
fields[rtype] = fields[rtype] field " "
|
||||
}
|
||||
}
|
||||
/field\(.*,DBF_.*LINK\)/ {
|
||||
islink[rtype,field] = 1
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_STRING\)/ {
|
||||
isstring[rtype,field] = 1
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_DEVICE\)/ {
|
||||
isdevice[rtype,field] = 1
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_FLOAT\)/ {
|
||||
isnumeric[rtype,field] = 1
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_DOUBLE\)/ {
|
||||
isnumeric[rtype,field] = 1
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_ULONG\)/ {
|
||||
isunsigned[rtype,field] = 1
|
||||
range[rtype,field] = 0xffffffff
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_USHORT\)/ {
|
||||
isunsigned[rtype,field] = 1
|
||||
range[rtype,field] = 0xffff
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_UCHAR\)/ {
|
||||
isunsigned[rtype,field] = 1
|
||||
range[rtype,field] = 0xff
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_LONG\)/ {
|
||||
isinteger[rtype,field] = 1
|
||||
range[rtype,field] = 0x7fffffff
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_SHORT\)/ {
|
||||
isinteger[rtype,field] = 1
|
||||
range[rtype,field] = 0x7fff
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_CHAR\)/ {
|
||||
isinteger[rtype,field] = 1
|
||||
range[rtype,field] = 0x7f
|
||||
next
|
||||
}
|
||||
/field\(.*,DBF_ENUM\)/ {
|
||||
isunsigned[rtype,field] = 1
|
||||
range[rtype,field] = 0xffff
|
||||
next
|
||||
}
|
||||
/menu\(.*\)/ {
|
||||
if (context == 1) {
|
||||
match($0,/\([ \t]*(.*)[ \t]*\)/,a)
|
||||
menu = a[1]
|
||||
if (choices[menu] != "") {
|
||||
#printf("menu %s redefined\n", menu) > "/dev/stderr"
|
||||
valid = 0
|
||||
} else {
|
||||
valid = 1
|
||||
choicenum[menu] = 0
|
||||
definition[menu] = filename " line " line
|
||||
}
|
||||
} else {
|
||||
match($0,/\((.*)\)/,a)
|
||||
menu = a[1]
|
||||
menuname[rtype,field] = menu
|
||||
}
|
||||
}
|
||||
/size\(.*\)/ {
|
||||
if (valid) {
|
||||
match($0,/\((.*)\)/,a)
|
||||
stringsize[rtype,field] = a[1]-1
|
||||
if (field == "NAME" && !maxNameLen) {
|
||||
maxNameLen = stringsize[rtype,field]
|
||||
}
|
||||
}
|
||||
}
|
||||
/device[ \t]*\(.*\)/ {
|
||||
match($0,/\([ \t]*(.*)[ \t]*,[ \t]*(.*)[ \t]*,.*,[ \t]*"(.*)"[ \t]*\)/,a)
|
||||
rtype = a[1]
|
||||
ltype = a[2]
|
||||
dtype = a[3]
|
||||
if (ltype == "CONSTANT") {
|
||||
issoft[rtype,dtype] = 1 }
|
||||
if (isdefined[rtype, dtype]) {
|
||||
if (debug) {
|
||||
printf("duplicate device type %s for record type %s\n\t%s line %d\n\t%s\n",
|
||||
dtype, rtype, filename, line, definition[rtype, dtype]) > "/dev/stderr"
|
||||
}
|
||||
modulename[rtype, dtype] = modulename[rtype, dtype] "\" or \"" module
|
||||
} else {
|
||||
isdefined[rtype, dtype] = 1
|
||||
modulename[rtype, dtype] = module
|
||||
devices[rtype] = devices[rtype] "\n\t\"" dtype "\""
|
||||
definition[rtype, dtype] = filename " line " line
|
||||
}
|
||||
}
|
||||
/record\(.*,".*"\)/ {
|
||||
match($0,/\((.*),"(.*)"/,a)
|
||||
rtype = a[1]
|
||||
record = a[2]
|
||||
if (recordtype[record] != "" && recordtype[record] != rtype) {
|
||||
printf("record %s redefined with different type\n\t%s in %s\n\t%s in %s\n",
|
||||
record, recordtype[record], definition[record], rtype, filename) > "/dev/stderr"
|
||||
} else {
|
||||
recordtype[record] = rtype
|
||||
definition[record] = filename
|
||||
if (!required[modulename[rtype]]) {
|
||||
if (debug) {
|
||||
printf ("recordtype %s requires \"%s\"\n", rtype, modulename[rtype]) > "/dev/stderr"
|
||||
}
|
||||
required[modulename[rtype]] = 1
|
||||
}
|
||||
}
|
||||
if (length(record)>maxNameLen) {
|
||||
printf("record name \"%s\" too long (max %d)\n",
|
||||
record, maxNameLen) > "/dev/stderr"
|
||||
}
|
||||
soft = 1
|
||||
}
|
||||
/field\(.*, ".*\")/ {
|
||||
if (!stringsize[rtype,"NAME"]) next;
|
||||
match($0,/\((.*), "(([^-+0-9\.][^\. ]*)?.*)"\)/,a)
|
||||
field = a[1]
|
||||
value = a[2]
|
||||
target = a[3]
|
||||
menu = menuname[rtype,field]
|
||||
if (isnoaccess[rtype,field]) {
|
||||
printf("writing \"%s\" to NOACCESS field %s.%s\n",
|
||||
value, record, field) > "/dev/stderr"
|
||||
} else if (isdevice[rtype,field]) {
|
||||
if (!isdefined[rtype,value]) {
|
||||
printf("unknown device \"%s\" in %s.%s (%s)\n",
|
||||
value, record, field, rtype) > "/dev/stderr"
|
||||
} else {
|
||||
if (!required[modulename[rtype,value]]) {
|
||||
if (debug) {
|
||||
printf ("DTYP \"%s\" for record type %s requires \"%s\"\n",
|
||||
value, rtype, modulename[rtype,value]) > "/dev/stderr"
|
||||
}
|
||||
required[modulename[rtype,value]] = 1
|
||||
}
|
||||
}
|
||||
soft = issoft[rtype,value]
|
||||
} else if (islink[rtype,field]) {
|
||||
if (target != "" && \
|
||||
((field != "INP" && field != "OUT") || soft)) {
|
||||
reference[target] = filename ": "record "." field
|
||||
}
|
||||
} else if (menu != "") {
|
||||
if (!ischoice[menu,value]) {
|
||||
if (value != int(value) || value < 0)
|
||||
{
|
||||
printf("unknown choice \"%s\" in %s.%s (%s) should be one of (%s):%s\n",
|
||||
value, record, field, rtype, menu, choices[menu]) > "/dev/stderr"
|
||||
} else {
|
||||
printf("better use choice \"%s\" (%s) instead of \"%s\" in %s.%s (%s)\n",
|
||||
enum[menu,value], menu, value,
|
||||
record, field, rtype) > "/dev/stderr"
|
||||
}
|
||||
}
|
||||
} else if (isnumeric[rtype,field]) {
|
||||
if (!match(value,/^ *[+-]?([0-9]+.?[0-9]*|[0-9]*.?[0-9]+)([eE][-+]?[0-9]+)? *$/)) {
|
||||
printf("value \"%s\" in %s.%s (%s) should be numeric\n",
|
||||
value, record, field, rtype) > "/dev/stderr"
|
||||
}
|
||||
} else if (isinteger[rtype,field]) {
|
||||
if (!match(value,/^ *[+-]?(0[xX])?[0-9]+ *$/)) {
|
||||
printf("value \"%s\" in %s.%s (%s) should be integer %d...%d\n",
|
||||
value, record, field, rtype, -range[rtype,field]-1, range[rtype,field]) > "/dev/stderr"
|
||||
}
|
||||
if (value+0 > range[rtype,field] || value+1 < -range[rtype,field]) {
|
||||
printf("value %s in %s.%s (%s) put of range %d...%d\n",
|
||||
value, record, field, rtype, -range[rtype,field]-1, range[rtype,field]) > "/dev/stderr"
|
||||
}
|
||||
} else if (isunsigned[rtype,field]) {
|
||||
if (!match(value,/^ *+?(0[xX])?[0-9]+ *$/)) {
|
||||
printf("value \"%s\" in %s.%s (%s) should be unsigned integer 0...%d\n",
|
||||
value, record, field, rtype, range[rtype,field]) > "/dev/stderr"
|
||||
}
|
||||
if (value+0 > range[rtype,field]) {
|
||||
printf("value %s in %s.%s (%s) put of range 0...%d\n",
|
||||
value, record, field, rtype, range[rtype,field]) > "/dev/stderr"
|
||||
}
|
||||
} else if (isstring[rtype,field]) {
|
||||
if (length(value)>stringsize[rtype,field]) {
|
||||
printf("string \"%s\" in %s.%s (%s) too long (max %d)\n",
|
||||
value, record, field, rtype,
|
||||
stringsize[rtype,field]) > "/dev/stderr"
|
||||
}
|
||||
} else {
|
||||
printf("unknown field %s in record %s (%s) should be one of:\n%s\n\n",
|
||||
field, record, rtype, fields[rtype]) > "/dev/stderr"
|
||||
}
|
||||
}
|
||||
END {
|
||||
for (target in reference) {
|
||||
if (recordtype[target] == "") {
|
||||
if (where) print reference[target],target
|
||||
else print target
|
||||
}
|
||||
}
|
||||
if (require) {
|
||||
for (module in required) {
|
||||
if (module != "base") {
|
||||
print "require \"" module "\""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'
|
||||
Reference in New Issue
Block a user