Files
sics/hdbcommand.c
koennecke 78fce0127d - Added a SICS to Hipadaba adapter
- Added a separate polling module to SICS
2006-12-07 14:04:17 +00:00

292 lines
9.3 KiB
C

/**
* This module implements a generalized scheme for executing functions.
* Functions are described by a special data structure containing the
* parameters as a Hipadaba list and and an execute function which implements
* the actual operation. This is augmented by list mechanisms in order to
* allow for a list of functions. This shall facilitate a couple of things:
* - when functions are defined in such a structured form, general invocation
* functions can be devised for handling the interpreter interface.
* - The set of functions of an object can be configured and extended at
* runtime.
* - A common usage case: execute a function with the same arguments, can be
* easily catered for.
* All this is not new and was pioneered in the language self or other
* dynamic object systems.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, September 2006
*/
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <hdbcommand.h>
/*-------------------------------------------------------------------------*/
static int debug = 1;
/* ============================= live and death ============================*/
pHdbCommand CreateHdbCommand(char *name, int (*execute)(pHdb parameters)){
pHdbCommand result = NULL;
assert(name != NULL);
assert(execute != NULL);
result = malloc(sizeof(hdbCommand));
if(result == NULL){
return NULL;
}
memset(result,0,sizeof(hdbCommand));
result->name = strdup(name);
if(result->name == NULL){
free(result);
return NULL;
}
result->execute = execute;
return result;
}
/*--------------------------------------------------------------------------*/
void AppendHdbCommandToList(pHdbCommand commandList, pHdbCommand command){
pHdbCommand current = NULL;
assert(commandList != NULL);
assert(command != NULL);
current = commandList;
while(current->next != NULL){
current = (pHdbCommand)current->next;
}
command->previous = (struct __hdbCommand *)current;
current->next = (struct __hdbCommand *)command;
command->next = NULL;
}
/*--------------------------------------------------------------------------*/
void AppendCommandParameter(pHdbCommand command, pHdb par){
assert(command != NULL);
assert(par != NULL);
AddHipadabaChild(command->parameters,par,NULL);
}
/*--------------------------------------------------------------------------*/
void KillHdbCommandList(pHdbCommand commandList){
pHdbCommand next = NULL, current = NULL;
assert(commandList != NULL);
current = commandList;
next = (pHdbCommand)current->next;
while(current != NULL){
if(current->name != NULL){
free(current->name);
}
if(current->parameters != NULL){
DeleteHipadabaNode(current->parameters,NULL);
}
free(current);
current = next;
if(current != NULL){
next = (pHdbCommand)current->next;
} else {
next = NULL;
}
}
}
/*======================= Invocation =======================================*/
static pHdbCommand locateCommand(pHdbCommand commandList, char *name){
pHdbCommand current = NULL;
current = commandList;
while(current != NULL){
if(strcmp(current->name,name) == 0) {
return current;
}
current = (pHdbCommand)current->next;
}
return NULL;
}
/*---------------------------------------------------------------------------*/
int HdbCommandInvoke(pHdbCommand commandList, char *name, ...){
va_list ap;
pHdbCommand toInvoke = NULL;
pHdb currentPar = NULL;
char *txt = NULL;
hdbValue *v = NULL;
va_start(ap,name);
toInvoke = locateCommand(commandList,name);
if(toInvoke == NULL){
return HDBCOMNOCOM;
}
currentPar = toInvoke->parameters;
while(currentPar != NULL){
/*
* I cannot call a function for this as ap would be undefined after
* a call to a function here
*/
switch(currentPar->value.dataType){
case HIPNONE:
break;
case HIPINT:
currentPar->value.v.intValue = va_arg(ap,int);
if(debug == 1){
printf("Read %d for parameter %s\n",
currentPar->value.v.intValue, currentPar->name);
}
break;
case HIPFLOAT:
currentPar->value.v.doubleValue = va_arg(ap,double);
if(debug == 1){
printf("Read %lf for parameter %s\n",
currentPar->value.v.doubleValue, currentPar->name);
}
break;
case HIPTEXT:
txt = va_arg(ap,char *);
if(currentPar->value.v.text != NULL){
free(currentPar->value.v.text);
}
currentPar->value.v.text = strdup(txt);
if(debug == 1){
printf("Read %s for parameter %s\n",
currentPar->value.v.text, currentPar->name);
}
break;
case HIPOBJ:
currentPar->value.v.obj = va_arg(ap,void *);
break;
case HIPINTAR:
case HIPINTVARAR:
case HIPFLOATAR:
case HIPFLOATVARAR:
v = (hdbValue *)va_arg(ap,void *);
copyHdbValue(v,&currentPar->value);
break;
default:
assert(0);
break;
}
currentPar = currentPar->next;
}
va_end(ap);
return toInvoke->execute(toInvoke->parameters);
}
/*-------------------------------------------------------------------------*/
static void *(*objMap)(char *name) = NULL;
/*-------------------------------------------------------------------------*/
void SetHdbComObjMapper(void *(*mapObj)(char *name)){
objMap = mapObj;
}
/*-------------------------------------------------------------------------*/
static int readParArguments(pHdb parNode, int argc, char *argv[]){
int i, intVal;
double doVal;
switch(parNode->value.dataType){
case HIPNONE:
return 0;
break;
case HIPINT:
if(argc < 1){
return HDBCOMNOARGS;
}
if(sscanf(argv[0],"%d",&parNode->value.v.intValue) != 1){
return HDBCOMBADARG;
}
return 1;
break;
case HIPFLOAT:
if(argc < 1){
return HDBCOMNOARGS;
}
if(sscanf(argv[0],"%lf",&parNode->value.v.doubleValue) != 1){
return HDBCOMBADARG;
}
return 1;
break;
case HIPOBJ:
if(objMap != NULL){
parNode->value.v.obj = objMap(argv[0]);
if(parNode->value.v.obj == NULL){
return HDBCOMBADOBJ;
} else {
return 1;
}
}
return 0;
break;
case HIPTEXT:
if(argc < 1){
return HDBCOMNOARGS;
}
if(parNode->value.v.text != NULL){
free(parNode->value.v.text);
}
parNode->value.v.text = strdup(argv[0]);
return 1;
break;
case HIPINTAR:
if(parNode->value.arrayLength > argc){
return HDBCOMNOARGS;
}
for(i = 0; i < parNode->value.arrayLength; i++){
if(sscanf(argv[i],"%d",&intVal) != 1){
return HDBCOMBADARG;
}
parNode->value.v.intArray[i] = intVal;
}
return parNode->value.arrayLength;
break;
case HIPFLOATAR:
if(parNode->value.arrayLength > argc){
return HDBCOMNOARGS;
}
for(i = 0; i < parNode->value.arrayLength; i++){
if(sscanf(argv[i],"%lf",&doVal) != 1){
return HDBCOMBADARG;
}
parNode->value.v.floatArray[i] = doVal;
}
return parNode->value.arrayLength;
break;
default:
/*
* I cannot process such variables
*/
return HDBCOMINVARG;
break;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int HdbCommandTextInvoke(pHdbCommand commandList, int argc, char *argv[]){
pHdbCommand toInvoke = NULL;
pHdb currentPar = NULL;
int argPointer, status;
assert(commandList != NULL);
if(argc < 1){
return HDBCOMNOARGS;
}
toInvoke = locateCommand(commandList,argv[0]);
if(toInvoke == NULL){
return HDBCOMNOCOM;
}
currentPar = toInvoke->parameters;
argPointer = 1;
while(currentPar != NULL){
status = readParArguments(currentPar,argc-argPointer,
&argv[argPointer]);
if(status < 0){
return status;
} else {
argPointer += status;
}
currentPar = currentPar->next;
}
return toInvoke->execute(toInvoke->parameters);
}