diff --git a/initializer.c b/initializer.c new file mode 100644 index 0000000..397e0d4 --- /dev/null +++ b/initializer.c @@ -0,0 +1,139 @@ +/*--------------------------------------------------------------------------- +initializer.c + +initializer routines + +Markus Zolliker, March 2005 +---------------------------------------------------------------------------- +*/ + +#include "sics.h" +#include "initializer.h" + +typedef struct Item { + struct Item *next; + const char *type; + const char *name; + Initializer maker; + int startupOnly; +} Item; + +static Item *list = NULL; +static int startup = 1; + +void MakeInitializer(const char *type, const char *name, Initializer maker, int startupOnly) { + Item *item; + + item = calloc(1, sizeof *item); + assert(item); + item->maker = maker; + item->next = list; + item->type = type; + item->name = name; + item->startupOnly = startupOnly; + list = item; +} + +Initializer GetInitializer(const char *type, const char *name) { + Item *p, **last; + + if (startup && pServ->pReader != NULL) { + /* pServ->pReader exists: startup finished */ + startup = 0; + /* remove startup initializers */ + p = list; + last = &list; + while (p != NULL) { + if (p->startupOnly) { + *last = p->next; + free(p); + p = *last; + } else { + last = &p->next; + p = p->next; + } + } + } + p = list; + while (p != NULL && (strcasecmp(p->name, name) != 0 || strcasecmp(p->type, type) != 0)) { + p = p->next; + } + if (p) { + return p->maker; + } + return NULL; +} + +static int MakeObject(SConnection *con, SicsInterp *sics, + void *data, int argc, char *argv[]) { + CmdInitializer cmdin; + CommandList *command; + char *className; + + if (argc < 3) { + SCPrintf(con, eError, "%s needs more arguments", argv[0]); + return 0; + } + + cmdin = (CmdInitializer)GetInitializer("Object", argv[2]); + if (cmdin) { + return cmdin(con, argc, argv, ! startup); + } else { + SCPrintf(con, eError, "do not know how to make a %s object", argv[2]); + return 0; + } +} + +static int RemoveObject(SConnection *con, SicsInterp *sics, + void *data, int argc, char *argv[]) { + CmdInitializer cmdin; + CommandList *command; + char *className; + + if (argc != 2) { + SCPrintf(con, eError, "%s has 1 argument", argv[0]); + return 0; + } + + command = FindCommand(sics, argv[1]); + if (!command) { + SCPrintf(con, eError, "ERROR: %s not found", argv[1]); + return 0; + } + className = ((pDummy)command->pData)->pDescriptor->name; + cmdin = (CmdInitializer)GetInitializer("Object", className); + if (cmdin) { + /* if we have an initializer, we are allowed to remove */ + if (pServ->pExecutor && isInRunMode(pServ->pExecutor)) { + SCPrintf(con, eError, "ERROR: cannot remove %s while running", argv[1]); + return 0; + } + SCPrintf(con, eValue, "remove %s", argv[1]); + SCparChange(con); + return RemoveCommand(sics, argv[1]); + } else { + SCPrintf(con, eError, "ERROR: %s is not removable", argv[1]); + return 0; + } +} + +static void KillInitializers(void *data) { + KillDummy(data); + Item *item, *next; + + item = list; + while (item) { + next = item->next; + free(item); + item = next; + } + list = NULL; +} + +void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly) { + if (! FindCommand(pServ->pSics, "MakeObject")) { + AddCommandWithFlag(pServ->pSics, "MakeObject", MakeObject, KillInitializers, NULL, 0); + AddCommandWithFlag(pServ->pSics, "RemoveObject", RemoveObject, NULL, NULL, 0); + } + MakeInitializer("Object", driver, (Initializer)maker, startupOnly); +} diff --git a/initializer.h b/initializer.h new file mode 100644 index 0000000..d156e58 --- /dev/null +++ b/initializer.h @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------- +initializer.h + +initializer list routines + +Markus Zolliker, March 2005 +---------------------------------------------------------------------------- +*/ + +#ifndef SICSINIT_H +#define SICSINIT_H + +typedef void (*Initializer)(void); + +void MakeInitializer(const char *type, const char *name, Initializer maker, int startupOnly); + +Initializer GetInitializer(const char *type, const char *name); + +/* + MakeObject has the following syntax: + + MakeObject objectName driver [ args ... ] + +*/ +typedef int (*CmdInitializer) (SConnection *pCon, int argc, char *argv[], int dynamic); +/* + make a driver with the initializer function maker + when the dynamic argument is not 0, the command was created after startup, + i.e. the SaveStatus routine has also to write command creation code. +*/ +void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly); + +#endif