- Added code to read SANS TOF frames from a) files and b) from HM

- Fixed an bug causing core dumps on bad Tcl scripts
- Started on a syntax checker for SICS
This commit is contained in:
cvs
2003-03-14 16:14:31 +00:00
parent a858f25522
commit 1969980f0f
19 changed files with 700 additions and 27 deletions

View File

@ -59,7 +59,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \
polterwrite.o fourlib.o motreg.o motreglist.o anticollider.o \
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) ecb.o ecbdriv.o \
ecbcounter.o hmdata.o tdchm.o nxscript.o A1931.o
ecbcounter.o hmdata.o tdchm.o nxscript.o A1931.o frame.o
MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o
COUNTEROBJ = countdriv.o simcter.o counter.o

View File

@ -503,7 +503,7 @@
/* get size of our problem */
GetHistDim(self->pHM,iDim,&i3);
assert(i3 == 3);
/* assert(i3 == 3); */
/* allocate some data */
length = 2 + iDim[0]*iDim[1];
@ -546,7 +546,7 @@
iImage[i] = htonl(iImage[i]);
}
/*
printf("Collpased maximum: %d\n",iMax);
printf("Collapsed maximum: %d\n",iMax);
*/
if(status != 1)
{
@ -557,14 +557,15 @@
else
{
/*
we are in simulation and justcreate some random numbers
we are in simulation and just create some random numbers
*/
for(i = 0; i < iDim[0]; i++)
{
for(i2 = 0; i2 < iDim[1]; i2++)
{
iIdx = i*iDim[1] + i2;
iImage[iIdx+2] = htonl(random());
iImage[iIdx+2] = htonl(random());
/* iImage[iIdx+2] = htonl(77);*/
}
}
}

View File

@ -185,18 +185,17 @@ Motor COX SIM -100. 100. .1 2. # counter x
ClientPut "Motors initialized"
#======================== histogram memory
MakeHM hm SinqHM
#MakeHM hm SIM
#MakeHM hm SinqHM
MakeHM hm SIM
hm configure OverFlowMode Ceil
hm configure HistMode PSD
hm configure Rank 1
hm configure Rank 2
hm configure dim0 256
hm configure dim1 256
hm configure xfac 10
hm configure yfac 10
hm configure xoff 128
hm configure yoff 128
hm configure Length 65536
hm configure BinWidth 4
hm preset 100.
hm CountMode Timer

View File

@ -37,10 +37,29 @@
static pCircular pTail = NULL;
#define MAXTAIL 1000
/*----------------------------------------------------------------------*/
void WriteToCommandLog(char *prompt,char *pText)
void WriteToCommandLog(char *prompt,char *text)
{
int iNL = 0, iPos;
char *pPtr = NULL;
char *pPtr = NULL, *pCopy = NULL, *pText = NULL;
char myBuffer[1024];
/*
we change the text, so we need to make a local copy. A copy
is dynamically allocated only if it does not fit into
myBuffer.
*/
if(strlen(text) > 1023){
pCopy = (char *)malloc((strlen(text)+2)*sizeof(char));
if(pCopy == NULL){
return;
}
memset(pCopy,0,(strlen(text)+2)*sizeof(char));
strcpy(pCopy,text);
pText = pCopy;
} else {
strcpy(myBuffer,text);
pText = myBuffer;
}
/* figure out if we have to do a newline with pText as well */
pPtr = strrchr(pText,'\n');
@ -56,6 +75,9 @@
/* supress status messages */
if(strstr(pText,"status =") != NULL)
{
if(pCopy != NULL){
free(pCopy);
}
return;
}
@ -64,6 +86,9 @@
*/
if(strstr(pText,"TRANSACTIONFINISHED") != NULL)
{
if(pCopy != NULL){
free(pCopy);
}
return;
}
@ -108,6 +133,9 @@
setCircular(pTail,strdup(pText));
nextCircular(pTail);
}
if(pCopy != NULL){
free(pCopy);
}
}
/*------------------------------------------------------------------------*/
static void PrintTail(int iNum, SConnection *pCon)

View File

