"""
#%TITLE%STLOCAL.MAC
#%NAME%
#Standard macros which can be used independ. of hardware
#%DESCRIPTION%
#In stlocal.mac you will find a collection of utilities to :
#%UL%
#%LI%edit macros
#%LI%for writting and reading local help
#%LI%print output to printer
#%LI%save and recall a configuration
#%LI%include the scan results in the data file
#%LI%save automatically the state file
#%LI%create and change the working directory
#%LI%define a new data group, using free number
#%LI%print tango error form the TANGO_ERR_STACK
#%XUL%
#%EXAMPLE%
#%PRE%
#emac mymacro (Calls your editor to modify mymacro)
#pon
#wa
#poff (Prints all the motor positions to the printer)
#putconf mysetup2 (saves a configuration)
#getconf mysetup2 (recalls mysetup2)
#help local (shows local help)
#groupinit (globalvar,width,elemno) (inits the group and returns its number)
#ctu ( counts in a loop )
#%PRE%
#%SETUP%
#No setup is necessary but you can change the editor with
# EDITOR="vi" if you do not want to use emacs
#%ATTENTION%
#This version of stlocal.mac is to be used with SPEC version 6.00.07 and later!
#Many ESRF specific macros like mv, ct have been eliminated by improvements
#made to the standard macros in standard.mac.
#The effort to keep all ESRF functionality was quite big, but we need to be
#vigilant to eliminate errors. All old code has been kept in this file as
#comments, which should allow tracking errors.
#%END%
"""
global STLOCALMACLOADED
global EDITOR
if (EDITOR=="") EDITOR="emacs"
#%UU%
#%MDESC%
#To clear an terminal window. Instead of tty_cntl("cl") use clscreen ...
#it will not loose the lift.
#
def clscreen() '{
local ii
for(ii = 0; ii < ROWS; ii ++) {
print
} # don`t do a clear screen as often visual information is lost.
}
'
#%UU%
#%MDESC%
#like wa but without dial
#def wu '{
# local s[]
# waitmove
# get_angles
# onp
# printf("\nCurrent Positions (user)\n")
# s[0] = "mne"
# s[1] = "user"
# show_motor_info(s, 2, MOTORS)
# offp;
#
#}
#'
#%UU%<macrosname>
#%MDESC%
#Edit a file
#
#def emacs '
#u emacs $1
#'
#%UU%<macroname>
#%MDESC%
#Edit a macro with emacs or another editor if the variable EDITOR is asigned
def emac '{
global EDITOR
local file
if ((whatis("$1") & 2) == 0) {
print "Usage: emac macroname"
exit
}
# give the file a suffix, so that editors can pick up the type.
file = "/tmp/$1.mac"
if (file_info(file, "-r") == 1) {
unix(sprintf("rm %s", file))
}
on(file); offt
prdef $1
ont; close(file)
unix(sprintf("%s %s", EDITOR, file))
if (file_info(file, "-r") == 1) {
fprintf(file,"\nu rm %s\n", file)
close(file)
qdofile(file)
}
}
'
#%UU%<macroname(s)>
#%MDESC%
#Like prdef but uses a pager like more to display the macro
#definition. You can define PAGER to change the page to less or
#something else.
def moredef '
def cleanup \'undef cleanup;
{ tmpfile = "/tmp/tmp_" SPEC USER
close(tmpfile)
unix(sprintf("/bin/rm -f %s",tmpfile)) } \'
{
global PAGER
tmpfile = "/tmp/tmp_" SPEC USER
unix(sprintf("/bin/rm -f %s",tmpfile))
on(tmpfile); offt
prdef $*
ont; close(tmpfile)
unix(sprintf("%s %s",PAGER == 0 ? "more" :PAGER,tmpfile))
cleanup
}
'
#%UU%
#%MDESC%
#Redefines the help macro. You can get local help with help
#local
def help '
if ($#) {
if ("$1" == "local") {
if ($# > 1) { localhelp "$2" } else { localhelp }
}
else {
gethelp("$1");
}
}
else {
local t
for (t="help";;)
if (gethelp(t) || (t = input("\nSubject? ")) == "")
break
}
'
#%IU%
#%MDESC%[subject]
#used by help, Calls a shell script machelp (must be in your path)
def localhelp '
if ($#) {
unix("machelp $*")
} else {
unix("machelp")
}
'
#%UU%
#%MDESC%
#switch the printer on, every thing on the screen will
#be sent to the printer until you type poff
def pon '{
local file
file = sprintf("/tmp/pp%s%s.log", USER, SPEC)
if (file_info(file, "-f") == 1)
unix(sprintf("rm %s", file))
on(file)
printf("PRINTER LOGFILE at %s from %s",date(),USER)
}
'
#%UU%
#%MDESC%
#switch the printer off and print the screen output since
#the last pon command.
# 3/9/98 - MP - option o12 to reduce sligthly the output so
# that it fits in a page
def poff '{
local file
file = sprintf("/tmp/pp%s%s.log", USER, SPEC)
close(file)
unix(sprintf("lp -o12 %s", file))
}
'
#%UU%
#%MDESC%
#dump a window to the printer - works on HP
def dump '
unix(sprintf("/usr/bin/X11/xwd -out /tmp/%s%sdump",USER,SPEC))
unix(sprintf("/usr/bin/X11/xpr -device ps -out /tmp/%s%sdump.ps -gray 4 /tmp/%s%sdump",USER,SPEC,USER,SPEC))
unix(sprintf("lp /tmp/%s%sdump.ps",USER,SPEC))
'
#%UU%[name]
#%MDESC%
#saves the current configuration file under the
#name [name]. If you do not give a name you will be asked for it
def putconf '
{
if ($# == 0) {
cname = getval("Save current configuration under which name","")
}
else {
cname = "$1"
}
unix(sprintf("cp %s/%s/config %s/local/spec/userconf/%s", \
SPECD,SPEC,BLISSADM,cname))
unix(sprintf("chmod 777 %s/local/spec/userconf/%s 2>/dev/null", \
BLISSADM,cname))
}
'
#%UU%[name]
#%MDESC%
#retrieves a saved configuration. The current
#configuration will be lost! If you do not give a name a list
#of all the saved configurations will be displayed and a name will
#be asked
def getconf '
{
if ($# == 0) {
unix(sprintf("ls -C %s/local/spec/userconf",BLISSADM))
printf("Use which configuration ? ")
cname = getval("")
}
else {
cname = "$1"
}
wait(-1)
user_waitall
sync
unix(sprintf("cp %s/local/spec/userconf/%s %s/%s/config", \
BLISSADM,cname,SPECD,SPEC))
}
reconfig
user_config
_assign
_assign_mono
'
#%UU%<macro>
#%MDESC%
#loads a macro from $(BLISSADM)/spec/macros
#
def jdo '{
if (file_info(sprintf("%s/../../macros/$1",SPECD), "-r") == 1)
qdofile(sprintf("%s/../../macros/$1",SPECD))
else
qdofile(sprintf("%s/../../macros/$1.mac",SPECD))
}
'
#%UU%<macro>
#%MDESC%
#loads a macro from $BLISSADM/local/spec/macros
#
def udo '{
if (file_info(sprintf("%s/local/spec/macros/$1",BLISSADM), "-r") == 1)
qdofile(sprintf("%s/local/spec/macros/$1",BLISSADM))
else
qdofile(sprintf("%s/local/spec/macros/$1.mac",BLISSADM))
}
'
#%UU%
#%MDESC%
#Saves the motor positions in a file called recover.mac and defines a
#macro %B%recover%B%to recover them later.
#
def usersave '{
local macfile
wait(-1); user_waitall; sync; get_angles
macfile=sprintf("%s/%s/userfiles/recover.mac",SPECD,SPEC)
unix(sprintf("/bin/rm -f %s;umask 000;touch %s",macfile, macfile))
if (open(macfile)) exit
fprintf(macfile,"# positions saved by %s (%s) on %s.\n", USER, SPEC, date())
fprintf(macfile,"def setback \'chg_dial(\$1,dial(\$1,\$2))\'\n")
for (i=0;i<MOTORS;i++) {
fprintf(macfile,"setback %s %g\n",motor_mne(i),A[i])
}
close (macfile)
rdef recover \'qdofile(sprintf("%s/%s/userfiles/recover.mac",SPECD,SPEC))\'
comment "Motor positions saved by %s (%s)" USER,SPEC
print "Use `recover\' to recover."
}
'
#%UU%command
#%MDESC%
#Tells you the unix time the macro execution took
def bench '{
local oldtime tunits tlabel
oldtime=time()
$*
oldtime = time()-oldtime
if (oldtime > 60) {
tunits = 60; tlabel="min."
} else if (oldtime > 1) {
tunits = 1; tlabel="sec."
} else {
tunits = 0.001; tlabel="msec."
}
printf("Execution time: %10.2f %s\n",oldtime/tunits, tlabel)
}
'
#%UU%[problem description]
#%MDESC%
#Sends a mail to the spec administrator and asks for help
def cryforhelp '
{
local descr
if ((time()/60-CRYLAST)<CRYMAXFREQ) {
printf("A little patience, please - You cried only %d Minutes ago\n",\
time()/60-CRYLAST)
printf("Retry in %d minutes\n",1+CRYMAXFREQ-(time()/60-CRYLAST))
exit
}
if (!$#) {
print "This macro mails a cry for help to your spec administrator"
descr=getval("Tell me why","")
} else {
descr ="$*"
}
if (descr == "") {
if (!yesno("Really send cry for help with no description",0)) {
exit
}
}
unix("echo CRY FOR HELP >/tmp/,xx")
fprintf("/tmp/,xx","\nfrom %s (%s,%s) on %s at %s\n%s\n",\
USER,SPEC,TERM,CRYBL,date(),descr)
if ((CRYTEL != "0")&&(CRYTEL != "")) \
fprintf ("/tmp/,xx","Tel: %s\n\nSysinfo:\n",CRYTEL)
else fprintf ("/tmp/,xx","\n\nSysinfo:\n",CRYTEL)
unix("echo hostname: `hostname` >>/tmp/,xx")
unix("echo id: `id` >>/tmp/,xx")
close("/tmp/,xx")
if (unix(sprintf("cat /tmp/,xx | rmail %s",\
((CRYREC=="0")||(CRYREC==""))?"icntl@esrf.fr":CRYREC))) {
print "Something went wrong, could not send mail"
} else {
print "I will try to get some help for you"
CRYLAST=time()/60
}
}
'
#%UU%[beamline [mail-address [tel-number]]]
#%MDESC%
#Sets some global variables for the cryforhelp macro. The [beamline]
#is for information only. I mail-address is not given, the mail is
#sent to icntl@esrf.fr. The tel-number is given for information only
def crysetup '
global CRYBL CRYREC CRYTEL CRYMAXFREQ CRYLAST
CRYMAXFREQ=15
if ($#) {
CRYBL="$1"
CRYREC="$2"
CRYTEL="$3"
} else {
CRYBL=getval("Enter the name of your beamline",CRYBL)
CRYREC=getval("Mail address of spec administrator",CRYREC)
CRYTEL=getval("Enter the telephon number you can be called back",CRYTEL)
}
'
### BEGIN ### Macros inserted by P.Fajardo (11/4/95)
#%IU%
#%MDESC%
#Prints the scan results in the data file
#
def resultline 'printf("#R %d %g %g %g %g %g %g\n", \
SCAN_N, pl_xMAX, pl_MAX, pl_FWHM, pl_CWHM, pl_COM, pl_SUM);'
#%UU%
#%MDESC%
#Activates the saving of the scan results in the data file (`#R' line).
#
def resultlinesetup '{
cdef("Ftail", "resultline\n", "resultline")
setup_tail("resultline")
}
'
#%IU%
#%MDESC%
#Used to deactivate the result line saving set by %B%resultlinesetup%B%.
#
def resultlineunsetup '{
cdef("", "", "resultline", "delete")
}
'
#%UU%[dummy-parameter]
#%MDESC%
#Saves the state file. The optional dummy parameter is internally used by
#the automatic saving feature activated by %B%saveallsetup%B%.
#
def saveall '{
local _now
_now=time()
if ($# == 0 || _now - SAVEDTIME > SAVINGTIME || _now < SAVEDTIME) {
savstate
printf("\n%s\'s state is stored\n", USER)
SAVEDTIME = _now
}
}
'
#%UU%[saving-time]
#%MDESC%
#Activates the automatic storage of the state file. The state file is saved
#to disk if the elapsed time since the last storage is longer than
#`saving-time' in seconds (defaulted to 5 minutes).
#
def saveallsetup '
global SAVEDTIME
if ($# > 0)
constant SAVINGTIME $1
else
constant SAVINGTIME 300
SAVEDTIME = time()
cdef("prompt_mac","saveall SAVINGTIME\n","saveall")
cdef("Ftail","offd;ont;saveall SAVINGTIME;ond;offt\n","saveall")
setup_tail("saveall")
'
#%IU%
#%MDESC%
#Used to cancel the `saveall' feature by the unsetup procedure.
#
def saveallunsetup '
unglobal SAVEDTIME
cdef("", "delete", "saveall")
'
#%UU%
#%MDESC%
#Changes current directory to the SPEC working directory. The SPEC working
#directory is defaulted to $HOME/data and can be modified by %B%newdir%B%.
#
def chgwd '
if (DATA_DIR == 0 || DATA_DIR == "./data") {
DATA_DIR = sprintf("%s/data", HOME)
}
if (!chdir(DATA_DIR)) {
printf("WARNING: Can\'t change directory to \`%s\'.\n", DATA_DIR)
chdir(".")
}
'
#%UU%[directory]
#%MDESC%
#Sets a new SPEC working directory. If the directory doesn't exist, the
#macro prompts the user before create it.
#
def newdir '{
local n names dir
if (DATA_DIR == 0 || DATA_DIR == "") DATA_DIR = CWD
_2 = DATA_DIR
if ($# == 0) {
_1 = getval("\nWorking directory", _2)
} else {
_1 = "$1"
}
if (_1 == "")
exit
n = split(_1, names, "/")
if (names[0] == "~") names[0] = HOME
dir = ""
for (i=0; i<n; i++) {
dir = sprintf("%s%s/", dir, names[i])
if (file_info(dir, "-d") != 1) {
if(yesno(sprintf("\"%s\" is not an existing directory, create", dir) \
,1)) {
if (unix(sprintf("mkdir %s", dir)) != 0)
exit
} else {
chdir(DATA_DIR)
exit
}
}
}
if (chdir(dir))
DATA_DIR = CWD
}
'
#%UU%
#%MDESC%
#Lets the user change the SPEC working directory and select a new file.
#This macro should be used instead of %B%newfile%B%if %B%chgwd%B%is
#executed by the startup macros.
#
def newsession '
newdir
print "\nCurrent files in directory:"
print "--------------------------"
unix("ls -F")
newfile
'
if (!(whatis("preunsetup")&2)) rdef preunsetup ""
rdef unsetup ""
cdef("config_mac", "resetup\n", "_setup_")
global SEDITOR
if (!SEDITOR) SEDITOR = "nedit -xrm 'nedit.saveOldVersion: False' -lm Spec"
#%UU%["g"]
#%MDESC%
#Runs the setup editor and executes %B%reconfig%B%and the setup files if
#they exist.%BR%
#Two files contain the local setup: a global setup that is common to all
#SPEC versions in the same installation and a particular setup file that
#is independent for each version of SPEC.
#By default the editor loads the particular setup file. Whith the parameter
#`g' the global setup file is loaded.
#
def setup '{
local file editor
wait(-1)
user_waitall
sync
editor = SEDITOR
if (GUI_RUN)
editor = sprintf("xterm -tn vt100 -e %s", editor)
if (SEDITOR == "vuepad")
editor = "/usr/vue/bin/vuepad"
# Check if setup files exist and run editor to modify
if ("$1" == "g") {
file = sprintf("%s/setup", SPECD)
} else {
file = sprintf("%s/%s/setup", SPECD, SPEC)
}
if (file_info(file) != 1)
unix(sprintf("(umask 0; touch %s)", file))
if (file_info(file, "-w") != 1) {
if (file_info(".", "-f") == 1)
printf("You do not have the right to change %s.\n", file)
else
printf("File %s does not exist.\n", file)
print "Press any key."
input(1)
} else if (!file_info(file, "size")) {
fprintf(file,"#\n")
fprintf(file,"# Add or modify setup lines.\n")
fprintf(file,"# Comment out the lines you want to cancel temporarily.\n")
fprintf(file,"#\n")
close(file)
}
if (GUI_RUN)
print "Starting setup editor. " \
"Close editor window to go back to the SPEC prompt."
unix(sprintf("%s %s", editor, file))
reconfig
}
'
#%UU%
#%MDESC%
#Executes the setup files if they exist.%BR%
#
def resetup '{
global SETUP SETUP_N
local gfile lfile gsetup lsetup
cdef("config_mac", "resetup\n", "_setup_")
preunsetup; rdef preunsetup ""; SETUP=1; SETUP_N++
cdef("prompt_mac", "resetup_end\n", "_setup_")
rdef cleanup "SETUP=0"
lsetup = (file_info(lfile = sprintf("%s/%s/setup",SPECD,SPEC), "-r") == 1)
gsetup = (file_info(gfile = sprintf("%s/setup",SPECD), "-r") == 1)
if (gsetup || lsetup) {
printf ("\nDoing SETUP.\n")
if (lsetup) qdofile(lfile)
if (gsetup) qdofile(gfile)
}
}
'
#%IU%
#%MDESC%
#Used by resetup.
#
def resetup_end '
{
if (!SETUP) {
print "\nAn error happened during SETUP. The current setup may be not ok."
print "Fix the problem and run \`resetup\'."
} else {
unsetup
rdef unsetup ""
}
SETUP=0
cdef("prompt_mac","","_setup_","delete")
}
'
#%IU%(<name>, [<parameter_string>])
#%MDESC%
#Macro function to be included in `xxxsetup' macros to implement the
#unsetup functionalities.%BR%
#When a `xxxsetup' macro is removed from one of the setup files, the macro
#`<name>unsetup' is invoked with the parameters contained
#in <parameter_string>. If <parameter_string> is omitted, the string "<name>"
#is user as only parameter for `<name>unsetup'.
#
def setup_tail(name, pars) '{
local _key unsetmacro
unsetmacro = sprintf("%sunsetup", name)
_key[0] = name
if (whatis("name") & 0x08000000) {
print "ERROR: wrong use of `setup_tail\'"
print "Usage: setup_tail(name, [parameters_as_a_string])"
} else if (SETUP) {
if (!(whatis("pars") & 0x08000000)) {
unsetmacro = sprintf("%s %s", unsetmacro, pars)
split(pars, _key)
}
cdef("preunsetup", sprintf("cdef(\'unsetup\', \'%s\n\', \'%s\')\n", \
unsetmacro, _key[0]))
cdef("unsetup","",_key[0],"delete")
}
}
'
#%IU%<macro> <first_word>
#%MDESC%
#Checks if a macro called <macro> that begins with <first_word> is already
#defined. If it is, the local variable `error' is set.
#
def checkifmacro '
local error __type
error = 1
__type = whatis("$1")
if (!__type || __type & 0x08000004) {
error = 0
} else if (__type & 2) {
local file line word
file = sprintf("/tmp/checkifmacro_%s", USER)
unix(sprintf("rm -f %s", file))
on(file); offt; prdef $1; ont ; close(file)
getline(file, 0)
while ((line = getline(file)) != -1) {
if (substr(line, 1, 3) == "def") {
sscanf(line, "def $1 \'%s", word)
if (word == "$2")
error = 0
break
}
}
getline(file, "close")
}
'
#%UU%<macro_name> <motor> [<motor> ...]
#%MDESC%
#Lets the user define new `where' macros in an easy way. A macro called
#<macro_name> is internally defined that displays the positions of the
#specified motors. If <macro_name> is invoked with a parameter more
#detailed information is presented.
#
def newwh '{
if ($# < 2) {
if (SETUP) print "Error in line: $0 $*"
print "Usage: newwh macro_name motor [motor ...]"
} else {
checkifmacro $1 _new_wh
if (!error) {
rdef $1 "_new_wh \$# $*"
setup_tail("newwh", "newwh$1 $1")
} else {
print "Macro \`$1\' is already defined. Ignoring \`newwh\'."
}
}
}
'
#%IU%"newwh<macro_name>" <macro_name>
#%MDESC%
#Undefines the macros created by %B%newwh%B%.
#
def newwhunsetup '{
checkifmacro $2 _new_wh
if (!error) undef $2
}
'
#%IU%<motor> [<motor> ...]
#%MDESC%
#Used by %B%newwh%B%to display the motor positions.
#
def _new_wh '{
local mlist newmlist n ngood nbad i j
n = split("$*", mlist) - 2
ngood = 0
for (i=0; i<n; i++) {
newmlist[ngood] = motor_num(mlist[i+2])
if (newmlist[ngood] >= 0) {
if (!is_using_motor(newmlist[ngood])) {
continue;
}
ngood++
} else {
nbad ++
printf("\`%s\' ", mlist[i+2])
}
}
if (nbad > 1)
print "are not valid motor mnemonics."
else if (nbad == 1)
print "is not a valid motor mnemonic."
if (ngood > 0) {
local row ncol col m
get_angles
i = 0
for (row = 0; row <= int((ngood-1)/6); row++) {
ncols = ngood - 6*row > 6? 6 : ngood - 6*row
for (col=0; col<ncols; col++) {
while(newmlist[i] < 0) i++;
m[col] = newmlist[i++]
}
printf("%13s", "")
for (col=0; col<ncols; col++)
printf("%10.9s ", motor_name(m[col]))
printf("\n%13s", "")
for (col=0; col<ncols; col++)
printf("%10.9s ", motor_mne(m[col]))
if ($1) {
printf("\n%13s", "(high)")
for (col=0; col<ncols; col++)
printf("%10.4f ", user(m[col], get_lim(m[col], 1)))
}
printf("\n%13s", "User ")
for (col=0; col<ncols; col++)
printf("%10.4f ", A[m[col]])
if ($1) {
printf("\n%13s", "(low)")
for (col=0; col<ncols; col++)
printf("%10.4f ", user(m[col], get_lim(m[col], -1)))
print
printf("\n%13s", "(high)")
for (col=0; col<ncols; col++)
printf("%10.4f ", get_lim(m[col], 1))
}
printf("\n%13s", "Dial ")
for (col=0; col<ncols; col++)
printf("%10.4f ", dial(m[col], A[m[col]]))
if ($1) {
printf("\n%13s", "(low)")
for (col=0; col<ncols; col++)
printf("%10.4f ", get_lim(m[col], -1))
}
print "\n"
}
}
}
'
#%UU%<macro_name> <motor> [<motor> ...]
#%MDESC%
#Lets the user define new `where' macros in an easy way. A macro called
#<macro_name> is internally defined that displays the user positions of the
#specified motors. If <macro_name> is invoked with a parameter more
#detailed information is presented.
#
def newwu '{
if ($# < 2) {
if (SETUP) print "Error in line: $0 $*"
print "Usage: newwu macro_name motor [motor ...]"
} else {
checkifmacro $1 _new_wu
if (!error) {
rdef $1 "_new_wu \$# $*"
setup_tail("newwu", "newwu$1 $1")
} else {
print "Macro \`$1\' is already defined. Ignoring \`newwu\'."
}
}
}
'
#%IU%"newwu<macro_name>" <macro_name>
#%MDESC%
#Undefines the macros created by %B%newwu%B%.
#
def newwuunsetup '{
checkifmacro $2 _new_wu
if (!error) undef $2
}
'
#%IU%<limits_flag> <dummy> <motor> [<motor> ...]
#%MDESC%
#Used by %B%newwu%B%to display only the motor user positions (not dial ones).
#
def _new_wu '{
local mlist n ngood i
n = split("$*", mlist) - 2
ngood = 0
for (i=0; i<n; i++) {
if ((mlist[i] = motor_num(mlist[i+2])) >= 0)
ngood++
else
printf("\`%s\' ", mlist[i+2])
}
if (ngood < n-1)
print "are not valid motor mnemonics."
else if (ngood == n-1)
print "is not a valid motor mnemonic."
if (ngood > 0) {
local row ncol col m
get_angles
i = 0
for (row = 0; row <= int((ngood-1)/6); row++) {
ncols = ngood - 6*row > 6? 6 : ngood - 6*row
for (col=0; col<ncols; col++) {
while(mlist[i] < 0) i++;
m[col] = mlist[i++]
}
printf("%13s", "")
for (col=0; col<ncols; col++)
printf("%10.9s ", motor_name(m[col]))
printf("\n%13s", "")
for (col=0; col<ncols; col++)
printf("%10.9s ", motor_mne(m[col]))
if ($1) {
printf("\n%13s", "(high)")
for (col=0; col<ncols; col++)
printf("%10.4f ", user(m[col], get_lim(m[col], 1)))
}
printf("\n%13s", "User ")
for (col=0; col<ncols; col++)
printf("%10.4f ", A[m[col]])
if ($1) {
printf("\n%13s", "(low)")
for (col=0; col<ncols; col++)
printf("%10.4f ", user(m[col], get_lim(m[col], -1)))
print
}
print "\n"
}
}
}
'
if (!(whatis("warningprompt") & 2)) rdef warningprompt ""
#%UU%<warningmacro> [<warningmacro> ...]
#%MDESC%
#Includes warning macros in %B%prompt_mac%B%. Warning macros display
#warning messages on the screen immediately before the prompt.%BR%
#For instance if a line %B%warningsetup datawarning%B%is included
#in your setup file, you will get amessage whenever no data file
#is selected.%BR%
#If you want to include your own warning macros, see %B%simulwarning%B%
#and %B%datawarning%B%as examples
#
def warningsetup '{
local n maclist mac
for (mac="", n = split("$*", maclist); n>0;)
mac = sprintf("%s; %s", maclist[--n], mac)
rdef warningprompt mac
cdef("prompt_mac","warningprompt\n","warning",0x20)
setup_tail("warning")
}
'
#%IU%
#%MDESC%
#Used to deactivate the warning macros by the automatic unsetup procedure.
#
def warningunsetup '
rdef warningprompt ""
cdef("prompt_mac", "delete", "warning")
'
#%IU%
#%MDESC%
#Warning macro that reminds the user that SPEC is in simulation mode.
#The macro name must be used as a parameter to warningsetup.
#
def simulwarning '
if (set_sim(-1)) { tty_cntl("md");printf("\n- SIMULATION");tty_cntl("me") }
'
#%IU%
#%MDESC%
#Warning macro that reminds the user that there is no data file selected
#in SPEC. The macro name must be used as a parameter to warningsetup.%BR%
#This macro also displays a warning message if the data file is
#called %B%dummy%B%.
#
def datawarning '
if (DATAFILE=="/dev/null" || DATAFILE=="") {
tty_cntl("md");printf("\n- NO DATA FILE");tty_cntl("me")
} else if (substr(sprintf("/%s",DATAFILE),length(DATAFILE)-4,6) == "/dummy") {
tty_cntl("md");printf("\n- DUMMY DATA FILE");tty_cntl("me")
DUMMYFILE["dummyscan"] = SCAN_N
}
'
#%UU%
#%MDESC%
#Changes the data file to a file called `dummy' in the current working
#directory. The name and the scan number of the previous data file is kept
#in memory and can be restored with %B%offdummy%B%.%BR%
#The macros %B%ondummy%B%and %B%offdummy%B%are provided as a fast way of
#switching files when one wants to run some scans (alignment checking,
#tests of command or macro files, ...) and don't want to fill up the data
#file with garbage.
#
def ondummy '{
global DUMMYFILE
local scan
if (substr(sprintf("/%s",DATAFILE),length(DATAFILE)-4,6) != "/dummy") {
DUMMYFILE["oldfile"] = DATAFILE
DUMMYFILE["oldscan"] = SCAN_N
if (file_info("dummy","-r") != 1)
DUMMYFILE["dummyscan"] = 0
if ((scan = DUMMYFILE["dummyscan"]) > 0)
scan = 10*(int((scan+1)/10)+1)-1
qcomment "Switching to data file `dummy\' scan %d" scan+1
newfile dummy scan
DUMMYFILE["dummyscan"] = SCAN_N
}
}
'
#%UU%
#%MDESC%
#Restores the previous data file name if %B%ondummy%B%was used.
#
def offdummy '{
local oldfile scan
if (substr(sprintf("/%s",DATAFILE),length(DATAFILE)-4,6) == "/dummy") {
oldfile = DUMMYFILE["oldfile"]
scan = 10*(int((DUMMYFILE["oldscan"]+1)/10)+1)-1
if (oldfile != "") {
if (file_info(oldfile, "-r") != 1) {
printf("I don\'t find the previous datafile: %s\n", oldfile)
oldfile = "/dev/null"
scan = 0
}
} else {
print "No previous datafile."
oldfile = "/dev/null"
scan = 0
}
DUMMYFILE["dummyscan"] = SCAN_N
qcomment "Switching back to data file `%s\' scan %d" "oldfile,scan"
newfile \'"oldfile"\' scan
}
}
'
#%UU%
#%MDESC%
#It is exactly like the one in standard.mac but keeping the file name even
#if the scan number is zero.
#def newfile '
# _3 = DATAFILE
# if ($# == 0) {
# _1 = getval("\nData file", DATAFILE)
# _2 = 0
# } else {
# _1 = "$1"; _2 = $2
# }
# if (_1 == "")
# exit
# if (_1 == "null")
# _1 = "/dev/null"
# if (!index(_1, "/") && file_info(DATA_DIR, "-d"))
# _1 = sprintf("%s/%s",DATA_DIR,_1)
#
# if (!file_info(_1, "-r")) {
# if (_1 == DATAFILE) {
# printf(\
# "Warning: Same name as before, but file isn\'t in %s directory.\n",\
# index(_1, "/")? "same":"current")
# printf("A new version of the file will be created.\n")
# }
# DATAFILE="/dev/null"
# } else if (_1 != "/dev/null") {
# local s
# if (file_info(s = SPECD "/chk_file", "-x"))
# if (unix(sprintf("%s %s",s,_1)))
# print "Note: file already exists."
# }
# #
# if (open(_1)) {
# DATAFILE="/dev/null"
# exit
# }
# if (_1 != "tty" && _1 != "/dev/tty")
# close(_1)
# if (_1 == DATAFILE) {
# if (open(_1)) {
# DATAFILE="/dev/null"
# exit
# }
# if ($# == 2 && SCAN_N != $2)
# SCAN_N = $2
# } else {
# if ($# == 0)
# _2 = getval("Last scan number",_2)
# else if ($# == 1)
# _2 = 0
# if (_3 != "" && _3 != "0" && _3 != "tty" && _3 != "/dev/tty")
# close(_3)
# if (open(_1)) {
# DATAFILE="/dev/null"
# exit
# }
# DATAFILE = _1
# SCAN_N = _2
# ond; offt
# printf("#F %s\n", DATAFILE)
# printf("#E %d\n",EPOCH)
# printf("#D %s\n",date())
# printf("#C %s User = %s\n",TITLE,USER)
# user_filehead
# local i,j,s
# for (i=0; i<MOTORS; i+=8) {
# s = sprintf("#O%d ", i/8)
# for (j=i; j<i+8 && j<MOTORS;) {
# if (motor_name(mA[j]) != "unused")
# s = s sprintf("%8s", motor_name(mA[j]))
# if (j%8 == 7)
# break
# s = s " "
# j++
# }
# print s
# }
# offd; ont
# }
# printf("Using \"%s\". Next scan is number %d.\n",DATAFILE,SCAN_N+1)
#'
#%UU%[<parameter>]
#%MDESC%
# Activates wizard mode for 10 minutes. If a positive parameter is provided
# the effect is permanent until %B%offwiz%B%is used. If <parameter> is
# null or negative its absolute value becames the time out in seconds
# instead of the 10 minutes default.
#def onwiz '
# if (!spec_par("specwiz")) {
# if (spec_par("specwiz",1)) {
# local timeout
# timeout = 600
# if ($#) {
# if (($1) == "$1" && ($1) <= 0)
# timeout = -($1)
# else
# timeout = -1
# }
# if (timeout >= 0) {
# global WIZ_TIME
# local wiz_timer
# wiz_timer = \
# \'if(time()>WIZ_TIME) {cdef("","","onwiz","delete");offwiz}\n\'
# WIZ_TIME = time() + timeout
# cdef("prompt_mac",wiz_timer,"onwiz")
# } else
# cdef("","","onwiz","delete")
# }
# }
#'
#
cdef("user_offwiz")
#%UU%
#%MDESC%
#Deactivates wizard mode set by %B%onwiz%B%. In replacement of the macro in
#standard.mac, as we use a user_offwiz macro. onwiz in standard.mac!
def offwiz 'spec_par("specwiz",0);user_offwiz;unglobal WIZ_TIME'
### END ### Macros inserted by P.Fajardo (11/4/95)
#%IU%[<motorgroup>]
#%MDESC%
#Handling of motor groups for the redefined %B%config%B%macro.
#<BR>
#This macro is used by the ESRF specific config macro, as we still need
#to support so-called motor groups. They use a feature of SPEC where you can
#define geometries with linked config files. This is a misuse of this
#geometry feature, but it is still used on some beamlines :-(
def config_geo '
unix(sprintf("umask 0;grep GEO %s/%s/config|cut -f3 -d\' \'>/tmp/geos", \
SPECD, SPEC))
if ("$1" != "all") {
local geo ngeo geolist goodgeo geoindx
goodgeo = 0
ngeo = 0
sscanf(getline("/tmp/geos", 0), "%s", geo)
if (geo == "all") while(1) {
sscanf(getline("/tmp/geos"), "%s", geo)
if (geo != -1) {
geolist[ngeo++] = geo
if (geo == "$1") goodgeo = ngeo
} else
break
}
getline("/tmp/geos", "close")
if (ngeo > 0 && goodgeo == 0) {
printf("\nMotor groups currently defined are:\n\n\t")
for (gindx = 0; gindx < ngeo; gindx++) printf("%s ", geolist[gindx])
geo = getval("\n\nSelect motor group", "all")
for (gindx = 0; gindx < ngeo; gindx++)
if (geo == geolist[gindx])
goodgeo=gindx+1
if (goodgeo == 0 && geo != "all") {
print "Not a valid motor group."
exit
}
}
if (goodgeo > 0)
$2 = sprintf("-g %s", geolist[goodgeo-1])
}
'
#%UU%[<motorgroup>]
#%MDESC%
#Redefinition of the standard %B%config%B%macro to include motor groups and
#specGUI configuration.
#<BR>
#This macro uses the config_geo macro, as we still need
#to support so-called motor groups. They use a feature of SPEC where you can
#define geometries with linked config files. This is a misuse of this
#geometry feature, but it is still used on some beamlines :-(
def config '{
local comm simswitch geoswitch
geoswitch = ""
config_geo $1 geoswitch
simswitch = set_sim(-1)? "-s":""
comm = sprintf("%s/edconf %s %s %s/%s",SPECD,simswitch,geoswitch,SPECD,SPEC)
wait(-1)
user_waitall
sync
if (GUI_RUN) {
print "\nStarting configuration editor. " \
"Use \`^c\' to close and go back to this window."
unix(sprintf("xterm -T \"Spec configuration (%s)\" -e %s", SPEC, comm))
} else
unix(comm)
reconfig
}
user_config
_assign
_assign_mono
if (GUI_RUN) {
X_config
}
'
#%UU%(group , points , width)
#%MDESC%
def groupinit (g, pts, w) '{
if (g==0) {
for ( i=0 ; (i<256)&&data_info(i,"elem") ; i++) {}
g=i
}
if (g<256) {
data_grp(g,pts,w)
return g
}
else return -1
}
'
#%UU%
#%MDESC%
#Redefinition of the standard %B%newmac%B%macro to make it compatible
#with the %B%jtdo()%B%function used in startup files.
def newmac '{
local t
unglobal TIMEMARK
t = sprintf("%s/site.mac", SPECD)
if (unix(sprintf("test ! -f %s", t))) {
qcomment "do %s" t
qdofile(t)
}
t = sprintf("%s/site_f.mac", SPECD)
if (unix(sprintf("test ! -f %s", t))) {
qcomment "do %s" t
qdofile(t)
}
t = sprintf("%s/%.4s.mac", SPECD, SPEC)
qcomment "do %s" t
qdofile(t)
t = sprintf("%s/standard.mac", SPECD)
qcomment "do %s" t
qdofile(t)
}
'
#%IU%([<machine>, [<stderr>]])
#%MDESC%
#This macro function returns a string describing the operating system of
#the computer called <machine>. The user must have permission to remote
#execution on <machine>. If the user has no permission or an error occurs
#the function returns -1. If <machine> is omitted or null, the function
#checks the local host.%BR%
#Current OS descriptions are: %B%hp700%B%, %B%sun4%B%, %B%solaris%B%and%B%linux%B%.%BR%.
#It is possible to redirect the standard error stream by specifying a file
#or device in <stderr>.
def ostype(machine, stderr) '{
global HT
local remuname file os vers
oscomm = "case `uname -s` in
SunOS ) if expr `uname -r` : 4* >/dev/null; then
echo sun4 ; exit 1
else
echo solaris; exit 2
fi;;
HP-UX ) echo hp700 ; exit 3;;
Linux ) echo linux ; exit 4;;
esac; echo unknown; exit 0"
HT = unix(sprintf("(%s) >/dev/null", oscomm))
HT = HT==1?"sun4":HT==2?"solaris":HT==3?"hp700":HT==4?"linux":"unknown"
if (machine == "")
return(HT)
else {
file = "/tmp/ostypespec"
if(remcom(machine, "uname -rs", "", file, stderr)) return(-1)
remuname = getline(file, 0)
getline(file, "close")
os = substr(remuname, 1, 5)
vers = substr(remuname, 7)
return(os=="HP-UX"?"hp700":os=="Linux"?"linux":os!="SunOS"?"unknown":vers<5?"sun4":"solaris")
}
}
'
#%IU%(<machine>, <command>, [<username>, [<stdout>, [<stderr>]]])
#%MDESC%
#This macro function tries to execute remotely <command> in the computer
#called <machine>. The user must have permission to remote
#execution on <machine>. If the <machine> is accessible and the user has
#the right permission the function returns 0, otherwise it returns -1.%BR%
#If <machine> is null, the function runs <command> on the local host.%BR%
#If <username> is not null the command is run as a different user in the
#remote computer.%BR%
#The standard output and standard error streams may be redirected by
#especifying not null values for <stdout> and/or <stderr> respectively.
def remcom(machine, command, username, stdout, stderr) '{
local remsh rcom get_environment
if (command == "") return(0)
if (stdout != "") stdout = sprintf(">%s", stdout); else stdout=""
if (stderr != "") stderr = sprintf("2>%s", stderr); else stderr=""
if (username != "") username = sprintf("-l %s", username); else username=""
if (machine == "") machine = "`hostname`"
get_environment = ". /etc/profile >/dev/null 2>&1"
rcom = sprintf("umask 0;%s %s %s \"%s ; %s\" %s %s", \
ostype()=="hp700"?"remsh":"rsh", \
machine, username, get_environment, command, stdout, stderr)
return(unix(rcom))
}
'
#%UU%[count-time [sleep-time]]
#%MDESC%
#It performs a counting loop and updates the value of the counters
#on the screen.
def ctu '{
local ctu_time ctu_sleep
if ($# > 0) ctu_time = $1 ; else ctu_time = 1
if ($# > 1) ctu_sleep = $2 ; else ctu_sleep = 0
rdef cleanup \'
undef cleanup
onp; show_cnts;offp
\'
waitmove
for (;;) {
local iter
count_em ctu_time
waitcount;get_counts
clscreen()
iter++
printf("%s %s. - Loop count: %4d\n","$0","$*",iter)
printf("------------------------------------------\n")
for (i=0;i<COUNTERS;i++)
if (cnt_name(i) != "unused")
printf("%12s = %g%s\n", cnt_name(i), S[i], \
i != sec && S[sec]? sprintf(" (%g/s)", S[i] / S[sec]):"")
sleep(ctu_sleep)
}
}
'
#%UU%(arr, x, y, nb, val)
#%MDESC%This macro will use calculate an approximate y value for val. This
#approximation will simply be done by a linear interpolation of the
#table given with the first 3 parameters. Nb is the number of elements in
#the array. ( You can use array_read (file,arr) to read these values
#from a file)
def interpol(arr, x, y, nb, val) '{
local i xgrows
xgrows = (arr[nb-1][x] >= arr[0][x])
for (i=0; i<nb; i++) {
if (val == arr[i][x])
return (arr[i][y])
if (xgrows && val < arr[i][x] || !xgrows && val > arr[i][x])
break;
}
if (i == 0)
return(arr[0][y])
else if (i == nb)
return (arr[nb-1][y])
else
return (arr[i-1][y] + (arr[i][y] - arr[i-1][y]) * \
(val - arr[i-1][x])/(arr[i][x] - arr[i-1][x]) )
}
'
#%UU% speccmd pipeop unixcmd
#%MDESC%executes speccmd and uses the pipeoperator to connect its output
#to a shell command. Ex.: prun prdef wa | sed -n -e '/loop/p' | wc or
#already more useful things like : prun prdef | grep user_
def prun '
cmd = \'$*\'
idx = index(cmd, "|")
idx2= index(cmd, ">")
if (idx2 && (!idx || idx2 < idx)) idx=idx2
if (!idx) {
unix(cmd)
exit
}
rnum = rand()
pfile="/tmp/pipe-" SPEC "." rnum
rdef speccmd substr(cmd, 1, idx-1)
unix(sprintf("/bin/rm -f %s", pfile)) ; on(pfile) ; offt
cdef("cleanup_once", \
"close(pfile); unix(sprintf(\"/bin/rm -f %s\", pfile)); ont; \
unglobal pfile rnum;\n", "wdx")
speccmd
close(pfile) ; ont
unix(sprintf("cat %s %s", pfile, substr(cmd,idx)))
#unix(sprintf("/bin/rm -f %s", pfile) # done by cleanup_once
unglobal pfile rnum
'
#%UU%[<file>]
#%MDESC%
#Display <file> or the datafile using `less'.
#
def more '{
local _1
if ($# == 0)
if (DATAFILE=="/dev/null" || DATAFILE=="") {
print "No data file."
exit
} else {
_1 = DATAFILE
}
else{
if ((whatis("$1") & 0x00200000) != 0)
_1 = $1
else
_1 = "$*"
}
unix(sprintf("less -P\"press \'q\' to exit, \'h\' for help\" %s", _1))
}
'
#%UU%[<scan_no>]
#%MDESC%
#Display the current scan ot <scan_no> using `less' with the current
#data file.
#
def shs '{
local str
if (DATAFILE=="/dev/null" || DATAFILE=="") {
print "No data file."
exit
}
if ($# == 0)
_1 = SCAN_N
else
_1 = $1
str = sprintf("\'+/#S %d\' %s", _1, DATAFILE)
more str
}
'
#%UU%
#%MDESC%
#Allows to pause in loops during macros or user macro files
#If defined (with cdef) in user_scan_loop it will allow users to stop
#temporarily execution of any scan.
#The key
def pause_query '{
local po
po=input(-1)
if ( po == "p" ) {
print "Execution suspended. Type \"r\" to resume"
while (input(-1) != "r" ) {
}
print "Execution resumed."
}
while (input(-1) != "" ) {}
}
'
#%UU%<mot1> <mot2> <lower limit Pos1-Pos2> <upper limit Pos1-Pos2>
#%MDESC%Define limits on the relative position of two motors. Pos1 - Pos2
#must be in between the lower and upper limit.
def set_rel_lm '{
if ($# != 4) {
p "Usage: $0 <mot1> <mot2> <lower limit Pos1-Pos2> <upper limit Pos1-Pos2>"
exit
}
_check0 "$1"; _check0 "$2"
cdef("user_checkall",sprintf("if (motor_num(\"$1\") != -1 && motor_num(\"$2\") != -1 && (A[$1] - A[$2] > %g || A[$1] - A[$2] < %g)) { print \"Relative limits for $1-$2 hit (Allowed range is [%g %g])\" ; exit }\n", ($4), ($3), ($3) , ($4)), "$1_$2")
}
'
#%UU%<mot1> <mot2>
#%MDESC%Deletes limits for relative position Mot1 - Mot2 defined with
#set_rel_lm
def del_rel_lm '{
if ($# != 4) {
p "Usage: $0 <mot1> <mot2>"
exit
}
_check0 "$1"; _check0 "$2"
cdef("user_checkall", "", "$1_$2", "delete")
}
'
# 2012/07/25 rh increased from 50 to 100
PLOT_CNTRS_MAX=100
#%UU%(command, macrofile)
#%MDESC%If the command is not defined, loads the macrofile
def mayneed(command, macro) '{
local a
a = macro
if ((whatis(command) == 0)) {
printf("macro set %s needed\nLoading it ....\n",macro)
if (file_info(sprintf("%s/local/spec/macros/%s",BLISSADM, a), "-r") == 1) {
qdofile(sprintf("%s/local/spec/macros/%s",BLISSADM, a))
} else {
if (file_info(sprintf("%s/local/spec/macros/%s.mac",BLISSADM, a), "-r") == 1) {
qdofile(sprintf("%s/local/spec/macros/%s.mac",BLISSADM, a))
} else {
if (file_info(sprintf("%s/../../macros/%s",SPECD, a), "-r") == 1) {
qdofile(sprintf("%s/../../macros/%s",SPECD, a))
} else {
if (file_info(sprintf("%s/../../macros/%s.mac",SPECD, a), "-r") == 1) {
qdofile(sprintf("%s/../../macros/%s.mac",SPECD, a))
} else {
if (file_info(sprintf("%s", a),"-r") == 1) {
qdofile(sprintf("%s", a))
} else {
if (file_info(sprintf("%s.mac", a),"-r") == 1) {
qdofile(sprintf("%s.mac", a))
} else {
printf("************* File not found **************\n")
printf("********** Unsuccessfull loading **********\n")
return 1
}
}
}
}
}
}
}
return 0
}
'
#%UU%(keyword)
#%MDESC%This macro will print all the existing errors from the built-in
#associative array containing the complete error stack for a tango_io,
#tango_put and tango_get commands, generating an error - TANGO_ERR_STACK,
#sorted by keyword. %BR%
#Valid keywords are: "desc","origin", "reason" or "severity".
#If no keyword, "desc" will be printed.
def print_tango_err(keyword) '{
local i ii
if (keyword == "")
keyword = "desc"
for (i in TANGO_ERR_STACK) {
split(i,ii,"\034")
if (ii[1] == keyword)
printf ("%s\n", TANGO_ERR_STACK[ii[0]][keyword])
}
}
'
#%UU%
#%MDESC%Macro to show arbitrary values, e.g. used with savemot
#and savecnt(saveload.mac)
#Make sure the calling macro uses variable "i" as the looper
#and "k" as the limit.
def _mo_loop '{
local s
for (j = i, s = ""; j < i + 8 && j < k; j++) {
if (is_using_motor(mA[j])) {
s = s sprintf("%$1", $2)
if (j < i + 7)
s = s " "
}
}
print s
}
'
#%UU%
#%MDESC%print one value as hexadecimal
def px 'printf("%#x\n", $*)'
#%MACROS%
#%IMACROS%
#%AUTHOR%
#STLOCAL.MAC JK, with heavy modifications by HW for Spec release 6.00.07 with a
#revised standard.mac.
#%TOC%
#$Revision: 4.5 $, $Date: 2020/10/12 11:34:00 $
|