by length limited versions wherever appropriate. SKIPPED: psi/el755driv.c psi/faverage.c psi/frame.c psi/lmd200.c psi/polterwrite.c psi/psi.c psi/sanswave.c psi/sinqhmdriv.c psi/termprot.c
202 lines
4.9 KiB
C
202 lines
4.9 KiB
C
/* -------------------------------------------------------------------------
|
|
This class allows for the implementation off SICS internal interfaces
|
|
through Tcl scripts. Additionally, helper functions for supporting such
|
|
scripts are provided.
|
|
|
|
This is the first implementation which only supports saving additional
|
|
data into status files. This is the object decriptor interface.
|
|
|
|
copyright: see file COPYRIGHT
|
|
|
|
Mark Koennecke, May 2003
|
|
------------------------------------------------------------------------*/
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <tcl.h>
|
|
#include "fortify.h"
|
|
#include "splitter.h"
|
|
#include "tclintimpl.h"
|
|
/*================== our data structure ===================================*/
|
|
typedef struct {
|
|
pObjectDescriptor pDes;
|
|
pIDrivable pDriv;
|
|
char *saveScript;
|
|
FILE *fd;
|
|
} tclInt, *pTclInt;
|
|
/*======================= interface functions ============================*/
|
|
static int TclSaveStatus(void *pData, char *name, FILE * fd)
|
|
{
|
|
pTclInt self = NULL;
|
|
char pBuffer[1024];
|
|
|
|
self = (pTclInt) pData;
|
|
assert(self);
|
|
|
|
if (self->saveScript == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
if (strlen(self->saveScript) + strlen(name) + 2 >= 1023) {
|
|
fprintf(fd, "#ERROR: arguments to long for save scripting");
|
|
return 1;
|
|
}
|
|
strcpy(pBuffer, self->saveScript);
|
|
strcat(pBuffer, " ");
|
|
strcat(pBuffer, name);
|
|
self->fd = fd;
|
|
|
|
Tcl_Eval(InterpGetTcl(pServ->pSics), pBuffer);
|
|
self->fd = NULL;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void *TclGetInterface(void *pData, int id)
|
|
{
|
|
pTclInt self = NULL;
|
|
self = (pTclInt) pData;
|
|
if (self == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (id == DRIVEID) {
|
|
return self->pDriv;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*======================== data structure creation and deletion ==========*/
|
|
static pTclInt MakeTclIntData(void)
|
|
{
|
|
pTclInt pNew = NULL;
|
|
|
|
pNew = (pTclInt) malloc(sizeof(tclInt));
|
|
if (pNew == NULL) {
|
|
return NULL;
|
|
}
|
|
memset(pNew, 0, sizeof(tclInt));
|
|
pNew->pDes = CreateDescriptor("SICS Interfaces in Tcl");
|
|
pNew->pDes->SaveStatus = TclSaveStatus;
|
|
pNew->pDes->GetInterface = TclGetInterface;
|
|
pNew->pDriv = CreateDrivableInterface();
|
|
if (!pNew->pDes || !pNew->pDriv) {
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static void KillTclInt(void *pData)
|
|
{
|
|
pTclInt self = NULL;
|
|
|
|
self = (pTclInt) pData;
|
|
if (self == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (self->pDes != NULL) {
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
if (self->saveScript != NULL) {
|
|
free(self->saveScript);
|
|
}
|
|
if (self->pDriv) {
|
|
free(self->pDriv);
|
|
}
|
|
free(self);
|
|
}
|
|
|
|
/*=============== interpreter interface + helper functions =============*/
|
|
int MakeTclInt(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pTclInt pNew = NULL;
|
|
char pBuffer[132];
|
|
int iRet;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: I need a name argument for the script interface",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
pNew = MakeTclIntData();
|
|
if (pNew == NULL) {
|
|
SCWrite(pCon, "ERROR: no memory to create SICS script interface",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
iRet =
|
|
AddCommand(pSics, argv[1], TclIntAction, KillTclInt, (void *) pNew);
|
|
if (!iRet) {
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: duplicate command %s not created", argv[1]);
|
|
SCWrite(pCon, pBuffer, eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
int TclIntAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pTclInt self = NULL;
|
|
char pBuffer[1024];
|
|
char *cmd;
|
|
float val;
|
|
|
|
self = (pTclInt) pData;
|
|
assert(self);
|
|
if (argc < 2) {
|
|
if (self->pDriv->GetValue != NULL) {
|
|
val = self->pDriv->GetValue(self, pCon);
|
|
snprintf(pBuffer, 1024, "%s = %f", argv[0], val);
|
|
SCWrite(pCon, pBuffer, eValue);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: %s expects at least one argument!",
|
|
argv[0]);
|
|
SCWrite(pCon, pBuffer, eError);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "savescript") == 0) {
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: missing argument to savescript", eError);
|
|
return 0;
|
|
}
|
|
if (self->saveScript != NULL) {
|
|
free(self->saveScript);
|
|
self->saveScript = NULL;
|
|
}
|
|
self->saveScript = strdup(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "backup") == 0) {
|
|
cmd = Arg2Tcl(argc - 2, &argv[2], pBuffer, 1023);
|
|
if (cmd) {
|
|
if (self->fd != NULL) {
|
|
fprintf(self->fd, "%s\n", cmd);
|
|
}
|
|
if (cmd != pBuffer)
|
|
free(cmd);
|
|
SCSendOK(pCon);
|
|
}
|
|
return 1;
|
|
} else {
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: keyword %s to %s not recognized",
|
|
argv[1], argv[0]);
|
|
SCWrite(pCon, pBuffer, eError);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|