262 lines
7.2 KiB
C
262 lines
7.2 KiB
C
/*---------------------------------------------------------------------------
|
|
initializer.c
|
|
|
|
initializer routines
|
|
|
|
Markus Zolliker, March 2005
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "sics.h"
|
|
#include "initializer.h"
|
|
#include "splitter.h"
|
|
|
|
typedef struct Item {
|
|
struct Item *next;
|
|
char *type; /* "Object" for all commands created by makeobject, else something more general */
|
|
char *name; /* the name for identifying an initializer */
|
|
char *desc; /* a description of the initializer. not the same as pObjectDescriptor->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, const char *desc) {
|
|
Item *item;
|
|
|
|
item = calloc(1, sizeof *item);
|
|
assert(item);
|
|
item->maker = maker;
|
|
item->next = list;
|
|
item->type = strdup(type);
|
|
item->name = strdup(name);
|
|
item->desc = strdup(desc);
|
|
item->startupOnly = startupOnly;
|
|
list = item;
|
|
}
|
|
|
|
Initializer GetInitializer(const char *type, const char *name) {
|
|
Item *p, **last;
|
|
|
|
if (startup && !ServerIsStarting(pServ)) {
|
|
/* 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;
|
|
}
|
|
}
|
|
}
|
|
for (p = list; p != NULL; p = p->next) {
|
|
if (strcasecmp(p->name, name) == 0 && strcasecmp(p->type, type) == 0) {
|
|
return p->maker;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static int MakeObject(SConnection *con, SicsInterp *sics,
|
|
void *data, int argc, char *argv[]) {
|
|
CmdInitializer cmdin;
|
|
|
|
if (argc < 3) {
|
|
SCPrintf(con, eError, "ERROR: should be: %s <object> <type> ...", argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
cmdin = (CmdInitializer)GetInitializer("Object", argv[2]);
|
|
if (cmdin) {
|
|
return cmdin(con, argc, argv, strcasecmp(argv[0],"makeobject") == 0);
|
|
} else {
|
|
SCPrintf(con, eError, "do not know how to make a %s object", argv[2]);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int DriverList(SConnection *con, SicsInterp *sics,
|
|
void *data, int argc, char *argv[]) {
|
|
Item *p;
|
|
char *name, *type;
|
|
|
|
if (argc < 2 || strcasecmp(argv[1], "list") == 0) {
|
|
for (p = list; p != NULL; p = p->next) {
|
|
if (argc < 3) {
|
|
SCPrintf(con, eStatus, "%s %s %s", p->type, p->name, p->desc);
|
|
} else if (strcasecmp(argv[2], p->type) == 0) {
|
|
SCPrintf(con, eStatus, "%s %s", p->name, p->desc);
|
|
}
|
|
}
|
|
} else {
|
|
if (argc == 2) {
|
|
name = argv[1];
|
|
type = "Object";
|
|
} else {
|
|
name = argv[2];
|
|
type = argv[1];
|
|
}
|
|
p = list;
|
|
while (p != NULL && (strcasecmp(p->type, type) != 0 || strcasecmp(p->name, name) != 0)) {
|
|
p = p->next;
|
|
}
|
|
if (p) {
|
|
SCPrintf(con, eValue, "%s", p->desc);
|
|
} else {
|
|
SCPrintf(con, eValue, "notfound");
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int RemoveObject(SConnection *con, SicsInterp *sics,
|
|
void *data, int argc, char *argv[]) {
|
|
CmdInitializer cmdin;
|
|
CommandList *command;
|
|
char *className;
|
|
char shortClassName[32];
|
|
char *p;
|
|
int removeAllowed;
|
|
|
|
if (argc != 2) {
|
|
SCPrintf(con, eError, "ERROR: should be: %s <object>", argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
command = FindCommand(sics, argv[1]);
|
|
if (!command) {
|
|
SCPrintf(con, eError, "ERROR: %s not found", argv[1]);
|
|
return 0;
|
|
}
|
|
|
|
if (((pDummy)command->pData)->pDescriptor->creationCommand != NULL) {
|
|
/* if there is a creationCommand, we are allowed to remove */
|
|
removeAllowed = 1;
|
|
} else {
|
|
/* if we have an initializer: we are also allowed to remove */
|
|
className = ((pDummy)command->pData)->pDescriptor->name;
|
|
cmdin = (CmdInitializer)GetInitializer("Object", className);
|
|
if (cmdin == 0) {
|
|
/* allow also a longer descriptor starting with the initializer name and a blank */
|
|
p = strchr(className, ' ');
|
|
if (p) {
|
|
snprintf(shortClassName, sizeof shortClassName, "%.*s", p - className, className);
|
|
cmdin = (CmdInitializer)GetInitializer("Object", shortClassName);
|
|
}
|
|
}
|
|
removeAllowed = (cmdin != NULL);
|
|
}
|
|
if (removeAllowed) {
|
|
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 int SaveCreationCommands(void *object, char *name, FILE *fil) {
|
|
CommandList *p;
|
|
ObjectDescriptor *desc;
|
|
int printHeader = 0;
|
|
|
|
for (p = pServ->pSics->pCList; p != NULL; p = p->pNext) {
|
|
desc = ((pDummy)p->pData)->pDescriptor;
|
|
if (desc->creationCommand && strcmp(desc->creationCommand, "0") != 0) {
|
|
if (printHeader == 0) {
|
|
printHeader = 1;
|
|
fprintf(fil, "\n#--- BEGIN creation commands\n");
|
|
}
|
|
fprintf(fil, "%s\n", desc->creationCommand);
|
|
}
|
|
}
|
|
if (printHeader == 1) {
|
|
fprintf(fil, "#--- END creation commands\n\n");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int CreationCommand(SConnection *con, SicsInterp *sics,
|
|
void *data, int argc, char *argv[]) {
|
|
CmdInitializer cmdin;
|
|
CommandList *command;
|
|
char *className;
|
|
char shortClassName[32];
|
|
char *p;
|
|
int removeAllowed;
|
|
ObjectDescriptor *desc;
|
|
|
|
if (argc < 2) {
|
|
SCPrintf(con, eError, "ERROR: should be: %s <object> [<creation command>]", argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
command = FindCommand(sics, argv[1]);
|
|
if (!command) {
|
|
SCPrintf(con, eError, "ERROR: %s not found", argv[1]);
|
|
return 0;
|
|
}
|
|
desc = ((pDummy)command->pData)->pDescriptor;
|
|
if (argc < 3) {
|
|
if (desc->creationCommand != NULL) {
|
|
SCPrintf(con, eValue, "%s", desc->creationCommand);
|
|
} else {
|
|
SCPrintf(con, eValue, "<static object>");
|
|
}
|
|
} else {
|
|
if (! desc->creationCommand) {
|
|
SCPrintf(con, eValue, "ERROR: %s is a static object", argv[1]);
|
|
return 0;
|
|
}
|
|
free(desc->creationCommand);
|
|
desc->creationCommand = Arg2Tcl(argc - 2, argv + 2, NULL, -1);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static void KillInitializers(void *data) {
|
|
KillDummy(data);
|
|
Item *item, *next;
|
|
|
|
item = list;
|
|
while (item) {
|
|
next = item->next;
|
|
if (item->name) free(item->name);
|
|
if (item->type) free(item->type);
|
|
if (item->desc) free(item->desc);
|
|
free(item);
|
|
item = next;
|
|
}
|
|
list = NULL;
|
|
}
|
|
|
|
void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly, const char *desc) {
|
|
MakeInitializer("Object", driver, (Initializer)maker, startupOnly, desc);
|
|
}
|
|
|
|
void InitializerInit(void) {
|
|
pDummy cc = NULL;
|
|
AddCommandWithFlag(pServ->pSics, "MakeObject", MakeObject, KillInitializers, NULL, 0);
|
|
AddCommandWithFlag(pServ->pSics, "MakeStaticObject", MakeObject, NULL, NULL, 0);
|
|
AddCommandWithFlag(pServ->pSics, "RemoveObject", RemoveObject, NULL, NULL, 0);
|
|
AddCommandWithFlag(pServ->pSics, "DriverList", DriverList, NULL, NULL, 0);
|
|
cc = CreateDummy("creation commands");
|
|
cc->pDescriptor->SaveStatus = SaveCreationCommands;
|
|
AddCommandWithFlag(pServ->pSics, "CreationCommand", CreationCommand,
|
|
KillDummy, cc, 0);
|
|
}
|