- Fixed a couple of small things with the TAS code
- Fixed new AMOR settings module - Initial implementation of the new SICS hierarchical parameter database SKIPPED: psi/amorset.c psi/libpsi.a psi/sps.c
This commit is contained in:
22
access.c
22
access.c
@ -3,8 +3,9 @@
|
||||
|
||||
Mark Koennecke, November 1996
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef PCODE
|
||||
#define PCODE
|
||||
#include <string.h>
|
||||
#include <sics.h>
|
||||
#include <splitter.h>
|
||||
|
||||
static char *aCode[] = {
|
||||
"internal",
|
||||
@ -13,4 +14,19 @@
|
||||
"spy",
|
||||
NULL };
|
||||
static int iCodes = 4;
|
||||
#endif
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int decodeSICSPriv(char *privText){
|
||||
int code = 0;
|
||||
|
||||
strtolower(privText);
|
||||
while(aCode[code] != NULL){
|
||||
if(strcmp(aCode[code], privText) == 0){
|
||||
return code;
|
||||
}
|
||||
code++;
|
||||
}
|
||||
if(code >= iCodes){
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
11
conman.c
11
conman.c
@ -65,6 +65,7 @@
|
||||
#include "uubuffer.h"
|
||||
#include "commandlog.h"
|
||||
#include "stptok.h"
|
||||
#include "sicshipadaba.h"
|
||||
|
||||
/*
|
||||
#define UUDEB 1
|
||||
@ -361,6 +362,7 @@ extern pServer pServ;
|
||||
char pBueffel[132];
|
||||
SConnection *pVictim = NULL;
|
||||
Item sItem;
|
||||
pHdb root = NULL;
|
||||
|
||||
pVictim = (SConnection *)pData;
|
||||
if(!VerifyConnection(pVictim))
|
||||
@ -388,6 +390,15 @@ extern pServer pServ;
|
||||
*/
|
||||
KillCapture(pVictim);
|
||||
|
||||
/*
|
||||
* remove any callbacks which might still be active in the Hipadaba
|
||||
*/
|
||||
root = GetHipadabaRoot();
|
||||
if(root != NULL)
|
||||
{
|
||||
InternalRemoveHipadabaCallback(root,pVictim->ident);
|
||||
}
|
||||
|
||||
/*
|
||||
If we have a grab, release it !
|
||||
*/
|
||||
|
@ -65,6 +65,9 @@ file.
|
||||
<dt>updateintervall
|
||||
<dd>The time intervall in seconds between updates. The defualt is
|
||||
1200, eg. 20 minutes.
|
||||
<dt>onoff
|
||||
<dd>can be 1 or 0. Switches automatic updates on or off. It might be usefule for
|
||||
scans to switch this off.
|
||||
</dl>
|
||||
</p>
|
||||
</BODY>
|
||||
|
@ -553,8 +553,6 @@ static int putSum(SicsInterp *pSics, SConnection *pCon,
|
||||
HistInt *sum = NULL;
|
||||
int iDet, iTime, i, j, iIndex, status;
|
||||
|
||||
return 1;
|
||||
|
||||
iTime = getFMdim(TIMEBIN);
|
||||
if(strcmp(name,"upper") == 0)
|
||||
{
|
||||
@ -607,8 +605,6 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
||||
pHistMem pMem = NULL;
|
||||
float fCenter, fFWHM, fStdDev, fVal;
|
||||
|
||||
return 1;
|
||||
|
||||
pMem = (pHistMem)FindCommandData(pSics,"hm2","HistMem");
|
||||
if(pMem == NULL)
|
||||
{
|
||||
|
788
hipadaba.c
Normal file
788
hipadaba.c
Normal file
@ -0,0 +1,788 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
The hierarchical parameter database code. For more information, see
|
||||
hipadaba.h
|
||||
|
||||
copyright: GPL
|
||||
|
||||
Mark Koennecke, June 2006
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include "hipadaba.h"
|
||||
|
||||
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||
#define HDBMAGICK 77119900
|
||||
/*================== internal functions ===================================*/
|
||||
void DeleteCallbackChain(pHdbCallback root){
|
||||
pHdbCallback current = NULL, thisEntry;
|
||||
|
||||
current = root;
|
||||
while(current != NULL){
|
||||
if(current->killFunc != NULL){
|
||||
current->killFunc(current->userData);
|
||||
}
|
||||
thisEntry = current;
|
||||
current = (pHdbCallback)current->next;
|
||||
free(thisEntry);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void DeleteNodeData(pHdb node){
|
||||
pHdb tmp = NULL;
|
||||
|
||||
if(node == NULL){
|
||||
return;
|
||||
}
|
||||
DeleteCallbackChain(node->writeCallbacks);
|
||||
DeleteCallbackChain(node->updateCallbacks);
|
||||
DeleteCallbackChain(node->readCallbacks);
|
||||
|
||||
if(node->name != NULL){
|
||||
free(node->name);
|
||||
}
|
||||
ReleaseHdbValue(&node->value);
|
||||
node->magic = 000000;
|
||||
|
||||
while(node->child != NULL){
|
||||
tmp = node->child;
|
||||
node->child = node->child->next;
|
||||
DeleteNodeData(tmp);
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void RemoveHdbNodeFromParent(pHdb node){
|
||||
pHdb parent = NULL;
|
||||
pHdb current = NULL;
|
||||
|
||||
parent = node->mama;
|
||||
if(parent != NULL){
|
||||
if(parent->child == node){
|
||||
parent->child = node->next;
|
||||
return;
|
||||
}
|
||||
current = parent->child;
|
||||
while(current->next != node){
|
||||
current = current->next;
|
||||
}
|
||||
current->next = current->next->next;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void RemoveCallbackNode(pHdbCallback victim){
|
||||
if(victim->previous != NULL) {
|
||||
victim->previous->next = victim->next;
|
||||
}
|
||||
if(victim->next != NULL){
|
||||
victim->next->previous = victim->previous;
|
||||
}
|
||||
if(victim->killFunc != NULL){
|
||||
victim->killFunc(victim->userData);
|
||||
}
|
||||
free(victim);
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
* This code is ugly: the problem is fixing up the start of the chain.
|
||||
* Think about it and improve
|
||||
* ----------------------------------------------------------------------*/
|
||||
static pHdbCallback DeleteForID(pHdbCallback root, int id){
|
||||
pHdbCallback current = root;
|
||||
pHdbCallback tmp = NULL;
|
||||
pHdbCallback result = NULL;
|
||||
|
||||
if(root == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete at the start of the chain
|
||||
*/
|
||||
result = root;
|
||||
while(result->id == id){
|
||||
tmp = result;
|
||||
result = result->next;
|
||||
RemoveCallbackNode(tmp);
|
||||
if(result == NULL){
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* delete nodes in the middle of the chain
|
||||
*/
|
||||
current = result;
|
||||
while(current != NULL){
|
||||
if(current->id == id){
|
||||
tmp = current;
|
||||
current = (pHdbCallback)current->next;
|
||||
RemoveCallbackNode(tmp);
|
||||
} else {
|
||||
current = (pHdbCallback)current->next;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static pHdbCallback DeleteForInternalID(pHdbCallback root, int id){
|
||||
pHdbCallback current = root;
|
||||
pHdbCallback tmp = NULL;
|
||||
pHdbCallback result = NULL;
|
||||
|
||||
if(root == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete at the start of the chain
|
||||
*/
|
||||
result = root;
|
||||
while(result->internalID == id){
|
||||
tmp = result;
|
||||
result = result->next;
|
||||
if(tmp->killFunc != NULL){
|
||||
tmp->killFunc(tmp->userData);
|
||||
}
|
||||
free(tmp);
|
||||
if(result == NULL){
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* delete nodes in the middle of the chain
|
||||
*/
|
||||
current = result;
|
||||
while(current != NULL){
|
||||
if(current->internalID == id){
|
||||
if(current->next != NULL){
|
||||
current->next->previous = current->previous;
|
||||
}
|
||||
if(current->previous != NULL){
|
||||
current->previous->next = current->next;
|
||||
}
|
||||
tmp = current;
|
||||
current = (pHdbCallback)current->next;
|
||||
if(tmp->killFunc != NULL){
|
||||
tmp->killFunc(tmp->userData);
|
||||
}
|
||||
free(tmp);
|
||||
} else {
|
||||
current = (pHdbCallback)current->next;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int InvokeCallbackChain(pHdbCallback root, pHdb node,
|
||||
void *callData, hdbValue v){
|
||||
pHdbCallback current = root;
|
||||
int status;
|
||||
|
||||
while(current != NULL){
|
||||
status = current->userCallback(current->userData,callData,
|
||||
node,v);
|
||||
if(status != 1){
|
||||
return status;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
char *hdbTrim(char *str)
|
||||
{
|
||||
char *ibuf = str, *obuf = str;
|
||||
int i = 0, cnt = 0;
|
||||
|
||||
/*
|
||||
** Trap NULL
|
||||
*/
|
||||
|
||||
if (str)
|
||||
{
|
||||
/*
|
||||
** Remove leading spaces (from RMLEAD.C)
|
||||
*/
|
||||
|
||||
for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf)
|
||||
;
|
||||
if (str != ibuf)
|
||||
memmove(str, ibuf, ibuf - str);
|
||||
|
||||
/*
|
||||
** Collapse embedded spaces (from LV1WS.C)
|
||||
*/
|
||||
|
||||
while (*ibuf)
|
||||
{
|
||||
if (isspace(*ibuf) && cnt)
|
||||
ibuf++;
|
||||
else
|
||||
{
|
||||
if (!isspace(*ibuf))
|
||||
cnt = 0;
|
||||
else
|
||||
{
|
||||
*ibuf = ' ';
|
||||
cnt = 1;
|
||||
}
|
||||
obuf[i++] = *ibuf++;
|
||||
}
|
||||
}
|
||||
obuf[i] = '\0';
|
||||
|
||||
/*
|
||||
** Remove trailing spaces (from RMTRAIL.C)
|
||||
*/
|
||||
|
||||
while (--i >= 0)
|
||||
{
|
||||
if (!isspace(obuf[i]))
|
||||
break;
|
||||
}
|
||||
obuf[++i] = '\0';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static pHdb locateChild(pHdb root, char *name){
|
||||
pHdb current = NULL;
|
||||
|
||||
current = root->child;
|
||||
while(current != NULL){
|
||||
if(strcmp(current->name,name) == 0){
|
||||
return current;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*================= data functions ========================================*/
|
||||
hdbValue makeHdbValue(int datatype, int length){
|
||||
hdbValue val;
|
||||
|
||||
memset(&val,0,sizeof(hdbValue));
|
||||
val.dataType = datatype;
|
||||
|
||||
switch(datatype){
|
||||
case HIPINTAR:
|
||||
val.arrayLength = length;
|
||||
val.v.intArray = malloc(length*sizeof(long));
|
||||
if(val.v.intArray != NULL){
|
||||
memset(val.v.intArray,0,length*sizeof(long));
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
val.arrayLength = length;
|
||||
val.v.floatArray = malloc(length*sizeof(double));
|
||||
if(val.v.floatArray != NULL){
|
||||
memset(val.v.floatArray,0,length*sizeof(double));
|
||||
}
|
||||
break;
|
||||
case HIPTEXT:
|
||||
val.v.text = strdup("UNKNOWN");
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
hdbValue MakeHdbInt(int initValue){
|
||||
hdbValue result;
|
||||
|
||||
result.dataType = HIPINT;
|
||||
result.v.intValue = initValue;
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
hdbValue MakeHdbFloat(double initValue){
|
||||
hdbValue result;
|
||||
|
||||
result.dataType = HIPFLOAT;
|
||||
result.v.doubleValue = initValue;
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
hdbValue MakeHdbText(char *initText){
|
||||
hdbValue result;
|
||||
|
||||
result.dataType = HIPTEXT;
|
||||
result.v.text = initText;
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
hdbValue MakeHdbIntArrray(int length, long *data){
|
||||
hdbValue result;
|
||||
|
||||
result.dataType = HIPINTAR;
|
||||
result.arrayLength = length;
|
||||
result.v.intArray = data;
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
hdbValue MakeHdbFloatArrray(int length, double *data){
|
||||
hdbValue result;
|
||||
|
||||
result.dataType = HIPFLOATAR;
|
||||
result.arrayLength = length;
|
||||
result.v.floatArray = data;
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void ReleaseHdbValue(hdbValue *v){
|
||||
switch(v->dataType){
|
||||
case HIPTEXT:
|
||||
if(v->v.text != NULL){
|
||||
free(v->v.text);
|
||||
}
|
||||
break;
|
||||
case HIPINTAR:
|
||||
if(v->v.intArray != NULL){
|
||||
free(v->v.intArray);
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
if(v->v.floatArray != NULL){
|
||||
free(v->v.floatArray);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int compareHdbValue(hdbValue v1, hdbValue v2){
|
||||
int i;
|
||||
|
||||
if(v1.dataType != v2.dataType){
|
||||
return 0;
|
||||
}
|
||||
switch(v1.dataType){
|
||||
case HIPNONE:
|
||||
return 0;
|
||||
break;
|
||||
case HIPINT:
|
||||
if(v1.v.intValue == v2.v.intValue){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case HIPFLOAT:
|
||||
if(ABS(v1.v.doubleValue - v2.v.doubleValue) < .01){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case HIPTEXT:
|
||||
if(strcmp(v1.v.text,v2.v.text) == 0){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case HIPINTAR:
|
||||
if(v1.arrayLength != v2.arrayLength){
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i < v1.arrayLength; i++){
|
||||
if(v1.v.intArray[i] != v2.v.intArray[i]){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
if(v1.arrayLength != v2.arrayLength){
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i < v1.arrayLength; i++){
|
||||
if(ABS(v1.v.floatArray[i] - v2.v.floatArray[i]) > .01){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int cloneHdbValue(hdbValue *source, hdbValue *clone){
|
||||
|
||||
memset(clone,0,sizeof(hdbValue));
|
||||
clone->dataType = source->dataType;
|
||||
return copyHdbValue(source, clone);
|
||||
}
|
||||
/*================= node functions ========================================*/
|
||||
pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
||||
pHdb pNew = NULL;
|
||||
|
||||
pNew = malloc(sizeof(Hdb));
|
||||
if(pNew == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(pNew,0,sizeof(Hdb));
|
||||
pNew->magic = HDBMAGICK;
|
||||
pNew->name = strdup(name);
|
||||
pNew->value.dataType = datatype;
|
||||
switch(datatype){
|
||||
case HIPINTAR:
|
||||
pNew->value.arrayLength = length;
|
||||
pNew->value.v.intArray = malloc(length*sizeof(long));
|
||||
if(pNew->value.v.intArray == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(pNew->value.v.intArray,0,length*sizeof(long));
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
pNew->value.arrayLength = length;
|
||||
pNew->value.v.floatArray = malloc(length*sizeof(double));
|
||||
if(pNew->value.v.floatArray == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(pNew->value.v.floatArray,0,length*sizeof(double));
|
||||
break;
|
||||
case HIPTEXT:
|
||||
pNew->value.v.text = strdup("UNKNOWN");
|
||||
break;
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void AddHipadabaChild(pHdb parent, pHdb child){
|
||||
pHdb current = NULL, prev = NULL;
|
||||
|
||||
assert(parent != NULL && child != NULL);
|
||||
|
||||
current = parent->child;
|
||||
child->mama = parent;
|
||||
if(current == NULL){
|
||||
parent->child = child;
|
||||
child->next = NULL;
|
||||
} else {
|
||||
/*
|
||||
* step to end of child chain
|
||||
*/
|
||||
while(current != NULL){
|
||||
prev = current;
|
||||
current = current->next;
|
||||
}
|
||||
child->next = NULL;
|
||||
prev->next = child;
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void DeleteHipadabaNode(pHdb node){
|
||||
pHdb current = NULL, tmp = NULL;
|
||||
|
||||
if(node == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveHdbNodeFromParent(node);
|
||||
|
||||
DeleteNodeData(node);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int isHdbNodeValid(pHdb node){
|
||||
if(node == NULL){
|
||||
return 0;
|
||||
}
|
||||
if(node->magic == HDBMAGICK){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pHdb GetHipadabaNode(pHdb root, char *path){
|
||||
pHdb resultNode = NULL;
|
||||
char *separator = NULL;
|
||||
|
||||
path = hdbTrim(path);
|
||||
|
||||
if(strcmp(path,"/") == 0 || strlen(path) == 0){
|
||||
return root;
|
||||
}
|
||||
|
||||
if(path[0] == '/'){
|
||||
path++;
|
||||
}
|
||||
|
||||
separator = strchr(path,'/');
|
||||
if(separator == NULL){
|
||||
return locateChild(root,path);
|
||||
} else {
|
||||
*separator = '\0';
|
||||
resultNode = locateChild(root, path);
|
||||
if(resultNode == NULL){
|
||||
return NULL;
|
||||
} else {
|
||||
separator++;
|
||||
return GetHipadabaNode(resultNode,separator);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char *GetHipadabaPath(pHdb node){
|
||||
pHdb nodeStack[64];
|
||||
int depth = 0, length = 0, i;
|
||||
pHdb current = NULL;
|
||||
char *pPtr = NULL;
|
||||
|
||||
/**
|
||||
* build a nodestack and find out required string length for path
|
||||
*/
|
||||
current = node;
|
||||
while(current != NULL){
|
||||
length += strlen(current->name) + 1;
|
||||
nodeStack[depth] = current;
|
||||
depth++;
|
||||
assert(depth < 64);
|
||||
current = current->mama;
|
||||
}
|
||||
|
||||
pPtr = malloc(length*sizeof(char));
|
||||
if(pPtr == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(pPtr,0,length*sizeof(char));
|
||||
|
||||
/*
|
||||
* we wish to decremement by one because above loop
|
||||
* increments one to many and we wish to ignore the
|
||||
* root node
|
||||
*/
|
||||
for(i = depth - 2; i >= 0; i--){
|
||||
strcat(pPtr,"/");
|
||||
strcat(pPtr,nodeStack[i]->name);
|
||||
}
|
||||
return pPtr;
|
||||
}
|
||||
/*==================== Callback Functions ==================================*/
|
||||
pHdbCallback MakeHipadabaCallback(hdbCallbackFunction func,
|
||||
void *userData, killUserData killFunc,
|
||||
int id, int internalID){
|
||||
pHdbCallback pNew = NULL;
|
||||
|
||||
assert(func != NULL);
|
||||
|
||||
pNew = malloc(sizeof(hdbCallback));
|
||||
if(pNew == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(pNew,0,sizeof(hdbCallback));
|
||||
|
||||
pNew->userCallback = func;
|
||||
pNew->userData = userData;
|
||||
pNew->killFunc = killFunc;
|
||||
pNew->id = id;
|
||||
pNew->internalID = internalID;
|
||||
return pNew;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
||||
pHdbCallback current = NULL;
|
||||
|
||||
switch(type){
|
||||
case HCBSET:
|
||||
if(node->writeCallbacks == NULL){
|
||||
node->writeCallbacks = newCB;
|
||||
return;
|
||||
} else {
|
||||
current = node->writeCallbacks;
|
||||
}
|
||||
break;
|
||||
case HCBUPDATE:
|
||||
if(node->updateCallbacks == NULL){
|
||||
node->updateCallbacks = newCB;
|
||||
return;
|
||||
} else {
|
||||
current = node->updateCallbacks;
|
||||
}
|
||||
break;
|
||||
case HCBREAD:
|
||||
if(node->readCallbacks == NULL){
|
||||
node->readCallbacks = newCB;
|
||||
return;
|
||||
} else {
|
||||
current = node->readCallbacks;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
if(current != NULL){
|
||||
while(current->next != NULL){
|
||||
current = (pHdbCallback)current->next;
|
||||
}
|
||||
current->next= newCB;
|
||||
newCB->previous = current;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
||||
switch(type){
|
||||
case HCBSET:
|
||||
if(node->writeCallbacks == NULL){
|
||||
node->writeCallbacks = newCB;
|
||||
return;
|
||||
} else {
|
||||
newCB->next = node->writeCallbacks;
|
||||
node->writeCallbacks->previous = newCB;
|
||||
node->writeCallbacks = newCB;
|
||||
}
|
||||
break;
|
||||
case HCBUPDATE:
|
||||
if(node->updateCallbacks == NULL){
|
||||
node->updateCallbacks = newCB;
|
||||
return;
|
||||
} else {
|
||||
newCB->next = node->updateCallbacks;
|
||||
node->updateCallbacks->previous = newCB;
|
||||
node->updateCallbacks = newCB;
|
||||
}
|
||||
break;
|
||||
case HCBREAD:
|
||||
if(node->readCallbacks == NULL){
|
||||
node->readCallbacks = newCB;
|
||||
return;
|
||||
} else {
|
||||
newCB->next = node->readCallbacks;
|
||||
node->readCallbacks->previous = newCB;
|
||||
node->readCallbacks = newCB;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void RemoveHipadabaCallback(pHdb root, int id){
|
||||
pHdb current = NULL;
|
||||
|
||||
root->writeCallbacks = DeleteForID(root->writeCallbacks,id);
|
||||
root->updateCallbacks = DeleteForID(root->updateCallbacks,id);
|
||||
root->readCallbacks = DeleteForID(root->readCallbacks,id);
|
||||
|
||||
current = root->child;
|
||||
while(current != NULL){
|
||||
RemoveHipadabaCallback(current,id);
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void InternalRemoveHipadabaCallback(pHdb root, int internalID){
|
||||
pHdb current = NULL;
|
||||
|
||||
root->writeCallbacks = DeleteForInternalID(root->writeCallbacks,internalID);
|
||||
root->updateCallbacks = DeleteForInternalID(root->updateCallbacks,internalID);
|
||||
root->readCallbacks = DeleteForInternalID(root->readCallbacks,internalID);
|
||||
|
||||
current = root->child;
|
||||
while(current != NULL){
|
||||
InternalRemoveHipadabaCallback(current,internalID);
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
/*=================== parameter interface ====================================*/
|
||||
int copyHdbValue(hdbValue *source, hdbValue *target){
|
||||
int i;
|
||||
|
||||
if(source->dataType != target->dataType){
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(source->dataType){
|
||||
case HIPNONE:
|
||||
break;
|
||||
case HIPINT:
|
||||
target->v.intValue = source->v.intValue;
|
||||
break;
|
||||
case HIPFLOAT:
|
||||
target->v.doubleValue = source->v.doubleValue;
|
||||
break;
|
||||
case HIPTEXT:
|
||||
if(target->v.text != NULL){
|
||||
free(target->v.text);
|
||||
}
|
||||
target->v.text = strdup(source->v.text);
|
||||
break;
|
||||
case HIPINTAR:
|
||||
if(target->arrayLength != source->arrayLength){
|
||||
if(target->v.intArray != NULL){
|
||||
free(target->v.intArray);
|
||||
}
|
||||
target->v.intArray = malloc(source->arrayLength * sizeof(long));
|
||||
if(target->v.intArray == NULL){
|
||||
return 0;
|
||||
}
|
||||
memset(target->v.intArray,0,source->arrayLength * sizeof(long));
|
||||
target->arrayLength = source->arrayLength;
|
||||
}
|
||||
for(i = 0; i < source->arrayLength; i++){
|
||||
target->v.intArray[i] = source->v.intArray[i];
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
if(target->arrayLength != source->arrayLength){
|
||||
if(target->v.floatArray != NULL){
|
||||
free(target->v.floatArray);
|
||||
}
|
||||
target->v.floatArray = malloc(source->arrayLength * sizeof(double));
|
||||
if(target->v.floatArray == NULL){
|
||||
return 0;
|
||||
}
|
||||
memset(target->v.floatArray,0,source->arrayLength * sizeof(double));
|
||||
target->arrayLength = source->arrayLength;
|
||||
}
|
||||
for(i = 0; i < source->arrayLength; i++){
|
||||
target->v.floatArray[i] = source->v.floatArray[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* unknown data type
|
||||
*/
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int SetHipadabaPar(pHdb node, hdbValue v, void *callData){
|
||||
int status;
|
||||
|
||||
status = InvokeCallbackChain(node->writeCallbacks, node, callData, v);
|
||||
return status;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData){
|
||||
int status;
|
||||
|
||||
status = InvokeCallbackChain(node->updateCallbacks, node, callData, v);
|
||||
if(status != 1 ){
|
||||
return status;
|
||||
}
|
||||
copyHdbValue(&v,&node->value);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){
|
||||
int status;
|
||||
|
||||
status = InvokeCallbackChain(node->readCallbacks, node, callData, *v);
|
||||
if(status != 1 ){
|
||||
return status;
|
||||
}
|
||||
v->dataType = node->value.dataType;
|
||||
copyHdbValue(&node->value,v);
|
||||
return 1;
|
||||
}
|
||||
|
266
hipadaba.h
Normal file
266
hipadaba.h
Normal file
@ -0,0 +1,266 @@
|
||||
/**
|
||||
* Hipadaba is a hierarchical database of parameters. Parameters can be of various types.
|
||||
* What happens when a parameter is being set, updated or read is largely determined
|
||||
* through callbacks which can be registered on parameters. This can implement permission
|
||||
* checking, range checking, automatic notifications and whatever comes up.
|
||||
*
|
||||
* There is some subtlety here between updating and setting a parameter. The issue is
|
||||
* that in instrument control there are two types of parameters: Instant program parameters
|
||||
* and external parameters like motors which are dependent on some possibly slow and
|
||||
* inaccurate hardware. Let us consider the latter: Setting the parameter should do all
|
||||
* necessary checks on the parameter and tell the hardware where to go. Some internal code
|
||||
* may be watching the hardware; that code should use Update which justs sets a new value
|
||||
* and invokes callbacks which notify interested parties about the new parameter value.
|
||||
* For program parameters, a callback shall be installed which calls update directly
|
||||
* after setting the parameter. Thus notification callbacks shall always be connected to the
|
||||
* update chain.
|
||||
*
|
||||
* copyright: GPL
|
||||
*
|
||||
* Mark Koennecke, June 2006
|
||||
*/
|
||||
#ifndef HIPADABA
|
||||
#define HIPADABA
|
||||
|
||||
/*------- datatypes */
|
||||
#define HIPNONE -1
|
||||
#define HIPINT 0
|
||||
#define HIPFLOAT 1
|
||||
#define HIPTEXT 2
|
||||
#define HIPINTAR 3
|
||||
#define HIPFLOATAR 4
|
||||
/* -------- callback types */
|
||||
#define HCBSET 0
|
||||
#define HCBUPDATE 1
|
||||
#define HCBREAD 2
|
||||
/*===================== structure definitions ===================================*/
|
||||
typedef struct __hdbValue {
|
||||
int dataType;
|
||||
int arrayLength;
|
||||
union __value {
|
||||
long intValue;
|
||||
double doubleValue;
|
||||
char *text;
|
||||
long *intArray;
|
||||
double *floatArray;
|
||||
}v;
|
||||
}hdbValue;
|
||||
/*------------------------------------------------------------------------------*/
|
||||
typedef struct __hipadaba {
|
||||
int magic;
|
||||
struct __hipadaba *mama;
|
||||
struct __hipadaba *child;
|
||||
struct __hipadaba *next;
|
||||
struct __hdbcallback *writeCallbacks;
|
||||
struct __hdbcallback *updateCallbacks;
|
||||
struct __hdbcallback *readCallbacks;
|
||||
char *name;
|
||||
hdbValue value;
|
||||
}Hdb, *pHdb;
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
typedef int (*hdbCallbackFunction)(void *userData, void *callData,
|
||||
pHdb currentNode, hdbValue v );
|
||||
typedef void (*killUserData)(void *data);
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
typedef struct __hdbcallback {
|
||||
void *userData;
|
||||
killUserData killFunc;
|
||||
hdbCallbackFunction userCallback;
|
||||
int id;
|
||||
int internalID;
|
||||
struct __hdbcallback *next;
|
||||
struct __hdbcallback *previous;
|
||||
}hdbCallback, *pHdbCallback;
|
||||
/*======================== Function protoypes: hdbData ========================*/
|
||||
hdbValue makeHdbValue(int datatype, int length);
|
||||
/**
|
||||
* wrap an integer as an hdbValue
|
||||
* @param initValue the initial value of the int
|
||||
* @return: A properly initialized hdbValue structure
|
||||
*/
|
||||
hdbValue MakeHdbInt(int initValue);
|
||||
/**
|
||||
* wrap a float as an hdbValue
|
||||
* @param initValue the initial value of the float
|
||||
* @return: A properly initialized hdbValue structure
|
||||
*/
|
||||
hdbValue MakeHdbFloat(double initValue);
|
||||
/**
|
||||
* wrap a text string as an hdbValue
|
||||
* @param initText the initial value of the text. WARNING: MakeHdbText does
|
||||
* not copy the data. The Hdb code only copies data on updates. Normally this
|
||||
* no problem; however in complicated cenarios it is better if initText points
|
||||
* to dynamically allocated memory.
|
||||
* @return: A properly initialized hdbValue structure
|
||||
*/
|
||||
hdbValue MakeHdbText(char *initText);
|
||||
/**
|
||||
* wrap a int array as an hdbValue
|
||||
* @param length The length of the int array
|
||||
* @param data the initial content of the int array. WARNING: MakeHdbIntArray
|
||||
* does not copy the data. The Hdb code only copies data on updates. Normally
|
||||
* this no problem; however in complicated scenarios it is better if
|
||||
* data points to dynamically allocated memory.
|
||||
* @return: A properly initialized hdbValue structure
|
||||
*/
|
||||
hdbValue MakeHdbIntArray(int length, long *data);
|
||||
/**
|
||||
* wrap a float array as an hdbValue
|
||||
* @param length The length of the int array
|
||||
* @param data the initial content of the float array. WARNING: MakeHdbFloatArray
|
||||
* does not copy the data. The Hdb code only copies data on updates. Normally
|
||||
* this no problem; however in complicated scenarios it is better if
|
||||
* data points to dynamically allocated memory.
|
||||
* @return: A properly initialized hdbValue structure
|
||||
*/
|
||||
hdbValue MakeHdbFloatArray(int length, double *data);
|
||||
/**
|
||||
* release any dynamic memory associated with v
|
||||
* @param v The hdbValue to check for dynamic memory allocation to be
|
||||
* released.
|
||||
*/
|
||||
void ReleaseHdbValue(hdbValue *v);
|
||||
/**
|
||||
* copy a hipadaba value field. Takes care of memory allocation
|
||||
* @param source The hdbValue to copy from
|
||||
* @param target The hdbValue to copy to.
|
||||
* @return 1 on success, 0 when out of memory or when type mismatch
|
||||
*/
|
||||
int copyHdbValue(hdbValue *source, hdbValue *target);
|
||||
/**
|
||||
* compares two hdbValues for identity
|
||||
* @param v1 The first hdbValue
|
||||
* @param v2 The second hdbValue
|
||||
* @return 1 when identical, 0 else
|
||||
*/
|
||||
int compareHdbValue(hdbValue v1, hdbValue v2);
|
||||
/**
|
||||
* create a hdbValue structure with the identical properties
|
||||
* as the one given as parameter. Datatypes are copied, memory is
|
||||
* allocated etc. Data is copied, too
|
||||
* @param source The hdbValue type to clone
|
||||
* @param clone the target hdbValue structure
|
||||
* @return 1 on success, 0 on when out of memory
|
||||
*/
|
||||
int cloneHdbValue(hdbValue *source, hdbValue *clone);
|
||||
/*========================== function protoypes: Nodes =======================*/
|
||||
/**
|
||||
* make a new hipadaba node
|
||||
* @param name The name of the new node
|
||||
* @param datatype The datatype of the new node
|
||||
* @return a new node or NULL when out of memory
|
||||
*/
|
||||
pHdb MakeHipadabaNode(char *name, int datatype, int length);
|
||||
/**
|
||||
* add a child to a node
|
||||
* @param parent The node to which to add the child
|
||||
* @param child The node to add
|
||||
*/
|
||||
void AddHipadabaChild(pHdb parent, pHdb child);
|
||||
/**
|
||||
* delete a hipadaba node and all its children
|
||||
* @parma node The node to delete
|
||||
*/
|
||||
void DeleteHipadabaNode(pHdb node);
|
||||
/*
|
||||
* checks if a Hdb node is valid
|
||||
* @param node The node to check
|
||||
* @return 1 when valid, 0 else
|
||||
*/
|
||||
int isHdbNodeValid(pHdb node);
|
||||
/**
|
||||
* retrieve a node
|
||||
* @param root The node where to start the search for the node
|
||||
* @param path The unix path string for the node relative to parent
|
||||
* @return The desired node or NULL when no such node exists
|
||||
*/
|
||||
pHdb GetHipadabaNode(pHdb root, char *path);
|
||||
/**
|
||||
* given a node, return the full path name to the node
|
||||
* @param node The node to get the path for
|
||||
* @return The full path to the node. This is dynamically allocated memory;
|
||||
* the caller is reponsible for deleting it. Can be NULL when out of memory.
|
||||
*/
|
||||
char *GetHipadabaPath(pHdb node);
|
||||
/**
|
||||
* removes a node from the parents child list.
|
||||
* @node the node to remove
|
||||
*/
|
||||
void RemoveHdbNodeFromParent(pHdb node);
|
||||
/**
|
||||
* delete a callback chain
|
||||
* @param root The callback chain to delete
|
||||
*/
|
||||
void DeleteCallbackChain(pHdbCallback root);
|
||||
/*===================== function protoypes: Callbacks ========================*/
|
||||
/**
|
||||
* make a new hipdaba callback
|
||||
* @param func The function to invoke for this callback
|
||||
* @param userData userData to be associated with this callback. Can be NULL.
|
||||
* @param killFunc A function for freeing the userData. Can be NULL, then it will
|
||||
* not be invoked
|
||||
* @param id An ID associated with this callback
|
||||
* @param internalID Another ID to be associated with this callback. ID's come in
|
||||
* useful when callbacks have to be deleted in a later stage.
|
||||
* @return A new suitabvly initialised callback structure or NULL when required elements
|
||||
* are missing or there is nor memory.
|
||||
*/
|
||||
pHdbCallback MakeHipadabaCallback(hdbCallbackFunction func,
|
||||
void *userData, killUserData killFunc,
|
||||
int id, int internalID);
|
||||
/**
|
||||
* add a callback at the end of the callback chain
|
||||
* @param node The node to which to append the callback
|
||||
* @param type the type of the callback to append
|
||||
* @param newCB The callback to append
|
||||
*/
|
||||
void AppendHipadabaCallback(pHdb node,int type, pHdbCallback newCB);
|
||||
/**
|
||||
* add a callback at the head of the callback chain
|
||||
* @param node The node to which to append the callback
|
||||
* @param type the type of the callback to append
|
||||
* @param newCB The callback prepend
|
||||
*/
|
||||
void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB);
|
||||
/**
|
||||
* remove recursively all callbacks witch match the id
|
||||
* @param root The starting node from where to start removing callbacks
|
||||
* @param id The ID callbacks have to match in order to be removed.
|
||||
*/
|
||||
void RemoveHipadabaCallback(pHdb root, int id);
|
||||
/**
|
||||
* remove recursively all callbacks witch match the internal id
|
||||
* @param root The starting node from where to start removing callbacks
|
||||
* @param internalID The internal ID callbacks have to match in order to be removed.
|
||||
*/
|
||||
void InternalRemoveHipadabaCallback(pHdb root, int internalID);
|
||||
|
||||
/*============== Parameter Handling ===============================*/
|
||||
/**
|
||||
* Set a hipadaba parameter. This is an external set for a parameter. It may cause
|
||||
* motors to start driving etc.
|
||||
* @param node The node for which to set the parameter
|
||||
* @param v The new value for the node
|
||||
* @param callData Additonal context data to be passed to the callback functions
|
||||
* @return 0 on failure, 1 on success
|
||||
*/
|
||||
int SetHipadabaPar(pHdb node, hdbValue v, void *callData);
|
||||
/**
|
||||
* Update a hipadaba parameter. This is an internal update of a parameter, during
|
||||
* driving etc.
|
||||
* @param node The node for which to update the parameter
|
||||
* @param v The new value for the node
|
||||
* @param callData Additonal context data to be passed to the callback functions
|
||||
* @return 0 on failure, 1 on success
|
||||
*/
|
||||
int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData);
|
||||
/**
|
||||
* Read a hipadaba parameter
|
||||
* @param node The node for which to read the parameter
|
||||
* @param v The read value for the node
|
||||
* @param callData Additonal context data to be passed to the callback functions
|
||||
* @return 0 on failure, 1 on success
|
||||
*/
|
||||
int GetHipadabaPar(pHdb node, hdbValue *v, void *callData);
|
||||
|
||||
#endif
|
21
macro.c
21
macro.c
@ -61,11 +61,9 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <tcl.h>
|
||||
#include "SCinter.h"
|
||||
#include "conman.h"
|
||||
#include "macro.h"
|
||||
#include <sics.h>
|
||||
#include "status.h"
|
||||
#include "obdes.h"
|
||||
#include "macro.h"
|
||||
#include "splitter.h"
|
||||
#include "ifile.h"
|
||||
#include "Dbg.h"
|
||||
@ -914,8 +912,6 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
}
|
||||
return 1; /* not reached */
|
||||
}
|
||||
|
||||
#include "access.c"
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TclPublish(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
@ -943,17 +939,8 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
}
|
||||
|
||||
/* try convert last parameter to user code */
|
||||
iUser = 0;
|
||||
strtolower(argv[2]);
|
||||
while(aCode[iUser] != NULL)
|
||||
{
|
||||
if(strcmp(aCode[iUser],argv[2]) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
iUser++;
|
||||
}
|
||||
if(iUser > iCodes)
|
||||
iUser = decodeSICSPriv(argv[2]);
|
||||
if(iUser < 0)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot identify %s as a valid user code",
|
||||
argv[2]);
|
||||
|
4
make_gen
4
make_gen
@ -8,7 +8,7 @@
|
||||
COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ)
|
||||
SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
servlog.o sicvar.o nserver.o SICSmain.o motorlist.o\
|
||||
sicsexit.o costa.o task.o $(FORTIFYOBJ)\
|
||||
sicsexit.o costa.o task.o $(FORTIFYOBJ) access.o\
|
||||
macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \
|
||||
devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \
|
||||
lld_blob.o strrepl.o lin2ang.o fomerge.o napi4.o napi5.o \
|
||||
@ -30,7 +30,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\
|
||||
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
|
||||
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
|
||||
sinfox.o sicslist.o cone.o statistics.o
|
||||
sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o
|
||||
|
||||
MOTOROBJ = motor.o simdriv.o
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||
|
2
motor.c
2
motor.c
@ -492,6 +492,8 @@ extern void KillPiPiezo(void *pData);
|
||||
|
||||
pM = (pMotor)self;
|
||||
|
||||
MotorHalt(pM);
|
||||
|
||||
if(pM->name)
|
||||
free(pM->name);
|
||||
|
||||
|
@ -83,7 +83,7 @@ static long MOLISetValue(void *data, SConnection *pCon, float val){
|
||||
return test;
|
||||
} else {
|
||||
tuktuk.running = 1;
|
||||
LLDnodeDataFrom(self,&tuktuk);
|
||||
LLDnodeDataFrom(self,&tuktuk);
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self);
|
||||
}
|
||||
|
2
ofac.c
2
ofac.c
@ -118,6 +118,7 @@
|
||||
#include "sinfox.h"
|
||||
#include "sicslist.h"
|
||||
#include "cone.h"
|
||||
#include "sicshipadaba.h"
|
||||
/*----------------------- Server options creation -------------------------*/
|
||||
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
@ -245,6 +246,7 @@
|
||||
AddCommand(pInter,"scriptcallback",CallbackScript,NULL,NULL);
|
||||
AddCommand(pInter,"help",SicsHelp,KillHelp,NULL);
|
||||
AddCommand(pInter,"list",SicsList,NULL,NULL);
|
||||
AddCommand(pInter,"InstallHdb",InstallSICSHipadaba,NULL,NULL);
|
||||
|
||||
/* commands to do with the executor. Only StopExe carries the
|
||||
DeleteFunction in order to avoid double deletion. All the
|
||||
|
@ -170,7 +170,6 @@ static int StartOscillation(pOscillator self, SConnection *pCon){
|
||||
static void KillOscillator(void *data){
|
||||
pOscillator self = (pOscillator)data;
|
||||
if(self != NULL){
|
||||
StopOscillation(self);
|
||||
if(self->pDes != NULL){
|
||||
DeleteDescriptor(self->pDes);
|
||||
}
|
||||
|
6
sics.h
6
sics.h
@ -36,6 +36,12 @@
|
||||
|
||||
extern pServer pServ;
|
||||
|
||||
/**
|
||||
* Decode privilege text. Implemented in access.c
|
||||
* @param the text to decode
|
||||
* @return -1 if code invalid, else the privilege code
|
||||
*/
|
||||
int decodeSICSPriv(char *privText);
|
||||
|
||||
#endif
|
||||
|
||||
|
1210
sicshipadaba.c
Normal file
1210
sicshipadaba.c
Normal file
File diff suppressed because it is too large
Load Diff
175
sicshipadaba.h
Normal file
175
sicshipadaba.h
Normal file
@ -0,0 +1,175 @@
|
||||
/**
|
||||
* This is a set of helper functions for SICS to work with the hierarchical parameter
|
||||
* database hipadaba. In SICS, the calldata associated with any callback will always
|
||||
* be the connection object.
|
||||
*
|
||||
* copyright: GPL
|
||||
*
|
||||
* Mark Koennecke, June 2006
|
||||
*/
|
||||
#ifndef SICSHIPADABA_H_
|
||||
#define SICSHIPADABA_H_
|
||||
#include <hipadaba.h>
|
||||
#include <sics.h>
|
||||
#include <dynstring.h>
|
||||
/*======================== data structure for automatic parameter update =======*/
|
||||
typedef struct {
|
||||
SConnection *pCon;
|
||||
int updateList;
|
||||
int iEnd;
|
||||
}hdbUpdateTask, *pHdbUpdateTask;
|
||||
/*======================== common callbacks =====================================*/
|
||||
/**
|
||||
* make a callback which checks permissions. To be used on write
|
||||
* @param priv The privilege to check against
|
||||
* @return a suitably initialized callback structure for
|
||||
* checking permissions.
|
||||
*/
|
||||
pHdbCallback MakeCheckPermissionCallback(int priv);
|
||||
/**
|
||||
* make a callback which directly updates a
|
||||
* paramter after setting. Usefule for program parameters.
|
||||
* @return a suitably initialized callback structure setting
|
||||
* program parameters
|
||||
*/
|
||||
pHdbCallback MakeSetUpdateCallback();
|
||||
/**
|
||||
* make a callback which starts a parameter driving.
|
||||
* @param sicsObject The SICS object to drive.
|
||||
* @return a suitably initialized callback structure for
|
||||
* starting a parameter driving.
|
||||
*/
|
||||
pHdbCallback MakeSICSDriveCallback(void *sicsObject);
|
||||
/**
|
||||
* make a callback which enables automatically
|
||||
* notification of pCon on parameter updates.
|
||||
* @param pCon The connection to notify. The notification
|
||||
* is issued in the context of this connection.
|
||||
* @param id An integer id which can later on be used to remove the
|
||||
* callback.
|
||||
* @return a suitably initialized callback structure for
|
||||
* automatic notification.
|
||||
*/
|
||||
pHdbCallback MakeNotifyCallback(SConnection *pCon, int id);
|
||||
/*======================== parameter creation ===================================*/
|
||||
/**
|
||||
* make a simple SICS hdb parameter. Setting it will call update immediately. Use
|
||||
* this for program parameters.
|
||||
* @param name The name of the parameter
|
||||
* @param priv The privilege required to change that parameter
|
||||
* @param v The initial value and datatype of this parameter
|
||||
* @return A new suitably configured Hdb parameter or NULL when out of memory.
|
||||
*/
|
||||
pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v);
|
||||
/**
|
||||
* make a SICS hdb drivable parameter. Setting it will start the motor,
|
||||
* virtual motor or environment parameter. This will call StartDevice
|
||||
* eventually
|
||||
* @param name The name of the parameter
|
||||
* @param priv The privilege required to change that parameter
|
||||
* @param sicsObject The object corresponding to this parameter.
|
||||
* @param dataType The datatype of this variable
|
||||
* @return A new suitably configured Hdb parameter or NULL when out of memory.
|
||||
*/
|
||||
|
||||
pHdb MakeSICSHdbDriv(char *name, int priv,void *sicsObject, int datatype);
|
||||
/**
|
||||
* makes a SICS Hdb read only parameter. Setting such a parameter causes an error.
|
||||
* @param name The name of the parameter
|
||||
* @param v The initial value and datatype of this parameter
|
||||
* @return A new suitably configured Hdb parameter or NULL when out of memory.
|
||||
*/
|
||||
pHdb MakeSICSROPar(char *name, hdbValue v);
|
||||
/**
|
||||
* make a SICS scriptable parameter. I.e. when this parameter is set or read,
|
||||
* appropriate scripts are invoked.
|
||||
* @param name The name of the parameter
|
||||
* @param setScript The script to call when this parameter is being set
|
||||
* @param readScript The script to call when this parameter is being read.
|
||||
* @param v The initial value and datatype of this parameter
|
||||
* @return A new suitably configured Hdb parameter or NULL when out of memory.
|
||||
*/
|
||||
pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript, hdbValue v);
|
||||
/**
|
||||
* remove a SICS paramameter node and its children. In contrast to the
|
||||
* normal DeletHipadabaNode, this function also takes care of
|
||||
* clearing scipted nodes out of the update tasks watch list.
|
||||
* @param node The node to delete
|
||||
*/
|
||||
void RemoveSICSPar(pHdb node);
|
||||
/*============= common SICS Interactions ===================================*/
|
||||
/**
|
||||
* Install a SICS automatic notification callback on the node. This is
|
||||
* a default callback using the current connection with its current
|
||||
* context for notification.
|
||||
* @param node The parameter on which to install the callback
|
||||
* @param pCon The connection to which this callback is linked.
|
||||
* @param id An int associated with this notification callback. A
|
||||
* precaution for later removal.
|
||||
* @param recurse a flag 0 or 1 which determines if callbacks are
|
||||
* installed to all nodes recursively.
|
||||
* @return 1 on success, 0 when out of memory.
|
||||
*/
|
||||
int InstallSICSNotify(pHdb node, SConnection *pCon, int id, int recurse);
|
||||
/**
|
||||
* handles the common task of checking for, and processing a SICS parameter.
|
||||
* @param root The node at which to search for parameters
|
||||
* @param pCon The connection in whichs context the parameter is processed.
|
||||
* @param printPrefix A prefix to prepend before printing this parameter.
|
||||
* Will be ignored if NULL.
|
||||
* @param argc number of arguments to process.
|
||||
* @param argv The arguments to process. argv[0] should be the parameter
|
||||
* name.
|
||||
* @return -1 when argv[0] is no parameter, 0 on failure, 1 on success.
|
||||
*/
|
||||
int ProcessSICSHdbPar(pHdb root, SConnection *pCon, char *printPrefix,
|
||||
int argc, char *argv[]);
|
||||
/**
|
||||
* A SICS task which scans a Hipadaba and reads and updates all parameters,
|
||||
* one per invocation. TODO: how to distinguish between automatic pars which
|
||||
* do not need this and pars which need this? Idea 1: make a root point at an
|
||||
* artificial tree of parameters which need to be checked like this.
|
||||
* @param pData The root to start scanning at.
|
||||
* @return 0 when ends, 1 else
|
||||
*/
|
||||
int SICSHipadabaTask(void *pData);
|
||||
void SICSHipadabaSignal(void *pData, int iSignal, void *pSigData);
|
||||
/*================== value helpers ========================================*/
|
||||
/**
|
||||
* format a Hdb Value into a string using SICS defaults.
|
||||
* @param v The Hdb value to format
|
||||
* @return a dynamic string holding the formatted data. NULL when
|
||||
* out of memory
|
||||
*/
|
||||
pDynString formatValue(hdbValue v);
|
||||
/**
|
||||
* read values for a Hdb value from a string.
|
||||
* @param v The hdbValue to read data into. Datatype and arraylength must
|
||||
* already have been initialised before this call in order to allow for
|
||||
* checks. Arrays should also have been allocated in the right size.
|
||||
* @param data The string to parse and convert.
|
||||
* @param error A string to copy failure reasons too
|
||||
* @param errlen The length of the error string
|
||||
* @return 0 on failure, 1 on success
|
||||
*/
|
||||
int readHdbValue(hdbValue *v, char *data, char *error, int errlen);
|
||||
/*================= SICS Interpreter Interface ===========================*/
|
||||
/**
|
||||
* InstallHipadaba installs the Hipadaba commands into the SICS interpreter.
|
||||
* The actual command implementation is in sicshipadaba.c.
|
||||
* @param pCon The connection object
|
||||
* @param pSics The SICS interpreter
|
||||
* @param pData The object data structure
|
||||
* @param argc The number of arguments
|
||||
* @param argv[] The text arguments
|
||||
* @return 0 on filaure, 1 on success
|
||||
*/
|
||||
int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/**
|
||||
* get the root of the SICS Hipadaba tree
|
||||
* @return The root node of the hipdaba
|
||||
*/
|
||||
pHdb GetHipadabaRoot();
|
||||
|
||||
#endif /*SICSHIPADABA_H_*/
|
37
sicvar.c
37
sicvar.c
@ -136,14 +136,7 @@
|
||||
"float",
|
||||
NULL
|
||||
};
|
||||
static char *cAccess[] = {
|
||||
"internal",
|
||||
"mugger",
|
||||
"user",
|
||||
"spy",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
int VarFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
@ -196,30 +189,8 @@
|
||||
}
|
||||
|
||||
/* argv[3] must be the access code, check that now */
|
||||
i = 0;
|
||||
while(cAccess[i] != NULL)
|
||||
{
|
||||
if(strcmp(argv[3],cAccess[i]) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
iCode = usInternal;
|
||||
break;
|
||||
case 1:
|
||||
iCode = usMugger;
|
||||
break;
|
||||
case 2:
|
||||
iCode = usUser;
|
||||
break;
|
||||
case 3:
|
||||
iCode = usSpy;
|
||||
break;
|
||||
default:
|
||||
i = decodeSICSPriv(argv[3]);
|
||||
if(i < 0){
|
||||
sprintf(pBueffel," %s access code %s not recognized",
|
||||
argv[1], argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
@ -227,7 +198,7 @@
|
||||
}
|
||||
|
||||
/* now we can actually install the variable */
|
||||
pRes = VarCreate(iCode,eType,argv[1]);
|
||||
pRes = VarCreate(i,eType,argv[1]);
|
||||
if(!pRes)
|
||||
{
|
||||
sprintf(pBueffel,"Memory Error creating variable %s", argv[1]);
|
||||
|
38
tasdrive.c
38
tasdrive.c
@ -192,22 +192,24 @@ static int TASHalt(void *pData){
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void writeMotPos(SConnection *pCon, char *name,
|
||||
static void writeMotPos(SConnection *pCon, int silent, char *name,
|
||||
float val, float target){
|
||||
char pBueffel[132];
|
||||
|
||||
snprintf(pBueffel,131,"Driving %5s from %8.3f to %8.3f",
|
||||
name, val, target);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
|
||||
if(silent != 1) {
|
||||
snprintf(pBueffel,131,"Driving %5s from %8.3f to %8.3f",
|
||||
name, val, target);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int startMotors(ptasMot self, tasAngles angles,
|
||||
SConnection *pCon, int driveQ, int driveTilt){
|
||||
float val;
|
||||
double curve;
|
||||
int status;
|
||||
int status, silent;
|
||||
|
||||
silent = self->math->silent;
|
||||
/*
|
||||
monochromator
|
||||
*/
|
||||
@ -220,7 +222,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"a1",val, angles.monochromator_two_theta/2.);
|
||||
writeMotPos(pCon,silent,"a1",val, angles.monochromator_two_theta/2.);
|
||||
|
||||
val = self->math->motors[A2]->pDrivInt->GetValue(self->math->motors[A2],pCon);
|
||||
if(ABS(val - angles.monochromator_two_theta) > MOTPREC){
|
||||
@ -231,7 +233,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"a2",val, angles.monochromator_two_theta);
|
||||
writeMotPos(pCon,silent,"a2",val, angles.monochromator_two_theta);
|
||||
|
||||
if(self->math->motors[MCV] != NULL){
|
||||
curve = maCalcVerticalCurvature(self->math->machine.monochromator,
|
||||
@ -245,7 +247,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"mcv",val, curve);
|
||||
writeMotPos(pCon,silent,"mcv",val, curve);
|
||||
}
|
||||
|
||||
if(self->math->motors[MCH] != NULL){
|
||||
@ -260,7 +262,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"mch",val, curve);
|
||||
writeMotPos(pCon,silent,"mch",val, curve);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -277,7 +279,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,self->math->motors[A5]->name,
|
||||
writeMotPos(pCon,silent,self->math->motors[A5]->name,
|
||||
val, angles.analyzer_two_theta/2.);
|
||||
|
||||
val = self->math->motors[A6]->pDrivInt->GetValue(self->math->motors[A6],pCon);
|
||||
@ -289,7 +291,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"a6",val, angles.analyzer_two_theta);
|
||||
writeMotPos(pCon,silent,"a6",val, angles.analyzer_two_theta);
|
||||
|
||||
if(self->math->motors[ACV] != NULL){
|
||||
curve = maCalcVerticalCurvature(self->math->machine.analyzer,
|
||||
@ -303,7 +305,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"acv",val, curve);
|
||||
writeMotPos(pCon,silent,"acv",val, curve);
|
||||
}
|
||||
if(self->math->motors[ACH] != NULL){
|
||||
curve = maCalcHorizontalCurvature(self->math->machine.analyzer,
|
||||
@ -319,7 +321,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
}
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"ach",val, curve);
|
||||
writeMotPos(pCon,silent,"ach",val, curve);
|
||||
}
|
||||
|
||||
if(driveQ == 0){
|
||||
@ -338,7 +340,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"a3",val, angles.a3);
|
||||
writeMotPos(pCon,silent,"a3",val, angles.a3);
|
||||
|
||||
val = self->math->motors[A4]->pDrivInt->GetValue(self->math->motors[A4],pCon);
|
||||
if(ABS(val - angles.sample_two_theta) > MOTPREC){
|
||||
@ -349,7 +351,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"a4",val, angles.sample_two_theta);
|
||||
writeMotPos(pCon,silent,"a4",val, angles.sample_two_theta);
|
||||
|
||||
if(driveTilt == 1){
|
||||
val = self->math->motors[SGL]->pDrivInt->GetValue(self->math->motors[SGL],pCon);
|
||||
@ -361,7 +363,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"sgl",val, angles.sgl);
|
||||
writeMotPos(pCon,silent,"sgl",val, angles.sgl);
|
||||
|
||||
val = self->math->motors[SGU]->pDrivInt->GetValue(self->math->motors[SGU],pCon);
|
||||
if(ABS(val - angles.sgu) > MOTPREC){
|
||||
@ -372,7 +374,7 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
writeMotPos(pCon,"sgu",val, angles.sgu);
|
||||
writeMotPos(pCon,silent,"sgu",val, angles.sgu);
|
||||
}
|
||||
self->math->mustDrive = 0;
|
||||
return OKOK;
|
||||
|
@ -692,6 +692,7 @@ static int TASUBScanDrive(pScanData self, int iPoint)
|
||||
int iTAS = 0;
|
||||
pMotor pMot;
|
||||
|
||||
pTAS->ub->silent = 1;
|
||||
/*
|
||||
loop through all the scan variables
|
||||
*/
|
||||
@ -721,6 +722,7 @@ static int TASUBScanDrive(pScanData self, int iPoint)
|
||||
else
|
||||
{
|
||||
status = Wait4Success(GetExecutor());
|
||||
pTAS->ub->silent = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -829,6 +831,8 @@ static int TASUBScanCount(pScanData self, int iPoint)
|
||||
|
||||
/* loop over all scan variables */
|
||||
status = 1;
|
||||
|
||||
pTAS->ub->silent = 0;
|
||||
for(i = 0; i < self->iScanVar; i++)
|
||||
{
|
||||
DynarGet(self->pScanVar,i,&pDings);
|
||||
|
19
tasub.c
19
tasub.c
@ -1514,6 +1514,25 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if(strcmp(argv[1],"silent") == 0){
|
||||
if(argc > 2){
|
||||
strtolower(argv[2]);
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&newSS);
|
||||
if(status != TCL_OK){
|
||||
SCWrite(pCon,"ERROR: failed to convert argument to number",eError);
|
||||
return 0;
|
||||
}
|
||||
self->silent = newSS;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBueffel,131,"%s.silent = %d",argv[0],self->silent);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
snprintf(pBueffel,131,"ERROR: subcommand %s to %s not defined",argv[1],
|
||||
argv[0]);
|
||||
|
1
tasub.h
1
tasub.h
@ -30,6 +30,7 @@
|
||||
pMotor motors[12];
|
||||
tasReflection r1, r2;
|
||||
int ubValid;
|
||||
int silent;
|
||||
}tasUB, *ptasUB;
|
||||
|
||||
|
||||
|
4
tasub.w
4
tasub.w
@ -32,6 +32,7 @@ A data structure:
|
||||
pMotor motors[12];
|
||||
tasReflection r1, r2;
|
||||
int ubValid;
|
||||
int silent;
|
||||
}tasUB, *ptasUB;
|
||||
@}
|
||||
\begin{description}
|
||||
@ -55,6 +56,9 @@ A data structure:
|
||||
runtime.
|
||||
\item[r1,r2] The indexs of the reflections used for calculating the orientation
|
||||
matrix.
|
||||
\item[ubValid] a flag denoting if the UB is valid.
|
||||
\item[silent] A flga which when 1 suppresses the printing of motor positions
|
||||
when driving. Usefule for scans.
|
||||
\end{description}
|
||||
|
||||
For the virtual motors, there must be a data structure, too:
|
||||
|
Reference in New Issue
Block a user