diff --git a/externalLinks b/externalLinks index 99b3124..c29cb2c 100755 --- a/externalLinks +++ b/externalLinks @@ -4,8 +4,8 @@ version () { echo '$Author: zimoch $' >&2 - echo '$Date: 2015/03/11 10:54:35 $' >&2 - echo '$Revision: 1.16 $' >&2 + echo '$Date: 2016/02/19 12:31:47 $' >&2 + echo '$Revision: 1.17 $' >&2 echo '$Source: /cvs/G/EPICS/App/scripts/externalLinks,v $' >&2 exit 1 } @@ -21,6 +21,7 @@ usage () { 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 " -o | -overwrite don't warn about overwriting fields" >&2 echo " -3.13 use lastest EPICS 3.13 version (default for SLS)" >&2 echo " -3.14 use lastest EPICS 3.14 version (default for SwissFEL, HIPA)" >&2 echo " -3.x.x use specific EPICS version" >&2 @@ -48,6 +49,7 @@ do ( -d | ?(-)-debug ) DEBUG=1 ;; ( -r | ?(-)-require ) REQUIRE=1 ;; ( -w | ?(-)-where ) WHERE=1 ;; + ( -o | ?(-)-overwrite ) OVERWRITE=1 ;; ( ?(-)-3.13 ) EPICS=3.13.10 ;; ( ?(-)-3.14 ) EPICS=3.14.12 ;; ( ?(-)-3.* ) EPICS=${1##*-} ;; @@ -86,7 +88,7 @@ function expandFile () { fi if [ -r $SCAN ] then - echo "FILENAME $SCAN" + echo "# file $SCAN" cat $SCAN fi CONVERT=dbd/slsConvert.dbd @@ -96,7 +98,7 @@ function expandFile () { fi if [ -r $CONVERT ] then - echo "FILENAME $CONVERT" + echo "# file $CONVERT" cat $CONVERT fi MAINDBD=/usr/local/epics/base-${EPICS}/dbd/softIoc.dbd @@ -109,7 +111,7 @@ function expandFile () { echo "can't find base.dbd or softIoc.dbd" >&2 exit 1 fi - echo "FILENAME $MAINDBD base" + echo "# file $MAINDBD base" cat $MAINDBD for dbd in dbd/*.dbd @@ -122,7 +124,7 @@ function expandFile () { ( */exampleApp.dbd ) ;; ( */menuScan.dbd ) ;; ( */scan.dbd ) ;; - ( * ) echo "FILENAME $dbd"; expandFile $dbd ;; + ( * ) echo "# file $dbd"; expandFile $dbd ;; esac done @@ -136,30 +138,45 @@ function expandFile () { module=${module%.dbd} if [ $module != base -a $module != slsMain -a $module != sls ] then - echo "FILENAME $dbd $module"; cat $dbd + echo "# file $dbd $module"; cat $dbd fi fi - done + done + + shopt -u nullglob + for moduledir in ${EPICS_MODULES:=/ioc/modules}/* + do + module=$(basename $moduledir) + for dbd in $(ls -1rv $moduledir/*.*.*/R${EPICS}/dbd/*.dbd 2>/dev/null | head -n 1) + do + echo "# file $dbd $module"; cat $dbd + done + done for subs in $@ do - echo "FILENAME $subs" - dbLoadTemplate $subs + echo "# file $subs" + dbLoadTemplate -L -- $subs done -} | awk -v where=$WHERE -v require=$REQUIRE -v debug=$DEBUG -v epics=$EPICS ' +} | awk -v where=$WHERE -v require=$REQUIRE -v debug=$DEBUG -v epics=$EPICS -v overwrite=$OVERWRITE ' BEGIN { epics3_14ver=gensub(/^3\.14\./,"",1,epics)+0 printf ("Info: Using EPICS version %s (see -? how to change)\n", epics) > "/dev/stderr" } - /FILENAME/ { - filename = $2 + {line ++} + /# file / { + filename = $3 + module = $4 line = 0 - module = $3 if (debug) { print "reading file " filename > "/dev/stderr" - } + } + next + } + /# line / { + line = $3 -1 + next } - {line ++} /^[ \t]*#/ { next } /\{/ {context++} /\}/ {context--} @@ -170,15 +187,15 @@ function expandFile () { 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" + printf("%s:%d\n\tduplicate choice %s for menu %s\n\t%s\n", + filename, line, choice, menu, definition[menu,choice]) > "/dev/stderr" } } else { ischoice[menu,choice] = 1 enum[menu,choicenum[menu]++] = choice - choices[menu] = choices[menu] "\n\t\"" choice "\"" + choices[menu] = choices[menu] "\"" choice "\" " modulename[menu,choice] = module - definition[menu,choice] = filename " line " line + definition[menu,choice] = filename ":" line } } } @@ -190,32 +207,31 @@ function expandFile () { 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" + printf("%s:%d\n\tduplicate choice %s for menu %s\n\t%s\n", + filename, line, choice, menu, definition[menu,choice]) > "/dev/stderr" } } else { ischoice[menu,choice] = 1 enum[menu,choicenum[menu]++] = choice - choices[menu] = choices[menu] "\n\t\"" choice "\"" + choices[menu] = choices[menu] "\""choice "\" " modulename[menu,choice] = module - definition[menu,choice] = filename " line " line + definition[menu,choice] = filename ":" line } } } /recordtype\(.*\)/ { match($0,/\((.*)\)/,a) rtype = a[1] - if (isdefined[rtype]) { + if (definition[rtype]) { if (debug) { - printf("duplicate recordtype %s\n\t%s line %d\n\t%s\n", - rtype, filename, line, definition[rtype]) > "/dev/stderr" + printf("%s:%d\n\tduplicate recordtype %s\n\t%s\n", + filename, line, rtype, definition[rtype]) > "/dev/stderr" } modulename[rtype] = modulename[rtype] "\" or \"" module valid = 0 } else { - isdefined[rtype] = 1 modulename[rtype] = module - definition[rtype] = filename " line " line + definition[rtype] = filename ":" line valid = 1 } } @@ -229,6 +245,10 @@ function expandFile () { isnoaccess[rtype,field] = 1 next } + /special\(SPC_DBADDR\)/ { + isnoaccess[rtype,field] = 0 + next + } /field\(.*,DBF_.*\)/ { if (field != "NAME") { fields[rtype] = fields[rtype] field " " @@ -255,37 +275,37 @@ function expandFile () { next } /field\(.*,DBF_ULONG\)/ { - isunsigned[rtype,field] = 1 + isunsigned[rtype,field] = "ULONG" range[rtype,field] = 0xffffffff next } /field\(.*,DBF_USHORT\)/ { - isunsigned[rtype,field] = 1 + isunsigned[rtype,field] = "USHORT" range[rtype,field] = 0xffff next } /field\(.*,DBF_UCHAR\)/ { - isunsigned[rtype,field] = 1 + isunsigned[rtype,field] = "UCHAR" range[rtype,field] = 0xff next } /field\(.*,DBF_LONG\)/ { - isinteger[rtype,field] = 1 + isinteger[rtype,field] = "LONG" range[rtype,field] = 0x7fffffff next } /field\(.*,DBF_SHORT\)/ { - isinteger[rtype,field] = 1 + isinteger[rtype,field] = "SHORT" range[rtype,field] = 0x7fff next } /field\(.*,DBF_CHAR\)/ { - isinteger[rtype,field] = 1 + isinteger[rtype,field] = "CHAR" range[rtype,field] = 0x7f next } /field\(.*,DBF_ENUM\)/ { - isunsigned[rtype,field] = 1 + isunsigned[rtype,field] = "ENUM" range[rtype,field] = 0xffff next } @@ -299,7 +319,7 @@ function expandFile () { } else { valid = 1 choicenum[menu] = 0 - definition[menu] = filename " line " line + definition[menu] = filename ":" line } } else { match($0,/\((.*)\)/,a) @@ -323,17 +343,16 @@ function expandFile () { dtype = a[3] if (ltype == "CONSTANT") { issoft[rtype,dtype] = 1 } - if (isdefined[rtype, dtype]) { + if (definition[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" + printf("%s:%d\n\tduplicate device type \"%s\" for record type %s\n\t%s\n", + filename, line, dtype, rtype, 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 + devices[rtype] = devices[rtype] "\"" dtype "\" " + definition[rtype, dtype] = filename ":" line } } /record\(.*,".*"\)/ { @@ -341,11 +360,11 @@ function expandFile () { 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" + printf("%s:%d\n\trecord \"%s\" redefined with different type %s\n\tfirst defined as %s in %s\n", + filename, line, record, rtype, recordtype[record], definition[record]) > "/dev/stderr" } else { recordtype[record] = rtype - definition[record] = filename + definition[record] = filename ":" line if (!required[modulename[rtype]]) { if (debug) { printf ("recordtype %s requires \"%s\"\n", rtype, modulename[rtype]) > "/dev/stderr" @@ -353,27 +372,27 @@ function expandFile () { required[modulename[rtype]] = 1 } } - if (length(record)>maxNameLen) { - printf("record name \"%s\" %d chars too long (max %d)\nmaybe this works with a higher EPICS version (this is %s)\n", - record, length(record)-maxNameLen, maxNameLen, epics) > "/dev/stderr" + if (length(record)>maxNameLen && record !~ /\$\(.*\)/) { + printf("%s:%d\n\trecord name \"%s\" %d chars too long (max %d)\n\tmaybe this works with a higher EPICS version (this is %s)\n", + filename, line, record, length(record)-maxNameLen, maxNameLen, epics) > "/dev/stderr" } if (record ~ /[ \t.]/) { - printf("whitespaces or dots in record name \"%s\" are not recommended\n", record) > "/dev/stderr" - + printf("%s:%d\n\trecord \"%s\"\n\twhitespaces or dots are not allowed in record names\n", + filename, line, record) > "/dev/stderr" } soft = 1 } /alias\(".*\",".*\")/ { if (epics3_14ver < 11) { - printf ("%s requires EPICS version >= 3.14.11 (this is %s)\n", - $0, epics) > "/dev/stderr" + printf ("%s:%d\n\t%s\n\trequires EPICS version >= 3.14.11 (this is %s)\n", + filename, line, $0, epics) > "/dev/stderr" } match($0,/\("(.*)","(.*)"/,a) record = a[1] aliasname = a[2] if (recordtype[record] == "") { - printf ("alias \"%s\" defined for not existing record \"%s\"\n\tin %s\n", - aliasname, record, filename) > "/dev/stderr" + printf ("%s:%d\n\talias \"%s\" undefined record \"%s\"\n", + filename, line, aliasname, record) > "/dev/stderr" } alias[aliasname] = record; } @@ -384,14 +403,28 @@ function expandFile () { value = a[2] menu = menuname[rtype,field] - if (fieldvalue[record,field] && fieldvalue[record,field] != value) { - printf("%s.%s redefined from \"%s\" to \"%s\"\n", - record, field, fieldvalue[record,field], value) > "/dev/stderr" + if (fieldvalue[record,field] && fieldvalue[record,field] != value && !overwrite) { + printf("%s:%d\n\t%s record \"%s\" field %s\n\tvalue redefined from \"%s\" to \"%s\"\n\tfirst defined in %s\n", + filename, line, rtype, record, field, fieldvalue[record,field], value, definition[record,field]) > "/dev/stderr" } - fieldvalue[record,field] = value - if (isnoaccess[rtype,field]) { + fieldvalue[record,field] = value + definition[record,field] = filename ":" line + if (!isfield[rtype,field]) { + printf("%s:%d\n\t%s record \"%s\" unknown field %s\n\tshould be one of:\n%s\n\n", + filename, line, rtype, record, field, fields[rtype]) > "/dev/stderr" + } else if (isnoaccess[rtype,field]) { printf("writing \"%s\" to NOACCESS field %s.%s\n", value, record, field) > "/dev/stderr" + } else if (islink[rtype,field]) { + if (value !~ /^ *(\$\([^)]*\) *)*$/ && \ + tolower(value) !~ /^ *[+-]?(0[0-7]*|0x[0-9a-f]+|[1-9][0-9]*|([0-9]+.?[0-9]*|[0-9]*.?[0-9]+)(e[-+]?[0-9]+)?|inf|nan) *$/ && \ + ((field != "INP" && field != "OUT") || soft)) { + reference[gensub(/ .*/,"",1,value)] = filename ":" line "\n\t" record "." field + } + if (field == "INP" || field == "OUT") { + iolink[record] = field + } + } else if (value ~ /\$\(.*\)/) { } else if (isdevice[rtype,field]) { if (iolink[record]) { if (!dtyp[record]) { @@ -399,9 +432,9 @@ function expandFile () { field, iolink[record], record) > "/dev/stderr" } } - if (!isdefined[rtype,value]) { - printf("unknown device \"%s\" in %s.%s (%s)\n", - value, record, field, rtype) > "/dev/stderr" + if (!definition[rtype,value]) { + printf("%s:%d\n\t%s record \"%s\" field %s\n\tunknown device \"%s\" should be one of:\n%s\n\n", + filename, line, rtype, record, field, value, devices[rtype]) > "/dev/stderr" } else { if (!required[modulename[rtype,value]]) { if (debug) { @@ -413,59 +446,46 @@ function expandFile () { } soft = issoft[rtype,value] dtyp[record] = value - } else if (islink[rtype,field]) { - if (value != "" && \ - tolower(value) !~ /^ *[+-]?(([0-9]+.?[0-9]*|[0-9]*.?[0-9]+)(e[-+]?[0-9]+)?|inf|nan) *$/ && \ - ((field != "INP" && field != "OUT") || soft)) { - reference[gensub(/ .*/,"",1,value)] = filename ": "record "." field - } - if (field == "INP" || field == "OUT") { - iolink[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" + printf("%s:%d\n\t%s record \"%s\" field %s\n\tunknown %s choice \"%s\" should be one of:\n%s\n\n", + filename, line, rtype, record, field, menu, value, 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" + printf("%s:%d\n\t%s record \"%s\" field %s\n\tbetter use %s choice \"%s\" instead of number \"%s\"\n", + filename, line, rtype, record, field, menu, enum[menu,value], value) > "/dev/stderr" } } } else if (isnumeric[rtype,field]) { - if (!match(tolower(value),/^ *[+-]?(([0-9]+.?[0-9]*|[0-9]*.?[0-9]+)(e[-+]?[0-9]+)?|inf|nan) *$/)) { - printf("value \"%s\" in %s.%s (%s) should be numeric\n", - value, record, field, rtype) > "/dev/stderr" + if (!match(tolower(value),/^ *[+-]?(0[0-7]*|0x[0-9a-f]+|[1-9][0-9]*|([0-9]+.?[0-9]*|[0-9]*.?[0-9]+)(e[-+]?[0-9]+)?|inf|nan) *$/)) { + printf("%s:%d\n\t%s record \"%s\" field %s\n\tvalue \"%s\" should be numeric\n", + filename, line, rtype, record, field, value) > "/dev/stderr" } } else if (isinteger[rtype,field]) { - if (!match(tolower(value),/^ *[+-]?(0x[0-9a-f]+|[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 (!match(tolower(value),/^ *[+-]?(0[0-7]*|0x[0-9a-f]+|[1-9][0-9]*) *$/)) { + printf("%s:%d\n\t%s record \"%s\" field %s\n\tvalue \"%s\" should be %s (%d ... %d)\n", + filename, line, rtype, record, field, value, isinteger[rtype,field], -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" + printf("%s:%d\n\t%s record \"%s\" field %s\n\tvalue %s is out of %s range %d ... %d\n", + filename, line, rtype, record, field, value, isinteger[rtype,field], -range[rtype,field]-1, range[rtype,field]) > "/dev/stderr" } } else if (isunsigned[rtype,field]) { - if (!match(tolower(value),/^ *+?(0x[0-9a-f]+|[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 (!match(tolower(value),/^ *+?(0[0-7]*|0x[0-9a-f]+|[1-9][0-9]*) *$/)) { + printf("%s:%d\n\t%s record \"%s\" field %s\n\tvalue \"%s\" should be %s (0 ... %d)\n", + filename, line, rtype, record, field, value, isunsigned[rtype,field], 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" + printf("%s:%d\n\t%s record \"%s\" field %s\n\tvalue %s is out of %s range 0 ... %d\n", + filename, line, rtype, record, field, value, isunsigned[rtype,field], range[rtype,field]) > "/dev/stderr" } } else if (isstring[rtype,field]) { if (length(value)>stringsize[rtype,field]) { - printf("string \"%s\" in %s.%s (%s) %d chars too long (max %d)\n", - value, record, field, rtype, + printf("%s:%d\n\t%s record \"%s\" field %s\n\tstring \"%s\" is %d chars too long (max %d)\n", + filename, line, rtype, record, field, value, length(value)-stringsize[rtype,field], 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 { @@ -475,7 +495,7 @@ function expandFile () { field = a[2] if (alias[record] != "") { record = alias[record] } if (recordtype[record] == "") { - if (where) print reference[target],target + if (where) print reference[target] " -> " target else print target } else { if (field == "") { field = "VAL" } @@ -486,8 +506,10 @@ function expandFile () { printf("link \"%s\" points to non-existing %s field \"%s.%s\"\n", link, rtype, record, field) > "/dev/stderr" } else if (isnoaccess[rtype,field]) { - printf("link \"%s\" points to NOACCESS %s field \"%s.%s\"\n", - link, rtype, record, field) > "/dev/stderr" + if (!(field == "TIME" && gensub(/.*\./,"",1,link) == "TSEL")) { + printf("link \"%s\" points to NOACCESS %s field \"%s.%s\"\n", + link, rtype, record, field) > "/dev/stderr" + } } } }