- Added missing hdbcommand code
This commit is contained in:
291
hdbcommand.c
Normal file
291
hdbcommand.c
Normal 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,¤tPar->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
96
hdbcommand.h
Normal 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_*/
|
Reference in New Issue
Block a user