Files
cdev-1.7.2n/extensions/tclnew/tcl_cdevcollections.cc
2022-12-13 12:44:04 +01:00

438 lines
11 KiB
C++

// Cdev collection access from tcl
// Johannes van Zeijts
// March 97, first version
/*
cdevcollection $devices
cdevcollection $devices $attr
$c set attrib $value
$c get devices
$c get attrib
$c get
$c get vector $v // store in blt::vector $v
$c $message // send to cdev and return results
*/
#include <tcl.h>
#include "blt.h"
#include <ctype.h>
#include <string.h>
#include <iostream.h>
#include <math.h>
//#include <dl.h>
// cdev includes
#include <cdevSystem.h>
#include <cdevRequestObject.h>
#include <cdevDevice.h>
#include <cdevGroup.h>
#include <cdevData.h>
static int VALUE_TAG_ID =- 1;
#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!= CDEV_SUCCESS)?-1:VALUE_TAG_ID)
static int STATUS_TAG_ID =- 1;
#define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!= CDEV_SUCCESS)?-1:STATUS_TAG_ID)
static int SEVERITY_TAG_ID =- 1;
#define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!= CDEV_SUCCESS)?-1:SEVERITY_TAG_ID)
typedef cdevRequestObject *cdevRequestObjectPtr;
// class DeviceEntry {
// public:
// DeviceEntry(char*);
// ~DeviceEntry();
//
// cdevRequestObject *request;
// cdevData result;
// int status;
// };
class TclCdevCollection {
public:
TclCdevCollection(int, char**);
~TclCdevCollection();
char *getAttrib();
void setAttrib(char*);
void getDevices(Tcl_Interp *);
void getStatus(Tcl_Interp *);
void getResult(Tcl_Interp *);
void getCallback(Tcl_Interp *);
int getLength() { return ndevices;}
void getVector(double*);
static void deleteCollection(ClientData);
int send();
int sendCallback(Tcl_Interp*, char*);
int checkCallback();
static void callbackFunction(int, void *, cdevRequestObject&, cdevData &);
static void TimerHandler(ClientData);
private:
cdevRequestObjectPtr *requests;
cdevData *results;
char **devices;
int ndevices;
char *attrib;
int *status, *callbacks;
};
TclCdevCollection::TclCdevCollection(int n, char** s) : ndevices(0), devices(NULL), attrib(NULL) {
if (n < 0) return;
ndevices = n;
devices = new char*[ndevices];
for (int i = 0; i<ndevices; i++) {
devices[i] = new char[strlen(s[i])+1];
strcpy(devices[i],s[i]);
}
requests = new cdevRequestObjectPtr[ndevices];
results = new cdevData[ndevices];
status = new int[ndevices];
callbacks = new int[ndevices];
}
TclCdevCollection::~TclCdevCollection() {
for (int i = 0; i<ndevices; i++) {
delete devices[i];
}
delete [] devices;
delete [] results;
delete callbacks;
delete status;
delete attrib;
delete requests;
}
class callbackInfo1 {
public:
callbackInfo1(TclCdevCollection*, int);
TclCdevCollection* ptr;
int index;
};
class callbackInfo2 {
public:
callbackInfo2(Tcl_Interp*, TclCdevCollection*, char*);
TclCdevCollection* ptr;
Tcl_Interp* interp;
char *s;
};
callbackInfo1::callbackInfo1(TclCdevCollection* c, int i) : ptr(c), index(i) {
}
callbackInfo2::callbackInfo2(Tcl_Interp* intp, TclCdevCollection* c, char* v) : interp(intp), ptr(c) {
s = new char[strlen(v)+1];
strcpy(s,v);
}
void TclCdevCollection::callbackFunction(int stat, void *userarg, cdevRequestObject&, cdevData &result) {
callbackInfo1 *info = (callbackInfo1 *) userarg;
TclCdevCollection *c = info->ptr;
c->status[info->index] = stat;
c->results[info->index] = result;
c->callbacks[info->index] = 1;
}
int TclCdevCollection::checkCallback() {
int stat = 0;
for (int i = 0; i < ndevices; i++) {
if (callbacks[i] == 0) return 0;
}
return 1;
}
void TclCdevCollection::TimerHandler(ClientData dummy) {
cdevSystem::defaultSystem().poll();
callbackInfo2 *info = (callbackInfo2 *) dummy;
if (info->ptr->checkCallback()) {
// set something
Tcl_SetVar2(info->interp, "Control", info->s, "1", TCL_GLOBAL_ONLY);
delete info;
} else { /// try again later
Tcl_CreateTimerHandler(50, TclCdevCollection::TimerHandler, dummy);
}
}
void TclCdevCollection::setAttrib(char* a) {
char message[256];
delete attrib;
attrib = new char[strlen(a)+1];
strcpy(attrib, a);
strcpy(message,"get ");
strcat(message, attrib);
for(int i = 0; i < ndevices; i++) {
requests[i] = cdevRequestObject::attachPtr(devices[i], message);
}
}
char* TclCdevCollection::getAttrib() {
return attrib;
}
void TclCdevCollection::getDevices(Tcl_Interp *interp) {
int i;
for (i = 0; i < ndevices; i++) {
Tcl_AppendElement(interp, devices[i]);
}
}
void TclCdevCollection::getStatus(Tcl_Interp *interp) {
int i;
char res[256];
for (i = 0; i < ndevices; i++) {
sprintf(res, "%d", status[i]);
Tcl_AppendElement(interp, res);
}
}
void TclCdevCollection::getCallback(Tcl_Interp *interp) {
int i;
char res[256];
for (i = 0; i < ndevices; i++) {
sprintf(res, "%d", callbacks[i]);
Tcl_AppendElement(interp, res);
}
}
void TclCdevCollection::getResult(Tcl_Interp *interp) {
int i;
char res[300];
for (i = 0; i < ndevices; i++) {
results[i].get(VALUE_TAG, res, 255);
Tcl_AppendElement(interp, res);
}
}
void TclCdevCollection::getVector(double *res) {
for (int i = 0; i < ndevices; i++) {
results[i].get(VALUE_TAG, &res[i]);
}
}
int TclCdevCollection::send() {
int stat = CDEV_SUCCESS;
int i;
for (i = 0; i < ndevices; i++) {
results[i].remove();
status[i] = requests[i]->send(NULL, results[i]);
if ((status[i] != CDEV_SUCCESS) && (stat == CDEV_SUCCESS)) {
stat = CDEV_ERROR;
}
}
return stat;
}
int TclCdevCollection::sendCallback(Tcl_Interp* interp, char* v) {
int stat = CDEV_SUCCESS;
for (int i = 0; i < ndevices; i++) {
results[i].remove();
callbacks[i] = 0;
callbackInfo1* info1 = new callbackInfo1(this, i);
cdevCallback* cb = new cdevCallback(TclCdevCollection::callbackFunction, (void *) info1);
status[i] = requests[i]->sendCallback(NULL, *cb);
if ((status[i] != CDEV_SUCCESS) && (stat == CDEV_SUCCESS)) {
stat = CDEV_ERROR;
}
}
callbackInfo2 *info2 = new callbackInfo2(interp, this, v);
Tcl_SetVar2(interp, "Control", v, "0", TCL_GLOBAL_ONLY);
Tcl_CreateTimerHandler(50, TclCdevCollection::TimerHandler, (ClientData) info2);
return stat;
}
void TclCdevCollection::deleteCollection(ClientData clientData) {
TclCdevCollection *collectionPtr;
collectionPtr = (TclCdevCollection *) clientData;
delete collectionPtr;
}
int CollectionCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){
TclCdevCollection *collectionPtr;
collectionPtr = (TclCdevCollection *) clientData;
if (strcmp(argv[1], "get") == 0) {
if (argc == 2) { // send it out to cdev // get
if (collectionPtr->getAttrib() == NULL) {
interp->result = "did not set attrib";
return TCL_ERROR;
}
if (collectionPtr->send() == CDEV_SUCCESS) {
collectionPtr->getResult(interp);
return TCL_OK;
}
interp->result = "encountered cdev error";
return TCL_ERROR;
}
if (strcmp(argv[2], "attrib") == 0) { // get attrib
Tcl_SetResult(interp, collectionPtr->getAttrib(), TCL_STATIC);
return TCL_OK;
}
if (strcmp(argv[2], "devices") == 0) { // get devices
collectionPtr->getDevices(interp);
return TCL_OK;
}
if (strcmp(argv[2], "status") == 0) { // get status
collectionPtr->getStatus(interp);
return TCL_OK;
}
if (strcmp(argv[2], "callback") == 0) { // get status
collectionPtr->getCallback(interp);
return TCL_OK;
}
if (strcmp(argv[2], "vector") == 0) { // get vector
if (argc != 4) return TCL_ERROR;
Blt_Vector vecInfo;
if (!Blt_VectorExists(interp, argv[3])) {
interp->result = "vector does not exist";
return TCL_ERROR;
}
if (collectionPtr->send() != CDEV_SUCCESS) {
interp->result = "encountered cdev error";
return TCL_ERROR;
}
if (vecInfo.arraySize < collectionPtr->getLength()) { // resize if necc.
if (Blt_ResizeVector(interp, argv[3], collectionPtr->getLength()) != TCL_OK) return TCL_ERROR;
}
if (Blt_GetVector(interp, argv[3], &vecInfo) != TCL_OK) return TCL_ERROR;
vecInfo.numValues = collectionPtr->getLength();
vecInfo.valueArr = (double *) malloc(sizeof(double) * collectionPtr->getLength());
collectionPtr->getVector(vecInfo.valueArr);
if (Blt_ResetVector(interp, argv[3], &vecInfo, TCL_DYNAMIC) != TCL_OK) {
return TCL_ERROR;
}
return TCL_OK;
}
}
if (strcmp(argv[1], "set") == 0) {
if (argc != 4) return TCL_ERROR;
if (strcmp(argv[2], "attrib") == 0) { // set attrib $value
collectionPtr->setAttrib(argv[3]);
return TCL_OK;
}
}
if (strcmp(argv[1], "sendcallback") == 0) {
if (strcmp(argv[2], "vector") == 0) { // sendcallback vector $v
if (argc != 4) return TCL_ERROR;
Blt_Vector vecInfo;
if (!Blt_VectorExists(interp, argv[3])) {
interp->result = "vector does not exist";
return TCL_ERROR;
}
if (collectionPtr->sendCallback(interp, argv[3]) != CDEV_SUCCESS) {
interp->result = "encountered cdev error";
return TCL_ERROR;
}
return TCL_OK;
}
return TCL_ERROR;
}
if (strcmp(argv[1], "checkcallback") == 0) {
if (collectionPtr->checkCallback()) {
interp->result = "1";
} else {
interp->result = "0";
}
return TCL_OK;
}
if (strcmp(argv[1], "getcallback") == 0) {
if (strcmp(argv[2], "vector") == 0) { // getcallback vector $v
if (argc != 4) return TCL_ERROR;
Blt_Vector vecInfo;
if (!Blt_VectorExists(interp, argv[3])) {
interp->result = "vector does not exist";
return TCL_ERROR;
}
if (!collectionPtr->checkCallback()) {
interp->result = "callbacks not ready";
return TCL_ERROR;
}
if (vecInfo.arraySize < collectionPtr->getLength()) { // resize if necc.
if (Blt_ResizeVector(interp, argv[3], collectionPtr->getLength()) != TCL_OK) return TCL_ERROR;
}
if (Blt_GetVector(interp, argv[3], &vecInfo) != TCL_OK) return TCL_ERROR;
vecInfo.numValues = collectionPtr->getLength();
vecInfo.valueArr = (double *) malloc(sizeof(double) * collectionPtr->getLength());
collectionPtr->getVector(vecInfo.valueArr);
if (Blt_ResetVector(interp, argv[3], &vecInfo, TCL_DYNAMIC) != TCL_OK) {
return TCL_ERROR;
}
return TCL_OK;
}
}
interp->result = "unknown command";
return TCL_ERROR;
}
int MakeCollectionCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){
TclCdevCollection *collectionPtr;
static int id = 0;
int c1;
char** s1;
if (argc < 2 || argc >3) {
interp->result = "wrong # args";
return TCL_ERROR;
}
if(Tcl_SplitList(interp, argv[1], &c1, &s1) != TCL_OK) {
return TCL_ERROR;
}
collectionPtr = new TclCdevCollection(c1,s1);
free ((char*) s1);
sprintf(interp->result, "col%d", id);
id++;
Tcl_CreateCommand(interp, interp->result, CollectionCmd, (ClientData) collectionPtr, TclCdevCollection::deleteCollection);
if (argc == 3) {
collectionPtr->setAttrib(argv[2]);
}
return TCL_OK;
}
extern "C" int Cdevcollection_Init(Tcl_Interp *interp) {
Tcl_PkgRequire(interp, "BLT", "2.4", 0);
Tcl_PkgRequire(interp, "Cdev", "", 0);
if(Tcl_PkgProvide(interp, "Cdevcollection", "1.0") != TCL_OK) {
return TCL_ERROR;
}
Tcl_CreateCommand(interp, "cdevcollection", MakeCollectionCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL);
return TCL_OK;
}