- Added missing hdbcommand code

This commit is contained in:
koennecke
2006-09-13 07:21:35 +00:00
parent 2f3e2d0ff0
commit 8bbdbafed8
2 changed files with 387 additions and 0 deletions

291
hdbcommand.c Normal file
View File

@ -0,0 +1,291 @@
/**
* 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);
}
/*--------------------------------------------------------------------------*/
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);
}
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);
}

96
hdbcommand.h Normal file
View File

@ -0,0 +1,96 @@
/**
* 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
*/
#ifndef HDBCOMMAND_H_
#define HDBCOMMAND_H_
#include <stdarg.h>
#include <hipadaba.h>
/*--------------- error codes ----------------------------------------------*/
#define HDCOMNOMEM -7801
#define HDBCOMNOCOM -7802
#define HDBCOMNOARGS -7803
#define HDBCOMBADARG -7804
#define HDBCOMINVARG -7805
#define HDBCOMBADOBJ -7806
/*---------------------------------------------------------------------------*/
typedef struct __hdbCommmand {
char *name;
pHdb parameters;
int (*execute)(pHdb parameters);
struct __hdbCommand *next;
struct __hdbCommand *previous;
}hdbCommand, *pHdbCommand;
/*======================= live and death ===================================*/
/**
* create a hdbCommand with an empty parameter list
* @param name The name of teh command
* @param execute The execute function for this command
* @return a fresh hdbCommand or NULL when out of memory
* */
pHdbCommand CreateHdbCommand(char *name, int (*execute)(pHdb parameters));
/**
* append a hdbCommand to a command list
* @param commandList The list to append the command to
* @param command The command to append
* @return 1 on success, a negative error code else.
*/
void AppendHdbCommandToList(pHdbCommand commandList, pHdbCommand command);
/**
* append a parameter to the parameter list
* @param command The command to append the parameter too
* @param par The parameter to append
*/
void AppendCommandParameter(pHdbCommand command, pHdb par);
/**
* delete a command list recursively
* @param commandList The command list to delete
*/
void KillHdbCommandList(pHdbCommand commandList);
/*===================== invocation ========================================*/
/**
* invoke a hdbCommand name. This does a lot: it locates the command,
* it assigne the parameter values and finally calls the execute function.
* @param commandList The command list in which to search for the command
* @param name The name of the command
* @param ... arguments to the command. ints, double, text and objects (pointers)
* are accepted as is.Arrays have to be passed in a pointers to a
* hdbValue structure. Otherwise there is not eonough information to safely
* copy array data.
* @return Negative error codes on invocation error, else the return
* value of the execute function.
*/
int HdbCommandInvoke(pHdbCommand commandList, char *name, ...);
/**
* invoke a hdbCommand name. This does a lot: it locates the command,
* it assigne the parameter values and finally calls the execute function.
* The name of the command must be in argv[0]
* @param commandList The command list in which to search for the command
* @param argc The number of arguments
* @param argv[] An array of strings holding the argument data
* @return Negative error codes on invocation error, else the return
* value of the execute function.
*/
int HdbCommandTextInvoke(pHdbCommand commandList, int argc, char *argv[]);
/**
* set a mapper which returns a void pointer for a name in order to resolve
* object references
* @param mapfunc
*/
void SetHdbComObjMapper(void *(*mapObj)(char *name));
#endif /*HDBCOMMAND_H_*/