801 lines
19 KiB
C++
Executable File
801 lines
19 KiB
C++
Executable File
// a CDEV access interface for tcl
|
|
// Johannes van Zeijts, March 95, first version
|
|
// May 95, second version, using Walt Akers callback example
|
|
// Dec 95, added arbitrary dimensional array output and context
|
|
// Jan 96, added handling of strings with spaces
|
|
// Aug 96, deleted callbackinfo when we are not monitoring
|
|
// Aug 96, converted to tcl7.5
|
|
// Nov 1, 96, moved to cdev 1.4
|
|
// March, 97, overhaul, allowed multiple devices
|
|
|
|
/* Output formatting
|
|
Attention given to 'Strings with spaces' which have special meaning in tcl
|
|
|
|
#devices = 1
|
|
|
|
#tags = 0 (only value tag)
|
|
|
|
dim = 0 1
|
|
String
|
|
String with spaces
|
|
|
|
dim = 1 1 1 1
|
|
St1 St2 St3
|
|
{St w sp1} {St w sp2} {St w sp3}
|
|
|
|
dim = 2 {11 12 13} {21 22 23}
|
|
{st1 st2 st3} {...}
|
|
{{st w sp1} {st w sp2} {st w sp3}} { ...}
|
|
|
|
|
|
|
|
|
|
#tags > 0 (value tag + other tags)
|
|
Each tag in its own list index
|
|
Result is always list of length (#tags + 1)
|
|
|
|
|
|
dim = 0
|
|
1
|
|
St1
|
|
{St w sp1}
|
|
|
|
|
|
dim = 1
|
|
{1 1 1}
|
|
{St1 St2 St3}
|
|
{{St w sp1} {St w sp2} {St w sp3}}
|
|
|
|
|
|
dim = 2
|
|
{{1 1 1} {1 1 1}}
|
|
{{{st w sp1} {st w sp2} {st w sp3}} {{st w sp1} {st w sp2} {st w sp3}}}
|
|
|
|
|
|
---------------------------------------------------------------------------------------
|
|
#devices > 1 ,
|
|
|
|
#tags = 0
|
|
dim = 0 1 1 1
|
|
{str w sp} {str w sp}
|
|
|
|
dim = 1 {1 1 1} {1 1 1}
|
|
{{str w sp} ..} { }
|
|
|
|
|
|
#tags > 0
|
|
dim = 0 {0 1 2} {0 1 2}
|
|
|
|
dim = 1 {{1 1 1} {1 1 1}}
|
|
|
|
*/
|
|
|
|
#include <tcl.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)
|
|
|
|
static int cdevdebug = 0;
|
|
|
|
class tclCdevData {
|
|
public:
|
|
tclCdevData();
|
|
void parse(Tcl_Interp*, char* *, int);
|
|
~tclCdevData();
|
|
|
|
cdevData out, context;
|
|
int hascontext;
|
|
|
|
int tagn, *taglist;
|
|
char *callbacktag;
|
|
|
|
int state, async;
|
|
}
|
|
;
|
|
|
|
tclCdevData::~tclCdevData() {
|
|
delete taglist;
|
|
}
|
|
|
|
tclCdevData::tclCdevData():hascontext(0), tagn(0), taglist(NULL), async(0), state(TCL_ERROR) {
|
|
}
|
|
;
|
|
// Parses command line, fills up the outgoing cdevData and the context (if any)
|
|
void tclCdevData::parse(Tcl_Interp *interp, char **argv, int argc) {
|
|
int i, c1, c2;
|
|
cdevData *ptr;
|
|
char **s1 = NULL;
|
|
char **s2 = NULL;
|
|
|
|
// Point to 'out' cdevData until we hit the context (if any)
|
|
ptr = &out;
|
|
for(i = 3; i < argc; i++) {
|
|
// skip 'cdev' '$device' and '$message'
|
|
if(Tcl_SplitList(interp, argv[i], &c1, &s1) != TCL_OK) {
|
|
return;
|
|
}
|
|
if(c1 == 2) {
|
|
// {tag value} pair, check if the value is a scalar
|
|
if(Tcl_SplitList(interp, s1[1], &c2, &s2) != TCL_OK) {
|
|
free((char *) s1);
|
|
return;
|
|
}
|
|
if(c2 == 1) {
|
|
// we have a scalar
|
|
ptr->insert(s1[0], s1[1]);
|
|
// insert scalar
|
|
}
|
|
else {
|
|
ptr->insert(s1[0], s2, c2);
|
|
// insert vector of scalars, does not handle matrices
|
|
}
|
|
free((char *) s2);
|
|
}
|
|
else if(c1 == 1) {
|
|
// can be one of "-context" , "-tags" or a callbacktag
|
|
if(strcmp(argv[i], "-context") == 0) {
|
|
// all remaining 'tag value' pairs go in the context
|
|
ptr = &context;
|
|
hascontext = 1;
|
|
}
|
|
else if(strcmp(argv[i], "-tags") == 0) {
|
|
// get the list of tags to print out from the result data
|
|
i++;
|
|
// points to next entry in argv
|
|
if(i == argc) {
|
|
interp->result = "expected tag names";
|
|
free((char *) s1);
|
|
return;
|
|
}
|
|
if(Tcl_SplitList(interp, argv[i], &tagn, &s2) != TCL_OK) {
|
|
interp->result = "tag problem";
|
|
free((char *) s1);
|
|
return;
|
|
}
|
|
else {
|
|
taglist = new int[tagn];
|
|
for(int j = 0; j < tagn; j++) {
|
|
if(cdevData::tagC2I(s2[j], &taglist[j]) != CDEV_SUCCESS) {
|
|
interp->result = "unknown tag";
|
|
free((char *) s2);
|
|
free((char *) s1);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
free((char *) s2);
|
|
}
|
|
else {
|
|
// single entry, a callbacktag, better be at end of input
|
|
if(i != argc-1) {
|
|
interp->result = "expecting callbacktag at end";
|
|
free((char *) s1);
|
|
return;
|
|
}
|
|
// Here we have a callback tag, hence we want to send asynchronously
|
|
callbacktag = argv[i];
|
|
async = 1;
|
|
}
|
|
}
|
|
else {
|
|
// c1 > 2
|
|
// tag / string pair (i.e. "value this is a string with spaces embedded"
|
|
char **av = s1;
|
|
av++;
|
|
char *concat = Tcl_Concat(c1-1, av);
|
|
ptr->insert(s1[0], concat);
|
|
if(cdevdebug == 1) {
|
|
fprintf(stderr, "inserted: %s, with value: %s\n", s1[0], concat);
|
|
}
|
|
free(concat);
|
|
}
|
|
free((char *) s1);
|
|
}
|
|
state = TCL_OK;
|
|
}
|
|
|
|
class callbackInfo {
|
|
public:
|
|
callbackInfo(Tcl_Interp*, char *);
|
|
callbackInfo(Tcl_Interp*, char*, char *);
|
|
~callbackInfo();
|
|
Tcl_Interp *interp;
|
|
char *s;
|
|
cdevCallback *callback;
|
|
|
|
void addtags(int, int *);
|
|
|
|
int *tags, ntags;
|
|
}
|
|
;
|
|
|
|
callbackInfo::callbackInfo(Tcl_Interp *e, char *arg) {
|
|
interp = e;
|
|
s = new char[strlen(arg)+1];
|
|
strcpy(s, arg);
|
|
ntags = 0;
|
|
tags = NULL;
|
|
callback = NULL;
|
|
}
|
|
|
|
callbackInfo::callbackInfo(Tcl_Interp *e, char *arg1, char *arg2) {
|
|
interp = e;
|
|
s = new char[strlen(arg1)+strlen(arg2)+1];
|
|
strcpy(s, arg1);
|
|
strcat(s, arg2);
|
|
ntags = 0;
|
|
tags = NULL;
|
|
callback = NULL;
|
|
}
|
|
|
|
callbackInfo::~callbackInfo() {
|
|
delete tags;
|
|
delete s;
|
|
}
|
|
|
|
void callbackInfo::addtags(int n, int *v) {
|
|
ntags = n;
|
|
tags = new int[n];
|
|
for(int i = 0; i < ntags; i++) {
|
|
tags[i] = v[i];
|
|
}
|
|
delete callback;
|
|
}
|
|
|
|
static char cs[512];
|
|
cdevBounds *Bounds;
|
|
int Dim;
|
|
|
|
static int K = 0;
|
|
|
|
void HandleLevel(char **in, int level, Tcl_DString &ds) {
|
|
int i;
|
|
for(i = 0; i < Bounds[level].length; i++) {
|
|
if(level >= Dim-1) {
|
|
Tcl_DStringAppendElement(&ds, in[K]);
|
|
K++;
|
|
}
|
|
else {
|
|
Tcl_DStringStartSublist(&ds);
|
|
HandleLevel(in, level+1, ds);
|
|
Tcl_DStringEndSublist(&ds);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Format a cdevData tag result into a tcl result
|
|
// mode == #ntags
|
|
|
|
void HandleTag(int tag, cdevData &result, Tcl_DString &ds, int mode, int ndevices) {
|
|
int i, len;
|
|
size_t dim;
|
|
char **sp;
|
|
|
|
if(result.getDim(tag, &dim) != CDEV_SUCCESS) {
|
|
cs[0] = NULL;
|
|
if (ndevices == 1 && mode == 0) {
|
|
Tcl_DStringAppend(&ds, cs, -1); // append an empty string
|
|
} else {
|
|
Tcl_DStringAppendElement(&ds, cs); // append an empty list
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Always retrieve the result as a char*, cdevData does the conversion for me!
|
|
|
|
if(dim == 0) {
|
|
/*
|
|
* // put this in if we want format conversions.
|
|
* i = result.getType(tag);
|
|
* if ((i == CDEV_FLOAT) || (i == CDEV_DOUBLE)) {
|
|
* result.get(tag,&dres);
|
|
* sprintf(cs,"%.2g",dres);
|
|
* } else {
|
|
*/
|
|
cs[0] = NULL;
|
|
result.get(tag, cs, 255);
|
|
|
|
if (mode == 0 && ndevices == 1) {
|
|
Tcl_DStringAppend(&ds,cs,-1);
|
|
} else {
|
|
Tcl_DStringAppendElement(&ds,cs);
|
|
}
|
|
return;
|
|
}
|
|
else {
|
|
// dim > 0
|
|
Dim = (int) dim;
|
|
K = 0;
|
|
Bounds = new cdevBounds[Dim];
|
|
result.getBounds(tag, Bounds, Dim);
|
|
len = 1;
|
|
for(i = 0; i < Dim; i++) {
|
|
len *= Bounds[i].length;
|
|
}
|
|
sp = new char*[len];
|
|
result.get(tag, sp);
|
|
|
|
if (mode>0 || (mode==0&&ndevices>1)) Tcl_DStringStartSublist(&ds);
|
|
HandleLevel(sp, 0, ds);
|
|
if (mode>0 || (mode==0&&ndevices>1)) Tcl_DStringEndSublist(&ds);
|
|
// append the result to a Tcl_DString
|
|
}
|
|
|
|
delete Bounds;
|
|
while(len > 0) {
|
|
len--;
|
|
delete sp[len];
|
|
}
|
|
delete [] sp;
|
|
}
|
|
|
|
int Cdev_Handleresult(int *tags, int ntags, cdevData &result, Tcl_DString &ds, int ndevices) {
|
|
// assume we always return the "value" tag
|
|
|
|
if (ndevices>1 && ntags>0) Tcl_DStringStartSublist(&ds);
|
|
|
|
HandleTag(VALUE_TAG, result, ds, ntags, ndevices);
|
|
if(ntags > 0) {
|
|
for(int i = 0; i < ntags; i++) {
|
|
HandleTag(tags[i], result, ds, ntags, ndevices);
|
|
}
|
|
}
|
|
if (ndevices>1 && ntags>0) Tcl_DStringEndSublist(&ds);
|
|
return TCL_OK;
|
|
}
|
|
|
|
// executes inside poll() whenever 'file' is readable
|
|
void Cdev_CallbackFunction(int, void *userarg, cdevRequestObject&, cdevData &result) {
|
|
Tcl_DString ds;
|
|
// could check status and do appropriate action like: set Error(info->s) ???
|
|
callbackInfo *info = (callbackInfo *) userarg;
|
|
Tcl_DStringInit(&ds);
|
|
int i = Cdev_Handleresult(info->tags, info->ntags, result, ds, 1);
|
|
Tcl_SetVar2(info->interp, "Control", info->s, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY);
|
|
Tcl_DStringFree(&ds);
|
|
}
|
|
|
|
// same as above, plus removes callbackinfo
|
|
void Cdev_CallbackFunctionOnce(int, void *userarg, cdevRequestObject&, cdevData &result) {
|
|
Tcl_DString ds;
|
|
// have to check status and do appropriate action like: set Error(info->s) ???
|
|
callbackInfo *info = (callbackInfo *) userarg;
|
|
Tcl_DStringInit(&ds);
|
|
int i = Cdev_Handleresult(info->tags, info->ntags, result, ds, 1);
|
|
Tcl_SetVar2(info->interp, "Control", info->s, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY);
|
|
Tcl_DStringFree(&ds);
|
|
delete info;
|
|
}
|
|
|
|
// Old way of polling, superseded by FileHandler calls, but since FD's are not working yet, still in use
|
|
void Cdev_UpdateProc(ClientData dummy) {
|
|
cdevSystem::defaultSystem().poll();
|
|
Tcl_CreateTimerHandler(200, Cdev_UpdateProc, dummy);
|
|
}
|
|
|
|
void Cdev_FileProc(ClientData, int) {
|
|
cdevSystem::defaultSystem().poll();
|
|
}
|
|
|
|
int CdevDebugCmd(ClientData, Tcl_Interp*, int, char* *) {
|
|
if(cdevdebug == 0) {
|
|
cdevdebug = 1;
|
|
}
|
|
else {
|
|
cdevdebug = 0;
|
|
}
|
|
return TCL_OK;
|
|
}
|
|
|
|
void Cdev_RegisterFD(int*, Tcl_File fd, int condition) {
|
|
printf("fd callback\n");
|
|
if(condition) {
|
|
Tcl_CreateFileHandler(fd, TCL_READABLE, Cdev_FileProc, NULL);
|
|
}
|
|
else {
|
|
Tcl_DeleteFileHandler(fd);
|
|
}
|
|
}
|
|
typedef cdevRequestObject *cdevRequestObjectPtr;
|
|
|
|
int CdevCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) {
|
|
// cdev device message {tag value} {..} cb
|
|
// cdev device message {tag value} {..} -context (tag value} {..} cb
|
|
|
|
char **devices = NULL;
|
|
int i, n, ndevices;
|
|
Tcl_DString ds;
|
|
cdevData result;
|
|
cdevCallback *cb = NULL;
|
|
callbackInfo *info;
|
|
cdevRequestObjectPtr request, *requests;
|
|
tclCdevData data;
|
|
int delinfo = 0;
|
|
|
|
if(argc < 3) {
|
|
Tcl_AppendResult(interp, "cdev: wrong # args", (char *) NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
ndevices = 0;
|
|
if(Tcl_SplitList(interp, argv[1], &ndevices, &devices) != TCL_OK) {
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if(ndevices == 1) {
|
|
request = cdevRequestObject::attachPtr(argv[1], argv[2]);
|
|
free((char*)devices);
|
|
}
|
|
else {
|
|
requests = new cdevRequestObjectPtr[ndevices];
|
|
for(n = 0; n < ndevices; n++) {
|
|
requests[n] = cdevRequestObject::attachPtr(devices[n], argv[2]);
|
|
}
|
|
}
|
|
|
|
data.parse(interp, argv, argc);
|
|
|
|
if(data.state != TCL_OK) {
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if(data.async) {
|
|
// we want to sent it async
|
|
|
|
if(ndevices == 1) {
|
|
info = new callbackInfo(interp, data.callbacktag);
|
|
if(data.tagn != 0) {
|
|
info->addtags(data.tagn, data.taglist);
|
|
}
|
|
|
|
if(strncmp(argv[2], "monitorOn", 9) == 0) {
|
|
cb = new cdevCallback(Cdev_CallbackFunction, (void *) info);
|
|
}
|
|
else if(strncmp(argv[2], "monitorOff", 10) == 0) {
|
|
delinfo = 1;
|
|
cb = new cdevCallback(NULL, NULL);
|
|
}
|
|
else {
|
|
cb = new cdevCallback(Cdev_CallbackFunctionOnce, (void *) info);
|
|
}
|
|
|
|
info->callback = cb;
|
|
|
|
if(data.hascontext) {
|
|
if(cdevdebug == 1) {
|
|
cout << "Context data: " << endl;
|
|
data.context.asciiDump(stdout);
|
|
}
|
|
if(request->setContext(data.context) != CDEV_SUCCESS) {
|
|
interp->result = "setContext error";
|
|
delete info;
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
if(cdevdebug == 1) {
|
|
cout << argv[1] << " " << argv[2] << " OutBound data: " << endl;
|
|
data.out.asciiDump(stdout);
|
|
}
|
|
|
|
if(request->sendCallback(data.out, *cb) != 0) {
|
|
delete info;
|
|
return TCL_ERROR;
|
|
}
|
|
else {
|
|
if(delinfo) delete info;
|
|
return TCL_OK;
|
|
}
|
|
}
|
|
else {
|
|
// ndevices > 1, send each one separately
|
|
int j = 0;
|
|
|
|
if(strncmp(argv[2], "monitorOn", 9) == 0) {
|
|
j = 1;
|
|
}
|
|
else if(strncmp(argv[2], "monitorOff", 10) == 0) {
|
|
j = 2;
|
|
}
|
|
|
|
for(n = 0; n < ndevices; n++) {
|
|
info = new callbackInfo(interp, devices[n], data.callbacktag);
|
|
if(data.tagn != 0) {
|
|
info->addtags(data.tagn, data.taglist);
|
|
}
|
|
if(j == 1) {
|
|
cb = new cdevCallback(Cdev_CallbackFunction, (void *) info);
|
|
}
|
|
else if(j == 2) {
|
|
delinfo = 1;
|
|
cb = new cdevCallback(NULL, NULL);
|
|
}
|
|
else {
|
|
cb = new cdevCallback(Cdev_CallbackFunctionOnce, (void *) info);
|
|
}
|
|
|
|
info->callback = cb;
|
|
|
|
if(data.hascontext) {
|
|
if(requests[n]->setContext(data.context) != 0) {
|
|
interp->result = "setContext error";
|
|
delete requests;
|
|
free((char *) devices);
|
|
delete info;
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
if(requests[n]->sendCallback(data.out, *cb) != CDEV_SUCCESS) {
|
|
delete requests;
|
|
delete info;
|
|
free((char *) devices);
|
|
return TCL_ERROR;
|
|
}
|
|
else {
|
|
if(delinfo) delete info;
|
|
}
|
|
}
|
|
delete requests;
|
|
free((char *) devices);
|
|
return TCL_OK;
|
|
}
|
|
}
|
|
|
|
// send it sync
|
|
Tcl_DStringInit(&ds);
|
|
|
|
if(ndevices == 1) {
|
|
if(data.hascontext) {
|
|
if(cdevdebug == 1) {
|
|
cout << "Context data: " << endl;
|
|
data.context.asciiDump(stdout);
|
|
}
|
|
if(request->setContext(data.context) != CDEV_SUCCESS) {
|
|
interp->result = "setContext error";
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
|
|
if(cdevdebug == 1) {
|
|
cout << argv[1] << " " << argv[2] << " OutBound data: " << endl;
|
|
data.out.asciiDump(stdout);
|
|
}
|
|
|
|
if(request->send(data.out, result) != CDEV_SUCCESS) {
|
|
sprintf(interp->result, "error in send: %s %s", argv[1], argv[2]);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if(cdevdebug == 1) {
|
|
cout << "Result data: " << endl;
|
|
result.asciiDump(stdout);
|
|
}
|
|
|
|
if(STATUS_TAG !=- 1) {
|
|
if(result.get(STATUS_TAG, &i) == CDEV_SUCCESS) {
|
|
if(i != CDEV_SUCCESS) {
|
|
if(SEVERITY_TAG !=- 1) {
|
|
Tcl_DStringFree(&ds);
|
|
result.get(SEVERITY_TAG, cs, 255);
|
|
Tcl_DStringAppend(&ds, cs, -1);
|
|
Tcl_DStringResult(interp, &ds);
|
|
}
|
|
else {
|
|
interp->result = "cdev status != 0";
|
|
}
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
}
|
|
if(Cdev_Handleresult(data.taglist, data.tagn, result, ds, 1) != TCL_OK) {
|
|
interp->result = "cannot handle cdev result";
|
|
Tcl_DStringFree(&ds);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
Tcl_DStringResult(interp, &ds);
|
|
interp->freeProc = TCL_DYNAMIC;
|
|
}
|
|
else {
|
|
// ndevices > 1
|
|
size_t valuedim;
|
|
int addbraces = 0;
|
|
for(n = 0; n < ndevices; n++) {
|
|
if(data.hascontext) {
|
|
if(requests[n]->setContext(data.context) != CDEV_SUCCESS) {
|
|
interp->result = "setContext error";
|
|
delete requests;
|
|
free((char *) devices);
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
if(requests[n]->send(data.out, result) != CDEV_SUCCESS) {
|
|
sprintf(interp->result, "error in send: %s %s", devices[n], argv[2]);
|
|
delete requests;
|
|
free((char *) devices);
|
|
return TCL_ERROR;
|
|
}
|
|
if(STATUS_TAG !=- 1) {
|
|
if(result.get(STATUS_TAG, &i) == CDEV_SUCCESS) {
|
|
if(i != CDEV_SUCCESS) {
|
|
if(SEVERITY_TAG !=- 1) {
|
|
Tcl_DStringFree(&ds);
|
|
result.get(SEVERITY_TAG, cs, 255);
|
|
Tcl_DStringAppend(&ds, cs, -1);
|
|
Tcl_DStringResult(interp, &ds);
|
|
}
|
|
else {
|
|
interp->result = "cdev status != 0";
|
|
}
|
|
delete requests;
|
|
free((char *) devices);
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
}
|
|
if(Cdev_Handleresult(data.taglist, data.tagn, result, ds, ndevices) != TCL_OK) {
|
|
interp->result = "cannot handle cdev result";
|
|
Tcl_DStringFree(&ds);
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
Tcl_DStringResult(interp, &ds);
|
|
interp->freeProc = TCL_DYNAMIC;
|
|
delete requests;
|
|
free((char *) devices);
|
|
}
|
|
return TCL_OK;
|
|
}
|
|
|
|
int CdevDirectoryCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) {
|
|
int ndevices = 0;
|
|
cdevData result;
|
|
Tcl_DString ds;
|
|
cdevCallback *cb = NULL;
|
|
callbackInfo *info;
|
|
int i;
|
|
tclCdevData data;
|
|
int delinfo = 0;
|
|
|
|
if(argc < 3) {
|
|
Tcl_AppendResult(interp, "cdevDirectory: wrong # args", (char *) NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if(argc < 3) {
|
|
Tcl_AppendResult(interp, "cdevDirectory: wrong # args", (char *) NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
cdevDevice &device = cdevDevice::attachRef("cdevDirectory");
|
|
|
|
data.parse(interp, argv-1, argc+1);
|
|
|
|
if(data.state != TCL_OK) {
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if(data.async) {
|
|
// we want to sent it async
|
|
|
|
info = new callbackInfo(interp, data.callbacktag);
|
|
if(data.tagn != 0) {
|
|
info->addtags(data.tagn, data.taglist);
|
|
}
|
|
|
|
if(strncmp(argv[2], "monitorOn", 9) == 0) {
|
|
cb = new cdevCallback(Cdev_CallbackFunction, (void *) info);
|
|
}
|
|
else if(strncmp(argv[2], "monitorOff", 10) == 0) {
|
|
delinfo = 1;
|
|
cb = new cdevCallback(NULL, NULL);
|
|
}
|
|
else {
|
|
cb = new cdevCallback(Cdev_CallbackFunctionOnce, (void *) info);
|
|
}
|
|
|
|
info->callback = cb;
|
|
|
|
if(cdevdebug == 1) {
|
|
cout << argv[1] << " " << argv[2] << " OutBound data: " << endl;
|
|
data.out.asciiDump(stdout);
|
|
}
|
|
|
|
if(device.sendCallback(argv[1], data.out, *cb) != 0) {
|
|
delete info;
|
|
return TCL_ERROR;
|
|
}
|
|
else {
|
|
if(delinfo) delete info;
|
|
return TCL_OK;
|
|
}
|
|
}
|
|
// send it sync
|
|
Tcl_DStringInit(&ds);
|
|
|
|
if(cdevdebug == 1) {
|
|
cout << argv[1] << " " << argv[2] << " OutBound data: " << endl;
|
|
data.out.asciiDump(stdout);
|
|
}
|
|
|
|
if(device.send(argv[1], data.out, result) != CDEV_SUCCESS) {
|
|
sprintf(interp->result, "error in send: %s", argv[1]);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if(cdevdebug == 1) {
|
|
cout << "Result data: " << endl;
|
|
result.asciiDump(stdout);
|
|
}
|
|
|
|
if(STATUS_TAG !=- 1) {
|
|
if(result.get(STATUS_TAG, &i) == CDEV_SUCCESS) {
|
|
if(i != CDEV_SUCCESS) {
|
|
if(SEVERITY_TAG !=- 1) {
|
|
Tcl_DStringFree(&ds);
|
|
result.get(SEVERITY_TAG, cs, 255);
|
|
Tcl_DStringAppend(&ds, cs, -1);
|
|
Tcl_DStringResult(interp, &ds);
|
|
}
|
|
else {
|
|
interp->result = "cdev status != 0";
|
|
}
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(Cdev_Handleresult(data.taglist, data.tagn, result, ds, 1) != TCL_OK) {
|
|
interp->result = "cannot handle cdev result";
|
|
Tcl_DStringFree(&ds);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
Tcl_DStringResult(interp, &ds);
|
|
interp->freeProc = TCL_DYNAMIC;
|
|
|
|
return TCL_OK;
|
|
}
|
|
|
|
extern"C"int Cdev_Init(Tcl_Interp *interp) {
|
|
|
|
// int i,fd[20],numFD = 20;
|
|
// System.getFd(fd, numFD);
|
|
// for (i=0;i<numFD;i++) {
|
|
// Cdev_RegisterFD(fd[i],1);
|
|
// }
|
|
// System.registerFdCallback(Cdev_RegisterFD);
|
|
// cdevGlobalTagTable.initialize();
|
|
|
|
|
|
if(Tcl_PkgProvide(interp, "Cdev", CDEV_VERSION) != TCL_OK) {
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
Tcl_CreateCommand(interp, "cdev", CdevCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL);
|
|
Tcl_CreateCommand(interp, "cdevDirectory", CdevDirectoryCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL);
|
|
Tcl_CreateCommand(interp, "cdevdebug", CdevDebugCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL);
|
|
|
|
Cdev_UpdateProc(NULL);
|
|
return TCL_OK;
|
|
}
|
|
|
|
|
|
|