@ -22,6 +22,9 @@
Added compressed writing method.
Mark Koennecke, October 2000
Added simulation mode
Mark Koennecke, March 2003
Copyright: see copyright.h
-----------------------------------------------------------------------------*/
#include "fortify.h"
@ -1169,7 +1172,8 @@ void SCSetWriteFunc(SConnection *self, writeFunc x)
}
if(pCon->iGrab)
{
sprintf(pBueffel,"ERROR: Request refused, control has been grabbed by somebody else");
sprintf(pBueffel,
"ERROR: Request refused, control has been grabbed by somebody else");
SCWrite(pCon,pBueffel,eError);
return 0;
}
@ -1390,7 +1394,7 @@ void SCSetWriteFunc(SConnection *self, writeFunc x)
SCWrite(pCon,pBueffel,eValue);
return 1;
}
/* check no or args */
if(argc < 3)
{

View File

@ -113,7 +113,9 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
int SCMatchRights(SConnection *pCon, int iCode);
int SCGetOutClass(SConnection *self);
int SCGetGrab(SConnection *pCon);
/********************* simulation mode ************************************/
void SCSetSimMode(SConnection *pCon, int value);
int SCinSimMode(SConnection *pCon);
/* **************************** Invocation ******************************** */
int SCInvoke(SConnection *self,SicsInterp *pInter,char *pCommand);

View File

@ -162,7 +162,7 @@
{
pDevEntry pNew = NULL;
int iRet;
char pBueffel[132];
char pBueffel[132], pError[80];
pIDrivable pDrivInt = NULL;
pICountable pCountInt = NULL;
@ -199,16 +199,16 @@
return 0;
}
/* start it */
/* start it */
pDrivInt = pDes->GetInterface(pData,DRIVEID);
pCountInt = pDes->GetInterface(pData,COUNTID);
if(pDrivInt)
{
iRet = pDrivInt->SetValue(pData,pCon,fNew);
iRet = pDrivInt->SetValue(pData,pCon,fNew);
}
else if(pCountInt)
{
iRet = pCountInt->StartCount(pData,pCon);
iRet = pCountInt->StartCount(pData,pCon);
}
else
{ /* this is a programmers error */
@ -356,6 +356,9 @@
return 1;
}
/*
check the status of all registered devices. Remove when finished
*/
iRet = LLDnodePtr2First(self->iList);
while(iRet != 0)
{

239
frame.c Normal file
View File

@ -0,0 +1,239 @@
/*-------------------------------------------------------------------------
A module implementing functionality for reading single time frames
from PSD time-of-flight datasets. This can be done either from
SINQHM histogram memories or from old data files visible from the
SICS server. The result is sent to the demanding client in UUencoded
format.
copyright: see file COPYRIGHT
Mark Koennecke, February-March 2003
---------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "fortify.h"
#include "sics.h"
#include "stringdict.h"
#include "counter.h"
#include "HistMem.h"
#include "HistMem.i"
#include "HistDriv.i"
#include "hardsup/sinqhm.h"
#include "sinqhmdriv.i"
#include "nxdict.h"
#include "frame.h"
/*======================================================================*/
static int readHMFrame(SConnection *pCon, pHistMem pHM, int nFrame){
HistInt *buffer = NULL;
int iDim[MAXDIM], rank, length, status, i;
pSINQHM pHist;
SinqHMDriv *pTata;
/*
find dimensions and allocate data
*/
GetHistDim(pHM,iDim,&rank);
if(rank < 2){
SCWrite(pCon,"ERROR: no PSD data present, cannot send frame",eError);
return 0;
}
length = iDim[0]*iDim[1];
buffer = (HistInt *)malloc((length + 2)*sizeof(HistInt));
if(!buffer){
SCWrite(pCon,"ERROR: out of memory in readHMFrame",eError);
return 0;
}
memset(buffer,0,(length+2)*sizeof(HistInt));
/*
first two values are dimensions
*/
buffer[0] = htonl(iDim[0]);
buffer[1] = htonl(iDim[1]);
if(isSINQHMDriv(pHM->pDriv) && rank == 3) {
/*
read from HM. The 5 is PROJECT__FRAME in Sinqhm_def.h
Again: be friendly: fix out of range frames
*/
if(nFrame < 0){
nFrame = 0;
}
if(nFrame >= iDim[2]){
nFrame = iDim[2]-1;
}
pTata = (SinqHMDriv *)pHM->pDriv->pPriv;
pHist = (pSINQHM)pTata->pMaster;
status = SINQHMProject(pHist, 5, 0, nFrame,
0, iDim[1], buffer+2,length*sizeof(HistInt));
if(status != 1){
SCWrite(pCon,"ERROR: SINQHM refused to deliver frame",eError);
free(buffer);
return 0;
}
} else {
/*
be friendly, just read the 2D data which is there
*/
status = GetHistogram(pHM,pCon,0,0,length,buffer+2,length*sizeof(HistInt));
if(!status){
free(buffer);
return status;
}
}
/*
enforce network byte order
*/
for(i = 0; i < length; i++){
buffer[i+2] = htonl(buffer[i+2]);
}
SCWriteUUencoded(pCon,"framedata", buffer,(length+2)*sizeof(HistInt));
free(buffer);
return 1;
}
/*=======================================================================*/
static int readFileFrame(SConnection *pCon,
char *file, char *dictFile,
char *alias, int nFrame){
int status, iDim[NX_MAXRANK], rank = 0, type = 0;
int iStart[3], iSize[3], length, i;
int *buffer = NULL;
NXhandle fileHandle;
NXdict dictHandle;
char error[512];
status = NXopen(file,NXACC_READ,&fileHandle);
if(status != NX_OK){
sprintf(error,"ERROR: failed to open %s", file);
SCWrite(pCon,error,eError);
return 0;
}
status = NXDinitfromfile(dictFile, &dictHandle);
if(status != NX_OK){
sprintf(error,"ERROR: failed to open dictionary %s", dictFile);
NXclose(&fileHandle);
SCWrite(pCon,error,eError);
return 0;
}
status = NXDopenalias(fileHandle,dictHandle,alias);
if(status != NX_OK){
sprintf(error,"ERROR: failed to open alias %s", alias);
NXclose(&fileHandle);
NXDclose(dictHandle,NULL);
SCWrite(pCon,error,eError);
return 0;
}
status = NXgetinfo(fileHandle,&rank,iDim,&type);
if(type != NX_INT32 && type != NX_UINT32)type = -1;
if(status != NX_OK || rank < 2 || type < 0 ){
sprintf(error,"ERROR: Dataset does not match!");
NXclose(&fileHandle);
NXDclose(dictHandle,NULL);
SCWrite(pCon,error,eError);
return 0;
}
/*
allocate space
*/
length = iDim[0]*iDim[1];
buffer = (int *)malloc((length+2)*sizeof(int));
if(!buffer){
NXclose(&fileHandle);
NXDclose(dictHandle,NULL);
SCWrite(pCon,"ERROR: out of memory in readFrameFromFile",eError);
return 0;
}
memset(buffer,0,(length+2)*sizeof(int));
/*
first two values: dimensions
*/
buffer[0] = htonl(iDim[0]);
buffer[1] = htonl(iDim[1]);
if(rank == 2){
/*
be friendly
*/
status = NXgetdata(fileHandle,buffer+2);
} else {
iStart[0] = iStart[1] = 0;
iStart[2] = nFrame;
iSize[0] = iDim[0];
iSize[1] = iDim[1];
iSize[2] = 1;
status = NXgetslab(fileHandle,buffer+2,iStart,iSize);
}
if(status != NX_OK){
NXclose(&fileHandle);
NXDclose(dictHandle,NULL);
free(buffer);
SCWrite(pCon,"ERROR: failed to read data",eError);
return 0;
}
/*
enforce network byte order
*/
for(i = 0; i < length; i++){
buffer[2+i] = htonl(buffer[2+i]);
}
SCWriteUUencoded(pCon,"framedata",buffer,(length+2)*sizeof(int));
NXclose(&fileHandle);
NXDclose(dictHandle,NULL);
free(buffer);
return 1;
}
/*=======================================================================*/
int PSDFrameAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){
pHistMem pHM;
int nFrame;
if(argc < 2){
SCWrite(pCon,"ERROR: Insufficient number of arguments to PSDFrame",
eError);
return 0;
}
strtolower(argv[1]);
if(strcmp(argv[1],"hm") == 0){
if(argc < 4){
SCWrite(pCon,"ERROR: Insufficient number of arguments to PSDFrame",
eError);
return 0;
}
pHM = (pHistMem)FindCommandData(pSics,argv[2],"HistMem");
if(pHM == NULL){
SCWrite(pCon,"ERROR: Did not find histogram memory",eError);
return 0;
}
nFrame = atoi(argv[3]);
return readHMFrame(pCon,pHM,nFrame);
} else if(strcmp(argv[1],"file") == 0){
if(argc < 6 ){
SCWrite(pCon,"ERROR: Insufficient number of arguments to PSDframe file",
eError);
return 0;
}
nFrame = atoi(argv[5]);
return readFileFrame(pCon,argv[2],argv[3],argv[4],nFrame);
} else {
SCWrite(pCon,"ERROR: subcommand to PSDframe not recognised",eError);
return 0;
}
}
/*======================================================================*/
int MakeFrameFunc(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){
return AddCommand(pSics,"PSDframe",PSDFrameAction,NULL,NULL);
}

22
frame.h Normal file
View File

@ -0,0 +1,22 @@
/*-------------------------------------------------------------------------
A module implementing functionality for reading single time frames
from PSD time-of-flight datasets. This can be done either from
SINQHM histogram memories or from old data files visible from the
SICS server.
copyright: see file COPYRIGHT
Mark Koennecke, February-March 2003
*/
#ifndef SICSFRAME
#define SICSFRAME
int MakeFrameFunc(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int PSDFrameAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
#endif

32
frame.w Normal file
View File

@ -0,0 +1,32 @@
\subsection{Frame}
This module allows to retrieve data frames from a 3D histogram (PSD plus
time dimension). This can be done either from a Sinq histogram memory
and old data files visible from the SICS server.
This module has no data structure and only implements the usual
interpreter interface functions.
@o frame.h @{
/*-------------------------------------------------------------------------
A module implementing functionality for reading single time frames
from PSD time-of-flight datasets. This can be done either from
SINQHM histogram memories or from old data files visible from the
SICS server.
copyright: see file COPYRIGHT
Mark Koennecke, February-March 2003
*/
#ifndef SICSFRAME
#define SICSFRAME
int MakeFrameFunc(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int PSDFrameAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
#endif
@}

View File

@ -438,8 +438,9 @@
SCWrite(pCon,pTcl->result,eError);
}
pCom = Tcl_DStringValue(&command);
sprintf(pBueffel,"ERROR: in Tcl line: %s",pCom);
SCWrite(pCon,pBueffel,eError);
SCWrite(pCon,"ERROR: in Tcl block:",eError);
SCWrite(pCon,pCom,eError);
SCWrite(pCon,"ERROR: end of Tcl error block",eError);
}
else /* SICS error */
{

View File

@ -494,6 +494,7 @@ extern VerifyChannel(mkChannel *self); /* defined in network.c */
case '\r':
case '\n':
iStat = CostaTop(pItem->pCon->pStack,pItem->pHold);
/* printf("%s\n",pItem->pHold); */
if(!iStat)
{
SCWrite(pItem->pCon,"ERROR: Busy",eError);

View File

@ -726,12 +726,8 @@
NXclosedata(Nfil);
/* histogram Length */
iStat = HistGetOption(pHist,"Length",pBuffer,131);
if(!iStat)
{
return 0;
}
iVal = atoi(pBuffer);
GetHistDim(pHist,iDim,&iVal);
iVal = iDim[0];
if(iVal < 1)
{
return 0;
@ -831,6 +827,10 @@
SNputdata1att(Nfil,"sample_mur",NX_FLOAT32, 1,&pVar->fVal,
"Units","???");
}
/* do a3 */
SNPutMotor(Nfil,pSics,pCon,"a3",
"sample_table_rotation","degree");
/* write sample environment here */
pCom = FindCommand(pSics,"temperature");
if(pCom)

3
ofac.c
View File

@ -111,6 +111,7 @@
#include "gpibcontroller.h"
#include "ecb.h"
#include "nxscript.h"
#include "frame.h"
/*----------------------- Server options creation -------------------------*/
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
@ -297,6 +298,7 @@
AddCommand(pInter,"MakeGPIB",MakeGPIB,NULL,NULL);
AddCommand(pInter,"MakeECB",MakeECB,NULL,NULL);
AddCommand(pInter,"MakeNXScript",MakeNXScript,NULL,NULL);
AddCommand(pInter,"MakePSDFrame",MakeFrameFunc,NULL,NULL);
}
/*---------------------------------------------------------------------------*/
static void KillIniCommands(SicsInterp *pSics)
@ -360,6 +362,7 @@
RemoveCommand(pSics,"MakeGPIB");
RemoveCommand(pSics,"MakeECB");
RemoveCommand(pSics,"MakeNXScript");
RemoveCommand(pSics,"MakePSDFrame");
}

View File

@ -118,6 +118,9 @@
#define PROJECT__SAMPLE 0x0004 /* sum a rectangular part of the PSD
detector in time
*/
#define PROJECT__FRAME 0x0005 /* select a frame from a 3D histogram:
2 position dims plus time binning
*/
/*
** ----------------------------------------------------------
** Definition of bits in <flag> of TOF edge-array

View File

@ -2203,6 +2203,80 @@ extern PART_ID sysHighMemPart;
exit (KER__BAD_VALUE);
}
}
/**
* --------------------------------------------------------------------------
* project_frame reads one time frame of a TOF or PSD histogram
*/
static int project_frame(int rw_skt, int pkt_size, int nx){
struct rply_buff_struct rply;
uint *buffer = NULL;
uchar *bufPtr;
int i, bytesToSend, nSend, bytesSent;
register union {
void *base;
uchar *ch;
usint *i2;
uint *i4;
} hm_pntr;
printf("PROJECT: Trying to retrieve time frame: %d\n", nx);
/*
check arguments
*/
if(nx < 0 || nx >= N_bins){
printf("PROJECT FRAME: bad time frame requested: 0 < %d < %d\n",
nx,N_bins);
rply_status_setup (&rply, KER__BAD_VALUE, 0, "Bad argument");
rply_status_send (rw_skt, &rply);
return OK;
}
/*
allocate space
*/
buffer = (uint *)malloc(N_hists*sizeof(uint));
if(!buffer){
printf ("\n\007 -- SQHM_PROJECT-FRAME: failed to get buffer!\n");
rply_status_setup_and_send (rw_skt, &rply, KER__BAD_ALLOC, 0,
"Failed to get buffer for projecting data");
return OK;
}
/*
fill buffer
FIX: This works only OK with 4 byte HM data.
*/
hm_pntr.i4 = Hist_base_addr;
for(i = 0; i < N_hists;i++){
buffer[i] = htonl(*(hm_pntr.i4 + (i*N_bins) + nx));
}
/*
build reply and send data
*/
rply.bigend = 0x12345678;
rply.u.project.n_bins = htonl(N_hists);
rply.u.project.bytes_per_bin = htonl(4);
rply.u.project.cnts_lo = 0;
rply.u.project.cnts_hi = 0;
rply_status_setup_and_send (rw_skt, &rply, KER__SUCCESS, 0, NULL);
bufPtr = (uchar *)buffer;
bytesToSend = N_hists*4;
while(bytesToSend > 0){
nSend = (bytesToSend > pkt_size) ? pkt_size : bytesToSend;
bytesSent = send(rw_skt,bufPtr,nSend,0);
if(bytesSent > 0){
bytesToSend -= bytesSent;
bufPtr += bytesSent;
} else {
return ERROR;
}
}
free(buffer);
return OK;
}
/*
**--------------------------------------------------------------------------*/
int do_project (
@ -2322,6 +2396,9 @@ extern PART_ID sysHighMemPart;
break;
/*-----------------------------------------------------------*/
case SQHM__TOF: /* Time-of-Flight Mode */
if( (sub_code & PROJECT__FRAME) == 0){
return project_frame(rw_skt,pkt_size,nx);
}
if ((sub_code & PROJECT__1_DIM) != 0) {
printf ("\n\007%s -- SQHM_PROJECT: SQHM__TOF+PROJECT__1_DIM not yet "
@ -2389,6 +2466,10 @@ extern PART_ID sysHighMemPart;
/*
** code for TRICS, AMOR PSD
*/
if( (sub_code & PROJECT__FRAME) == 0){
return project_frame(rw_skt,pkt_size,nx);
}
if(sub_code == PROJECT__COLL){
my_nbins = psdXSize * psdYSize;
nTime = Tof_edges[0]->n_bins;

View File

@ -78,7 +78,7 @@
SCWrite(pCon,"Continuing here seriously compromises hacker's ethics",eError);
SCWrite(pCon,"You will NOT find valuable data here!",eError);
SCWrite(pCon,"The SICS server does NOT allow you to spawn to the system",eError);
SCWrite(pCon,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",eError);
SCWrite(pCon,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",eError);
}
/*-------------------------------------------------------------------------*/
static void SendGA(SConnection *pCon)

View File

@ -0,0 +1,86 @@
\documentclass[12pt,a4paper]{article}
%%\usepackage[dvips]{graphics}
%%\usepackage{epsf}
\setlength{\textheight}{24cm}
\setlength{\textwidth}{16cm}
\setlength{\headheight}{0cm}
\setlength{\headsep}{0cm}
\setlength{\topmargin}{0cm}
\setlength{\oddsidemargin}{0cm}
\setlength{\evensidemargin}{0cm}
\setlength{\hoffset}{0cm}
\setlength{\marginparwidth}{0cm}
\begin{document}
\begin{center}
\begin{Large}
SICS Syntax Checker\\
Implementation Notes\\
\end{Large}
Mark K\"onnecke\\
Mark.Koennecke@psi.ch\\
March/April 2003\\
Laboratory for Neutron Scattering\\
Paul Scherrer Institute\\
CH--5232 Villigen--PSI
Switzerland
\end{center}
Users wish to check their batch files for syntax errors before
submitting them to SICS for the weekend or the night. Unfortunately
checking SICS syntax is not so easy as it consists of Tcl syntax plus
SICS commands. In order to implement a syntax checker various
possibilities exist:\begin{itemize}
\item Implement the syntax checker as a calculation mode within
SICS. This has the disadvantage that the syntax check can only be run
by one person and only when the SICS server is not performing an
experiment. This is due to the fact, that SICS has only one set of
variables which may be changed dureing the syntax check. In order to
prevent corruption the security measures stated above are necessary.
\item Use a SICServer with simulated hardware. This would
work. Problems are that this is very time consuming to set up and the
synchronisation of parameter values with the main SICServer. This has
been solved through the sync command and thus this option is available
for complex scripts.
\item Use a Tcl interpreter with dummy SICS commands as a syntax
checker. In many cases batch files are fairly simple and a complete
simulation is not needed. The such a option would be sufficient.
\end{itemize}
\end{document}
\section{The Tcl Syntax Checker}
This section describes the syntax checker built from a Tcl interpreter
with dummy routines testing SICS syntax. The dummy procedures only
have to test the syntax and else do nothing. Not many such proecdures
have to be implemented but a means is needed for mapping names, for
instance motor names, to a suitable procedure for checking the syntax.
This syntax checker can be used in a variety of situations:
\begin{itemize}
\item Standalone: the preferred mode of operation
\item Within SICS: SICS would need to have a second Tcl interpreter
for this purpose in order to prevent corruption of the main
interpreter. Even then a rogue script could go into an endless loop
and thus hang the SICS server. Thus this second interpreter would have
to run as a separate process or thread.
\item This syntax checker could also help debugging SICS scripts.
\end{itemize}
For each instrument two files are needed for this syntax checker. The
first is a common library file which implements the syntax checking
procedures and the sics_alias procedure which maps names to
procedures. The second is a mapping file which defines the instrument
and enables those names the instrument provides. This is much like the
instrument initialization file for the main SICS program.
In order to help in script debugging, a global array with parameter
values defined through the user script will be maintained.
In a latter stage a connection to the main SICS could be added to the
system. Through this connection the actual configuration of the
instrument could be queried. Also parameter values can be updated in
order to help in debugging sophisticated scripts. Moreover this
connection could be used to check limit violations.

View File

@ -0,0 +1,168 @@
#-----------------------------------------------------------------------------
# This is the library file for the Tcl syntax checker for SICS commands.
# The basic idea is this:
# - SICS commands are replaced by Tcl procedures with the same name which
# implement the actual syntax check for this command.
# - As many SICS commands are object commands a facility is needed to map
# syntax checking procedures to names.
#
# copyright: see file COPYRIGHT
#
# Mark Koennecke, March 2003
#---------------------------------------------------------------------------
# sicsSyntaxMap maps the procedure syntaxProc to the name name. The name
# is prepended to the argument list in order to make the name available
# in the syntax checking procedure as the first argument
# This means syntax check procedures have two arguments:
# - the name
# - the list of remaining parameters as a string. Use syntaxListify
# to convert the list to a proper list for further processing
#---------------------------------------------------------------------------
proc sicsSyntaxMap {name syntaxProc} {
append newProc "proc " $name " args " \{ $syntaxProc " "
append newProc $name " " "\$args" \}
eval $newProc
}
#--------------------------------------------------------------------------
# a helper procedure which tests a value if it is numeric
#--------------------------------------------------------------------------
proc syntaxNumeric {val} {
set ret [catch {expr $val *1.} msg]
if { $ret == 0} {
return 1
} else {
return 0
}
}
#--------------------------------------------------------------------------
# a helper procedure which converts a stringified list back into a proper
# list
#--------------------------------------------------------------------------
proc syntaxListify {uff} {
set l [string trim $uff "{}"]
return [split $l]
}
#--------------------------------------------------------------------------
# a helper procedure which gets a parameter from the global parameter
# array or replaces it by the default 77 if it does not exist
#-------------------------------------------------------------------------
proc syntaxGet {name} {
global sicsPar
if { [info exists sicsPar($name)] == 1} {
return [format "%s = %s" $name \
$sicsPar($name)]
} else {
return [format " %s = 77" $name]
}
}
#------------------------------------------------------------------------
# syntaxCounterMode tests if par is a valid counter mode
#-----------------------------------------------------------------------
proc syntaxCounterMode {par} {
set p [string trim [string tolower $par]]
switch $p{
monitor { return 1}
timer {return 1}
default { return 0}
}
}
#---------------------------------------------------------------------------
# syntaxDummy is a syntax checking procedure which does nothing. This is a
# quick fix for SICS commands for which no syntax checking procedure has yet
# been defined.
#-------------------------------------------------------------------------
proc syntaxDummy {name args} {
set args [syntaxListify $args]
return
}
#-----------------------------------------------------------------------
# syntaxTextPar is a syntax handling procedure for simple text variables
#----------------------------------------------------------------------
proc syntaxTextPar {name args} {
global sicsPar
set args [syntaxListify $args]
if { [llength $args] > 0} {
set sicsPar($name) [join $args]
} else {
if { [info exists sicsPar($name)] == 1} {
return [format "%s = %s" $name \
$sicsPar($name)]
} else {
return [format " %s = UNKNOWN" $name]
}
}
}
#------------------------------------------------------------------------
# syntaxNumPar is a syntax handling procedure for a numeric variable
#-----------------------------------------------------------------------
proc syntaxNumPar {name args} {
global sicsPar
set args [syntaxListify $args]
if { [llength $args] > 0} {
if { [syntaxNumeric [lindex $args 0]] == 1} {
set sicsPar($name) [lindex $args 0]
} else {
error [format \
"ERROR: expected numeric argument for %s, received: %s" \
$name [lindex $args 0]]
}
} else {
return [syntaxGet $name]
}
}
#--------------------------------------------------------------------------
# syntaxMotor handles the syntax for a SICS motor
#-------------------------------------------------------------------------
lappend motSubKey list reset interest uninterest position hardposition
lappend motSub hardlowerlim hardupperlim softlowerlim
lappend motSub softupperlim softzero fixed interruptmode precision
lappend motSub accessmode sign failafter
proc syntaxMotor {name args} {
global sicsPar motSub motSubKey
set args [syntaxListify $args]
#----- value request
if { [llength $args] == 0} {
return [syntaxGet $name]
}
#---------- keywords
set subcommand [string tolower [lindex $args 0]]
if { [lsearch $motSubKey $subcommand] >= 0} {
return
}
#---------- parameters
if { [lsearch $motSub $subcommand] < 0} {
error [format "ERROR: motor %s does not know subcommand %s" \
$name $subcommand]
} else {
if { [llength $args] > 1 } {
set val [lindex $args 1]
if { [syntaxNumeric $val] == 0 } {
error [format "ERROR: %s.%s expected number, received %s" \
$name $subcommand $val]
} else {
set sicsPar($name.$subcommand) $val
}
} else {
return [syntaxGet $name.$subcommand]
}
}
}
#---------------------------------------------------------------------------
# syntaxCounter deals with the syntax for a single counter
#---------------------------------------------------------------------------
proc syntaxCounter {name args} {
global sicsPar motSub motSubKey
set args [syntaxListify $args]
if { [llength $args == 0} {
error [format "ERROR: subcommand expected to %s" $name]
}
#--------- get command
set subcommand [string trim [string tolower [lindex $args 0]]]
switch $subcommand {
}
}