#%TITLE% ISG.MAC
#
#%NAME%
# Utility macros for interactive communication with isgdevices.
#
#%CATEGORY% Tools, Isg
#
#%OVERVIEW%
# This macro set provides utilities to build macros to talk interactively
# to isgdevices. Most of the internals are implemented by
# the macro function %B%isg_main()%B% that can be customised by redefinition
# of the macros %B%isg_prompt%B%, %B%isg_update%B%, %B%isg_show%B%
# and %B%isg_process%B%.
# In this way the functionality may be extended and adapted to specific
# features of certain isgdevices.
# %BR%
# The macro %B%isg%B% is an example of use of %B%isg_main()%B% and can be
# used as a generic interactive macro to dialogue with any isgdevice.
#
#%EXAMPLE%
# %DL%
# %DT%isg 0
# %DD%Starts the interactive test program to talk to the first isgdevice
# connected to the serial line port 0.
# %XDL%
# %DT%isg isg/serlin109/6 type=VSCANNER
# %DD%Talks to the first isgdevice connected to the device isg/serlin109/6.
# %XDL%
#
#%END%
#$Log: isg.mac,v $
#Revision 1.8 2019/11/20 15:40:35 homsrego
#removed toupper and tolower, are builtin in SPEC >= 6.08. for other cases loaded spec_utils.mac
#
#Revision 1.7 2008/07/17 14:40:37 rey
#*** empty log message ***
#
#Revision 1.6 2008/07/17 14:39:25 rey
#documentation changes
#
#Revision 1.5 2004/03/10 17:21:47 rey
#isg_path command added#
#
#Revision 1.4 2003/12/08 17:39:16 fajardo
#some bugs fixed
#
#Revision 1.3 2003/07/03 06:37:30 perez
#Add userconf for blissadm
#
#Revision 1.2 2003/02/21 16:34:05 fajardo
#Support for several isgdevices.
#
jtdo("spec_utils")
jtdo("isgdevice")
#%UU% <device_name> [<parameter>=<value> ...}]
#%MDESC%
# Macro that runs the interactive loop. %B%isg%B% canrefresh certain
# information on the screen and at the same time accepts commands
# from the standard input.
# The following optional parameters can be also set.
# %UL%
# %LI%Valid parameters:%DL%
# %DT%position=<pos>
# %DD%This parameter allows to address a particular unit when the serial
# line is shared by several isgdevices in dasychain.
# <pos> is a numerical value it indicates the relative position of
# the module in the serial line chain starting from 0.
# %DT%address=<addr>
# %DD%This parameter allows to address a particular unit when the serial
# line is shared by several isgdevices in dasychain.
# <addr> is is treated as the isgdevice address set by
# the ADDR command and stored internally in the unit.
# %DT%type=<type>
# %DD%This parameter allows to address a particular unit when the serial
# line is shared by several isgdevices in dasychain.
# <type> must be an uppercase string that identifies the functional
# type of isgdevice.
# %XDL%
# %DT%isgname=<name>
# %DD%This is the private name used by spec to identify the device.
# If not set, the name is forced to %"isg%".
# %XUL%
# If no addressing parameter is specified, %B%spec%B% looks for the
# first unit in the chain.
def isg '{
global ISG[]
local retval isgname
ISG["name"] = "isg"
if ($# == 0 || (retval = _isginit("$*"))) {
if (SETUP) print "Error in line: $0 $*"
if (retval < 0) {
print "Usage: $0 device_name [parameter=value ...]"
if (yesno("\nDisplay online help", 0)) eval("help local isg")
}
exit
}
rdef isg_prompt "_isg_prompt"
rdef isg_update "_isg_update"
rdef isg_show "_isg_show"
rdef isg_process ""
isg_main(ISG["name"])
}'
def _isginit(args) '{
local i nparam auxlist0[] auxlist1[] larr
local comdev
nparam = split(args, auxlist0)
for (i = 0; i < nparam; i++) {
if (split(auxlist0[i], larr, "=") > 1){
delete auxlist0[i]
auxlist1[larr[0]] = larr[1]
} else if (i > 1) {
delete auxlist0[i]
auxlist1[larr[0]] = "yes"
}
}
if (!(0 in auxlist0)) {
printf("Bad parameters\n")
return(-1)
}
comdev = auxlist0[0]
if ("isgname" in auxlist1){
ISG["name"] = auxlist1["isgname"]
delete auxlist1["isgname"]
ISG["prompt"] = ISG["name"]
} else
ISG["prompt"] = ""
if ("position" in auxlist1){
isgdev = isgdevice_add(ISG["name"], comdev , 0, auxlist1["position"])
if (!ISG["prompt"])
ISG["prompt"] = "#" auxlist1["position"]
delete auxlist1["position"]
} else if ("address" in auxlist1){
isgdev = isgdevice_add(ISG["name"], comdev , 1, auxlist1["address"])
if (!ISG["prompt"])
ISG["prompt"] = "&" auxlist1["address"]
delete auxlist1["address"]
} else if ("type" in auxlist1){
isgdev = isgdevice_add(ISG["name"], comdev , 3, auxlist1["type"])
if (!ISG["prompt"])
ISG["prompt"] = auxlist1["type"]
delete auxlist1["type"]
} else {
isgdev = isgdevice_add(ISG["name"], comdev , 0, 0)
}
if (isgdev <= 0) {
printf("No isgdevice found at : %s\n", comdev)
return(1)
}
i = ""
for (i in auxlist1) {
print "Invalid parameter: " i "=" auxlist1[i]
}
if (i != "")
return(-1)
else
return(0)
}'
def isgserver 'runforever("isg $*")'
def _isg_prompt '{
if (ISG["prompt"])
printf("ISG(%s)", ISG["prompt"])
else
printf("ISG")
}'
def _isg_update 'update = 0'
def _isg_show ''
def _isg_process 'return(-1)'
#%UU%(<isgdev> [, <options> [, <minT>, <maxT>]])
#%MDESC%
# This macro function runs a loop to provide interactive communication to an
# isgdevice. Among the available features :
# %LI%Checks for keyboard input and compares with the list commands recognised
# by the isgdevice. If the command is recognised by the device then it sends
# it through the serial line. If not, the macro tries execution by the eval()
# function.
# %LI%Can update information on the screen, like the status of the device.
# %LI%Whith the option 'S' implements a TCP server for isgdevices.
# %LI%Implements special commands (starting by a dot character \".\" )
# %LI%It can be customised by macro redefinition.
#
def isg_main(isgname, options, minT, maxT) '{
global ISG_NCOMM
local updateT update_flag line remcomm
local line time0 devcomm answer
local commlist[]
if (minT <= 0) minT = .02
if (maxT <= 0) maxT = 2
updateT = maxT
update_flag = 0
ISG_NCOMM++
if (isg_get_commands(isgname, commlist) != ISGDEV_OK) {
print "Error talking to ISGdevice \`" isgname "\'."
return(1)
}
isg_update
isg___process(isgname, ".", 0)
while(1){
time0 = time()
line = ""
devcomm = 0
printf("\n")
isg___prompt
while(1) {
sleep(0.05)
c = input(-1)
if (c == "\n") {
if (line && !devcomm)
devcomm = isg_check_devcomm(devcomm, line, commlist)
printf("\n")
tty_cntl("cd")
break
} else if ((c == "\b" || c == "\177") && line) {
line = substr(line, 0, length(line)-1)
printf("\b \b")
if (devcomm)
devcomm = isg_check_devcomm(devcomm, line, commlist)
} else if (asc(c) == 27) {
while(input(-1));
} else if (c >= " " && c <= "z") {
if (c == " " && devcomm == 0)
devcomm = isg_check_devcomm(devcomm, line, commlist)
line = line c
printf(c)
}
if ((time()-time0) > updateT) {
isg_update
if (update_flag){
printf("\n")
isg___prompt
updateT = minT
} else {
updateT *= 2
if (updateT > maxT)
updateT = maxT
}
time0 = time()
}
}
if (devcomm > 0) {
isg___command(isgname, line)
updateT = minT
ISG_NCOMM++
} else if (devcomm < 0) {
answer = isg___process(isgname, line, commlist)
if (answer == ISGDEV_ERR)
return(0)
ISG_NCOMM++
}
isg_update
}
}'
def isg___command(isgname, line) '{
local answer
answer = isgdevice_comm_ack(isgname, line)
if(answer == ISGDEV_ERR)
printf("Error sending command [%s].\n", line)
else if (answer != "")
printf("%s\n", answer)
return(answer)
}'
#%IU%
#
def isg_check_devcomm(devcomm, line, commlist) '{
local linelen ucline commlen comm i c
linelen = length(line)
commlen = (devcomm >= 0)? devcomm : -devcomm
if (commlen) {
if (linelen >= commlen)
return(devcomm)
else {
for(i = 0; i < linelen; i++) printf("\b")
printf("%s", line)
return(0)
}
} else {
ucline = ""
for(i = 1; i <= linelen; i++) {
c = asc(substr(line, i, 1))
ucline = sprintf("%s%c", ucline, (c >= 0x60)? c - 0x20 : c)
}
sscanf(ucline, " %s", comm)
if (comm == "")
return(0)
if (comm in commlist) {
for(i = 1; i <= linelen; i++) printf("\b")
printf("%s", ucline)
return(linelen)
} else
return(-linelen)
}
}'
#%IU%
#%MDESC%
# Prints the user prompt.
#
def isg___prompt '
printf("%d.", ISG_NCOMM)
isg_prompt
printf(" > %s", line)
'
#%IU%
#%MDESC%
# Macro function that analyzes and execute special commands
# It returns '0' if it is not an internal command, '1' if the command
# is recognized and `-1' if it is not.
#
def isg___process(isgname, line, commlist) '{
local comm[] npar info[] i sl_id
if ((npar = split(line, comm) - 1) >= 0){
if (substr(comm[0], 1, 1) != ".")
return(eval(line))
if (comm[0] == "." || comm[0] == ".h" || comm[0] == ".help") {
print
if (whatis("commlist") & 0x01000000) {
print "\tDevice commands: " isgdevice_comm_ack(isgname, "?VER")
print "\t---------------"
isg_show_commlist(commlist)
print
}
print "\tInternal commands:"
print "\t------------------"
isg_show_comm("., .h, .help", "Display available commands")
isg_show_comm(".i, .info", "Display device information")
isg_show
isg_show_comm(".s, .save", "Save configuration to file")
isg_show_comm(".l, .load", "Load configuration from file")
isg_show_comm(".d, .debug", "Switch debug mode")
if (ISGDEV_CONF[isgname]["mode"] != "gpib") {
isg_show_comm(".f, .flush", "Flush communication interface")
}
isg_show_comm(".q, .quit", "Quit interactive macro")
} else if (comm[0] == ".info" || comm[0] == ".i") {
print
print "\tSPEC info"
print "\t---------"
if (ISGDEV_CONF[isgname]["mode"] == "gpib")
print "\tGPIB address: " ISGDEV_CONF[isgname]["comdev"]
else
print "\tSerial line : " ISGDEV_CONF[isgname]["comdev"] \
" Position " ISGDEV_CONF[isgname]["pos"]
sl_id = "#" ISGDEV_CONF[isgname]["comdev"] "_" \
ISGDEV_CONF[isgname]["pos"]
print "\tModule type : " ISGDEV_DEV[sl_id]["app"]
print "\t address : " ISGDEV_DEV[sl_id]["addr"]
print "\t name : " ISGDEV_DEV[sl_id]["name"]
if ("?INFO" in commlist) {
npar = split(isgdevice_comm_ack(isgname, "?INFO"), info, "\n")
print
print "\tDevice info"
print "\t-----------"
for (i = 0; i < npar; i++)
printf("\t%s\n", info[i])
}
} else if (comm[0] == ".exec" || comm[0] == ".ex") {
line = substr(line, length(comm[0]) + 1)
isg___command(isgname, line)
} else if (comm[0] == ".debug" || comm[0] == ".d") {
isgdebug
} else if (comm[0] == ".flush" || comm[0] == ".f") {
print "Flushing communication interface..."
isgdevice_flush(isgname)
} else if (comm[0] == ".quit" || comm[0] == ".q") {
stopforever()
return(ISGDEV_ERR)
} else {
isg_process
if (comm[0] == ".save" || comm[0] == ".s") {
isg_save(isgname)
} else if (comm[0] == ".load" || comm[0] == ".l") {
isg_upload(isgname)
} else {
printf("Internal command [%s] not valid.\n", comm[0])
}
}
}
return(ISGDEV_OK)
}'
def isg_show_comm(comm, descr) '{printf("\t%-20s - %s\n", comm, descr)}'
def isg_show_commlist(commlist) '{
local comm rcomm
for (comm in commlist)
commlist[comm] = 0
for (comm in commlist) {
if (commlist[comm])
continue
commlist[comm] = 1
if (substr(comm, 1, 1) != "?") {
rcomm = sprintf("?%s", comm)
if (rcomm in commlist) {
commlist[rcomm] = 1
comm = sprintf("%s, %s", comm, rcomm)
}
} else {
sscanf(comm, "?%s", rcomm)
if (rcomm in commlist) {
commlist[rcomm] = 1
comm = sprintf("%s, %s", rcomm, comm)
}
}
printf("\t%-20s - \n", comm)
}
}'
def isg_get_commands(isgname, commlist) '{
local answ list[]
answ = isgdevice_comm(isgname, "?HELP")
if (answ == ISGDEV_ERR)
return(answ)
split(answ, list)
for (i in list) {
sscanf(list[i], "%s", answ)
commlist[answ] = 0
}
return(ISGDEV_OK)
}'
def runonce(macro, key) '{
local comm
if (!key) key = "runatprompt"
comm = macro ";runonce_cleanup " key "\n"
cdef("prompt_mac", comm, key)
comm = "runonce_cleanup " key "\n"
cdef("cleanup_once", comm)
}'
def runonce_cleanup 'cdef("prompt_mac","","$1","delete")'
def runforever(macro) '{
local file comm
file = "/tmp/forever." SPEC
if (file_info(file, "-r") == 1) {
comm = "rm " file
unix(comm)
}
comm = "echo \"do_forever\nqdo " file "\" > " file
unix(comm)
comm = "chmod a+rw " file
unix(comm)
rdef do_forever macro
spec_par("keep_going", 1)
qdofile(file)
return(file)
}'
def stopforever() '{
spec_par("keep_going", 0)
rdef do_forever "if (0)"
}'
def isg_save(isgname, info, fext) '{
local path file filepath indx aux
path = isg_path("config/")
if (!fext)
fext = "." tolower(ISGDEV_CONF[isgname]["app"])
aux = isg_ls(isgname, path, fext)
file = getval("\nSave current configuration as", aux)
if (indx = index(file, ".")) {
if (substr(file, indx) != fext) {
print "No a valid filename."
return(-1)
}
} else
file = file fext
if (!info) {
info = isgdevice_comm(isgname, "?INFO")
if (info == ISGDEV_ERR)
return(-1)
}
filepath = path file
if (file_info(filepath, "-e")) {
if (!yesno(sprintf("Overwrite %s", file), 0))
return(-1)
unix(sprintf("rm %s", filepath))
}
unix(sprintf("(umask 0; touch %s)", filepath))
if (!file_info(filepath, "-w")) {
print "You do not have rights to write " filepath
return(-1)
}
fprintf(filepath, "#ISGDEVICE %s %d\n", isgdevice_comm(isgname, "?VER"), time())
fprintf(filepath, info)
close(filepath)
print "Module configuration saved in: " filepath
return(0)
}'
def isg_path(lpath) '{
local path
if (whatis("BLISSADM") & 0x04000000) {
path = BLISSADM "/local/isg/" lpath
} else {
path = SPECD "/../local/userconf/isg/" lpath
}
return(path)
}'
def isg_upload(isgname, file, fext) '{
local finfo[] path filepath
local cmdlst[] ncmd
local i answ
path = isg_path("config/")
if (!file) {
if (!fext)
fext = "." tolower(ISGDEV_CONF[isgname]["app"])
file = isg_ls(isgname, path, fext)
file = getval("\nFile to load", file)
if (!file || index(file, "*"))
return(0)
if (!index(file, "."))
file = file fext
}
filepath = path file
if (isg_file_header(filepath, finfo, 1) < 0) {
print "Problem reading file: " file
return(-1)
}
printf("\nContent of \`%s\', %s %s - %s:\n", \
file, finfo["type"], finfo["version"], date(finfo["date"]))
for(ncmd = 0; (line = getline(filepath)) != -1; ) {
local aux
if (sscanf(line, " %s", aux) <= 0 || substr(aux, 1, 1) == "#")
continue
# a patch for the ADDR command
if (sscanf(line, " ADDR \"%s", aux) == 1)
line = substr(line, 1, index(line, "\"") - 1) substr(aux, 1, index(aux, "\"") - 1)
cmdlst[ncmd++] = line
print " " line
}
if (yesno("\nUpload configuration into the device", 0)) {
for (i = 0; i < ncmd; i++) {
if (substr(cmdlst[i], 1, 1) == " ") {
print ">>> " cmdlst[i]
print isgdevice_comm_ack(isgname, cmdlst[i])
}
}
return(1)
} else
return(0)
}'
#!!! tolower and toupper are builtin in SPEC >= 6.08
# in other case is defined in spec_utils.mac
#def tolower(str) '{return(__tocase(str, 1))}'
#def toupper(str) '{return(__tocase(str, 0))}'
def __tocase(str, case) '{
string array str_a[length(str)]
str_a = str
str_a = str_a + (case * (str_a >= asc("A")) - (str_a >= asc("a"))) * (asc("a") - asc("A"))
return(sprintf("%s", str_a))
}'
def isg_ls(isgname, path, fext) '{
local aux filelist[] filepath finfo[]
local oldestd oldestf
uxcom = "cd " path "; ls *" fext
unix(uxcom, aux)
nf = split(aux, filelist, "\n")
for (i = 0; i < nf; i++){
if (filelist[i])
filepath = path filelist[i]
else
continue
if (isg_file_header(filepath, finfo) < 0) {
print filelist[i] " **BAD**"
} else {
printf("%-15s %9s %s - Created: %s\n", \
filelist[i], finfo["type"], finfo["version"],date(finfo["date"]))
if (finfo["date"] > oldestd) {
oldestf = filelist[i]
oldestd = finfo["date"]
}
}
}
if (!oldestf)
oldestf = "config" fext
return(oldestf)
}'
def isg_file_header(filepath, finfo, verbose) '{
local line unittype, version, cdate
if(getline(filepath, "open") < 0) {
return(-1)
}
line = getline(filepath)
if (sscanf(line, "#ISGDEVICE %s %s %d", unittype, version, cdate) != 3) {
if (verbose) print "Not a isgdevice configuration file."
return(-1)
}
finfo["type"] = unittype
finfo["version"] = version
finfo["date"] = cdate
return(0)
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% P.Fajardo, Revision: 8/00, (Original 8/00).
# $Revision: 1.8 $ / $Date: 2019/11/20 15:40:35 $
#%TOC%
|