Files
sicspsi/pardef.c
koennecke a5f315b56a - Added Sycamore protocol and command context to SICS
- Added sinfo to SICS
- Added driver for TCP/IP Astrium velocity selector
- Added driver for TCP/IP Astrium chopper controller
2005-12-22 22:16:13 +00:00

1149 lines
28 KiB
C

/*---------------------------------------------------------------------------
pardef.c
my way to define and handle object parameters
What is a bit unusual, is the long list of static variables in this
module. This design allows short argument lists.
Markus Zolliker, March 2005
----------------------------------------------------------------------------
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <fortify.h>
#include <ctype.h>
#include "logger.h"
#include "pardef.h"
#include "sugar.h"
#include "commandlog.h"
#define ILLNUM -2
#define ILLARGC -3
#define AMBIGUOS -4
#define ILLPRIV -5
#define BADLOG -6
#define UNKPAR -7
typedef enum { NO_OP, FMT_OP, SET_OP, GET_OP, INIT_OP } ParOp;
static ParData *obj = NULL;
static ParAct act;
static ParAct action;
static char *parName;
static int cmdArgc;
static char **cmdArgs;
static char *thisPar;
static int returnValue;
static SConnection *sicsConnection;
static char *outputFormat;
static int access;
static FILE *saveFile;
static int doit;
static char *listTail;
static char **enumList;
static char *logName;
static time_t now;
static ParInfo *par;
static float floatValue;
static char combiName[80];
static char *grpFmt;
static char *loggerDir = NULL;
static int showTime = 0;
static int exact;
void ParKill(void *object);
static ParClass parClass={"Par", sizeof(ParData), 0, {&parClass}};
/*----------------------------------------------------------------------------*/
void *ParCast(ParClass *class, void *object) {
ParClass *t;
if (! object) return NULL;
t = ((ParData *)object)->class;
assert(t->base[0] == &parClass);
if (t && t->base[class->level] == class) {
return object;
} else {
return NULL;
}
}
/*----------------------------------------------------------------------------*/
void *ParCheck(ParClass *class, void *object) {
ParClass *t;
assert(object);
t = ((ParData *)object)->class;
assert(t->base[0] == &parClass);
assert(t && t->base[class->level] == class);
return object;
}
/*----------------------------------------------------------------------------*/
void *ParMakeClass(ParClass *class, ParClass *base) {
int i;
if (class->base[0] == NULL) { /* initialize */
if (base == NULL) {
base = &parClass;
}
assert(class->size >= base->size);
for (i=0; i<=base->level; i++) {
class->base[i] = base->base[i];
}
assert(i<PAR_LEVELS);
class->base[i] = class;
class->level = i;
} else if (base) { /* check */
for (i=0; i<=base->level; i++) {
assert(class->base[i] == base->base[i]);
}
assert(class->base[i] == class);
assert(class->level == i);
}
return class;
}
/*--------------------------------------------------------------------------*/
int ParPrintf(void *object, int iOut, const char *fmt, ...) {
va_list ap;
char buf0[128];
int l;
char *buf, *dyn = NULL;
SConnection *con;
ParData *pobj = object;
con = NULL;
if (pobj == NULL) {
if (obj) {
if (sicsConnection) {
con = sicsConnection;
} else {
pobj = obj;
}
}
}
if (!con && pobj) {
con = SCLoad(&pobj->conn);
if (!con && iOut < 0) return 0;
}
if (iOut < 0 && (!pobj || -iOut > pobj->verbose)) return 0;
if (iOut<0) iOut=eStatus;
va_start(ap, fmt);
l = vsnprintf(buf0, sizeof(buf0), fmt, ap);
va_end(ap);
if (l >= sizeof buf0) {
/* we have probably a C99 conforming snprintf and need a larger buffer */
dyn = malloc(l+1);
if (dyn != NULL) {
va_start(ap, fmt);
vsnprintf(dyn, l+1, fmt, ap);
va_end(ap);
}
buf = dyn;
} else {
buf = buf0;
}
if (con) {
SCWrite(con, buf, iOut); /* writes to command log when user or manager */
} else if (iOut >= 0) {
WriteToCommandLog(">", buf); /* no connection, write to commandlog only */
}
if (dyn) free(dyn);
return 1;
}
/*-------------------------------------------------------------------------*/
static void ParDo(SConnection *con, ParData *o, ParAct a, char *parName) {
act = a;
action = a;
sicsConnection = con;
if (parName && strcmp(parName, "*") == 0) {
thisPar = "";
} else {
thisPar = parName;
}
returnValue = 0;
par = NULL;
grpFmt = NULL;
assert(obj==NULL);
obj = o;
obj->pardef(obj);
obj = NULL;
}
/*--------------------------------------------------------------------------*/
char *ParArg2Text(int argc, char *argv[], char *res, int maxsize) {
int i, l;
char *p;
if (res == NULL) {
maxsize = 0;
for (i=0; i<argc; i++) {
maxsize += strlen(argv[i]) + 1;
}
res=malloc(maxsize);
if (!res) return NULL;
}
maxsize--;
*res='\0';
if (argv[0]) {
strncat(res, argv[0], maxsize);
}
p = res;
for (i=1; i<argc; i++) {
l = strlen(p);
p += l;
maxsize -= l;
if (maxsize == 0) return res;
*p=' ';
p++;
maxsize--;
*p='\0';
strncat(p, argv[i], maxsize);
}
return res;
}
/*-------------------------------------------------------------------------*/
static int ParSaveAll(void *object, char *name, FILE *fil) {
ParData *o = ParCheck(&parClass, object);
saveFile = fil;
assert(0==strcasecmp(o->name, name));
if (o->creationCmd) {
fprintf(fil, "if {[catch { %s }] == 0} {\n", o->creationCmd);
}
ParDo(0, o, PAR_SAVE, NULL);
if (o->creationCmd) {
fprintf(fil, "}\n");
}
return returnValue;
}
/*--------------------------------------------------------------------------*/
int ParLog(void *object) {
ParData *o = ParCheck(&parClass, object);
int next;
now = time(NULL);
next = now - (o->logTime / o->period + 1) * o->period;
if (next >= 0) {
showTime = 1;
ParDo(0, o, PAR_LOG, NULL);
o->logTime = now;
o->logPending = 0;
}
return next;
}
/*-------------------------------------------------------------------------*/
static int ParCallBack(int event, void *eventData, void *userData,
commandContext cc) {
char *pBuf = (char *)eventData;
SConnection *con = (SConnection *)userData;
if (event == VALUECHANGE) {
SCPushContext2(con,cc);
SCWrite(con,pBuf,eValue);
SCPopContext(con);
return 1;
}
return 1;
}
/*----------------------------------------------------------------------------*/
static int ParOutError(SConnection *con, ParData *o) {
switch (returnValue) {
case AMBIGUOS:
SCPrintf(con, eError, "ERROR: doubly defined parameter %s.%s", o->name, thisPar);
break;
case ILLPRIV:
SCPrintf(con, eError, "ERROR: insufficient privilege to change %s.%s", o->name, thisPar);
break;
case ILLNUM:
SCPrintf(con, eError, "ERROR: illegal value", o->name, cmdArgs[0]);
break;
case ILLARGC:
SCPrintf(con, eError, "ERROR: illegal number of arguments for %s %s", o->name, thisPar);
break;
case BADLOG:
SCPrintf(con, eError, "ERROR: can not create log directory for %s %s", o->name, thisPar);
break;
case UNKPAR:
SCPrintf(con, eError, "ERROR: %s %s is unknown", o->name, thisPar);
break;
/*
case BUSY:
SCPrintf(con, eError, "ERROR: %s busy", o->name);
break;
*/
default:
if (returnValue < 0) {
return -1;
} else {
return 1;
}
}
return -1;
}
/*----------------------------------------------------------------------------*/
static void ParListSugar(SConnection *con, ParData *o) {
ParInfo *p;
char buf[512];
int l, i;
char *sugar;
p = o->infoList;
l = snprintf(buf, sizeof buf, "%s sugar =", o->name);
while (p != NULL) {
if (p->log) {
sugar = LoggerName(p->log);
if (strchr(sugar, '.') == NULL && strcmp(sugar, o->name) != 0) {
i = snprintf(buf + l, sizeof buf - l, " %s", sugar);
if ( i<=0 ) break;
l += i;
if (l >= sizeof buf - 1) break;
}
}
p = p->next;
}
SCWrite(con, buf, eStatus);
}
/*----------------------------------------------------------------------------*/
static int ParExecute(SConnection *con, SicsInterp *sics, void *object, int argc, char *argv[]) {
static char *empty[1]={""};
long id;
int iret, logIt = 0;
ParData *o = ParCheck(&parClass, object);
char *setArgv[2];
if (SCGetRights(con) <= usUser) {
SCSave(&o->conn, con);
}
if (argc>1) thisPar = argv[1];
if (argc >= 2 && 0==strcasecmp(argv[1], "list")) {
cmdArgc = argc - 2;
cmdArgs = argv + 2;
ParDo(con, o, PAR_LIST, NULL);
return 1;
}
if (argc == 1) { /* no args */
ParDo(con, o, PAR_SHOW, "");
if (returnValue == 0) {
SCSendOK(con);
returnValue = 1;
}
} else if ((0 == strcasecmp(argv[1], "log") || 0 == strcasecmp(argv[1], "unlog"))) {
if (argc < 3) {
returnValue = ILLARGC;
thisPar = argv[1];
} else {
cmdArgc = argc - 3;
cmdArgs = argv + 3;
doit = toupper(argv[1][0]) != 'U';
exact = 1;
ParDo(con, o, PAR_LOGSWITCH, argv[2]);
}
} else if ((0 == strcasecmp(argv[1], "save") || 0 == strcasecmp(argv[1], "unsave"))) {
if (argc != 3) {
returnValue = ILLARGC;
} else {
doit = toupper(argv[1][0]) != 'U';
ParDo(con, o, PAR_SAVESWITCH, argv[2]);
}
SCparChange(con);
} else if (strcmp(argv[1],"interest") == 0) {
if (!o->pCall) {
o->pCall = CreateCallBackInterface();
}
assert(o->pCall);
id = RegisterCallback(o->pCall, SCGetContext(con),VALUECHANGE, ParCallBack, con, NULL);
SCRegister(con, pServ->pSics, o->pCall, id);
SCSendOK(con);
return 1;
} else if (strcmp(argv[1],"uninterest") == 0) {
if (o->pCall) {
RemoveCallback2(o->pCall, con);
}
SCSendOK(con);
return 1;
} else if (strcmp(argv[1],"sugar") == 0) {
ParListSugar(con, o);
return 1;
} else {
if (strcmp(argv[1], "=") == 0) {
cmdArgc = argc - 2;
cmdArgs = argv + 2;
ParDo(con, o, PAR_SET, "");
logIt = 1;
} else {
if (argc == 2) {
ParDo(con, o, PAR_SHOW, argv[1]);
} else {
cmdArgc = argc - 2;
cmdArgs = argv + 2;
ParDo(con, o, PAR_SET, argv[1]);
logIt = 1;
}
/* parameter not found, try to use args as set value for pure object
not a very good idea: a typo in a parameter name will change pure value
--> use always '='
if (returnValue == 0) {
cmdArgc = argc - 1;
cmdArgs = argv + 1;
errPar = thisPar;
ParDo(con, o, PAR_SET, "");
if (returnValue <= 0) {
thisPar = errPar;
returnValue = UNKPAR;
}
}
*/
}
}
if (returnValue == 0) {
returnValue = UNKPAR;
}
iret = ParOutError(con, o);
if (logIt) ParLog(o); /* log changes */
return iret;
}
/*----------------------------------------------------------------------------*/
static void KillLogger(ParInfo *par) {
if (par->log != NULL) {
LoggerKill(par->log);
if (par->sugarStatus == 1) {
RemoveCommand(pServ->pSics, LoggerName(par->log));
par->sugarStatus = 0;
}
par->log = NULL;
}
}
/*----------------------------------------------------------------------------*/
int ParSwitchLog(int on, char *name) {
char buf[80], alias[80];
KillLogger(par);
if (on) {
if (par->name[0] == '\0') {
snprintf(buf, sizeof buf, "%s", obj->name);
} else {
snprintf(buf, sizeof buf, "%s.%s", obj->name, par->name);
}
if (name == NULL) {
name = buf;
}
if (loggerDir == NULL) {
loggerDir = IFindOption(pSICSOptions, "LoggerDir");
if (loggerDir == NULL) loggerDir="./";
LoggerSetDir(loggerDir);
}
par->log = LoggerMake(name, obj->period, exact);
if (par->log == NULL) {
return BADLOG;
}
if (par->sugarStatus == 0 && name != buf && strcmp(name,buf) != 0) {
snprintf(alias, sizeof alias, "%s %s", obj->name, par->name);
par->sugarStatus = SugarMake(name, alias);
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
void ParFind(void) {
ParInfo *p, **last, **endList;
assert(obj);
if (par == NULL) {
last = &obj->infoList;
par = *last;
} else {
last = &par->next;
}
if (par) {
/* start search after the actual parameter */
p = par->next;
while (p != NULL && 0 != strcmp(p->name, parName)) {
p = p->next;
}
} else {
p = NULL;
}
if (p == NULL) { /* not found: search again from list head */
p = obj->infoList;
while (p != NULL && 0 != strcmp(p->name, parName)) {
if (p == par) {
p = NULL;
break;
}
p = p->next;
}
if (p == NULL) {
p = calloc(1, sizeof *p);
if (p == NULL) return;
p->name = parName;
p->log = NULL;
p->saveIt = 0;
p->saveLog = 0;
p->state = PAR_ALWAYS_READY;
p->next = *last;
*last = p;
}
}
par = p;
}
/*--------------------------------------------------------------------------*/
long ParText2Int(char *text) {
long num = 0;
if (strcasecmp(text, "undefined") == 0) {
return PAR_LNAN;
}
if (enumList) {
while (enumList[num] != NULL) {
if (strcasecmp(enumList[num],text) == 0) {
return num;
}
num++;
}
}
return -1;
}
/*--------------------------------------------------------------------------*/
char *ParInt2Text(int num) {
int i;
static char buf[12];
if (num == PAR_LNAN) {
return "undefined";
}
if (! enumList) return NULL;
for (i = 0; i <= num; i++) {
if (enumList[i] == NULL) {
return NULL;
}
}
return enumList[num];
}
/*----------------------------------------------------------------------------*/
void ParGroup(char *groupFmt) {
grpFmt = groupFmt;
}
/*----------------------------------------------------------------------------*/
void ParName(char *name) {
if (grpFmt && *grpFmt) {
snprintf(combiName, sizeof combiName, grpFmt, name);
parName = combiName;
} else {
parName = name;
}
ParFind();
outputFormat = NULL;
action = act;
assert(obj);
switch (act) {
case PAR_SHOW:
case PAR_SET:
enumList = NULL;
if (0==strcasecmp(name, thisPar)) {
access = -1;
} else {
action = PAR_NOOP;
}
return;
case PAR_LIST:
enumList = NULL;
listTail = NULL;
doit = -1;
return;
case PAR_LOG:
return;
case PAR_LOGSWITCH:
if (0==strcasecmp(name, thisPar)) {
access = -1;
} else {
action = PAR_NOOP;
}
return;
case PAR_SAVESWITCH:
if (0==strcasecmp(name, thisPar)) {
access = -1;
} else {
action = PAR_NOOP;
}
return;
case PAR_INIT:
/* for save: use -1 as default value */
access = -1;
doit = -1;
logName = ""; /* log by default */
exact = 1; /* exact by default */
return;
case PAR_GET:
if (0 != strcasecmp(name, thisPar)) {
action = PAR_NOOP;
}
return;
case PAR_SAVE:
case PAR_KILL:
case PAR_NOOP:
return;
}
}
/*----------------------------------------------------------------------------*/
static int RestoreMode(void) {
return (pServ->pReader && (SCGetRights(sicsConnection) <= usInternal));
}
/*----------------------------------------------------------------------------*/
ParOp ParWhat(int numeric) {
static char buf[80];
char *sp, *lname;
int i;
ParOp op;
int on;
assert(obj);
switch (action) {
case PAR_LIST:
if (doit < 0) {
if (listTail && cmdArgc == 0) {
doit = 1;
} else {
doit = 0;
}
}
if (doit || (cmdArgc > 0 && 0 == strcasecmp(cmdArgs[0], "all"))) return FMT_OP;
break;
case PAR_LOG:
if (par && par->log) {
return FMT_OP;
}
break;
case PAR_LOGSWITCH:
if (cmdArgc > 1) {
returnValue = ILLARGC;
break;
}
if (returnValue) {
returnValue = AMBIGUOS;
break;
}
if (par) {
returnValue = 1;
if (cmdArgc > 0) {
lname = cmdArgs[0];
} else {
lname = NULL;
}
par->saveLog = 1;
ParSwitchLog(doit, lname);
LoggerSetNumeric(par->log, numeric);
SCparChange(sicsConnection);
return NO_OP;
}
break;
case PAR_SAVESWITCH:
if (cmdArgc > 1) {
returnValue = ILLARGC;
break;
}
if (returnValue) {
returnValue = AMBIGUOS;
break;
}
if (par) {
returnValue = 1;
par->saveIt = doit;
return NO_OP;
}
break;
case PAR_INIT:
if (! RestoreMode()) {
if (access < 0) {
access = usInternal;
}
if (doit < 0) {
if (access == usInternal) {
doit = 0;
} else {
doit = 1;
}
}
if (doit) { /* set save flag */
if (par) {
par->saveIt = 1;
}
}
}
if (logName) { /* set log */
if (par) {
if (logName[0] != '\0') {
lname = logName;
} else {
lname = NULL;
}
ParSwitchLog(1, lname);
LoggerSetNumeric(par->log, numeric);
}
}
return INIT_OP;
case PAR_SHOW:
if (returnValue) {
returnValue = AMBIGUOS;
break;
}
returnValue = 1;
return FMT_OP;
case PAR_SET:
if (returnValue) {
returnValue = AMBIGUOS;
break;
}
if (access < 0) {
access = usInternal;
}
if (access < SCGetRights(sicsConnection)) {
returnValue = ILLPRIV;
break;
}
returnValue = 1;
return SET_OP;
case PAR_SAVE:
if (parName[0] == '\0') {
parName = "*";
}
if (par->saveLog) {
if (par->log) {
fprintf(saveFile, " %s log %s %s\n", obj->name, parName, LoggerName(par->log));
} else {
fprintf(saveFile, " %s unlog %s\n", obj->name, parName);
}
}
if (par && par->saveIt) {
return FMT_OP;
}
break;
case PAR_GET:
if (returnValue) {
returnValue = AMBIGUOS;
break;
}
return GET_OP;
default:
return NO_OP;
}
action = PAR_NOOP; /* for the result of ParActionIs */
return NO_OP;
}
/*----------------------------------------------------------------------------*/
void ParOut(char *buf) {
int l, i, j, m, ln, lp, iret;
char *p;
char buffer[256];
char *endp;
char *pnam;
char *sep;
char *saved, *logged;
time_t last;
assert(obj);
assert(outputFormat==NULL);
switch (action) {
case PAR_LIST:
if (par->log) {
snprintf(buffer, sizeof buffer, "%s", LoggerName(par->log));
} else {
if (parName[0] != '\0') {
snprintf(buffer, sizeof buffer, "%s.%s", obj->name, parName);
} else {
snprintf(buffer, sizeof buffer, "%s", obj->name);
}
}
if (enumList) {
i = strtol(buf, &endp, 0);
if (endp != buf) {
listTail = ParInt2Text(i); /* overwrite listTail */
}
}
p = buf;
/* find dot or end of number */
while (*p == ' ') p++; /* skip blanks */
i = 0;
if (p[i] == '-') i++;
j = i;
while (p[i] >= '0' && p[i] <='9') i++;
l = strlen(p);
ln = strlen(buffer) - strlen(obj->name);
if (i != j && (buf[i] == '.' || buf[i] <= ' ')) {
l += 16 - i - ln; /* decimal point or end of number at least 16 chars after object name */
lp = strlen(p);
if (l < lp) l = lp;
m = 23 - l - ln; /* unit/comment at least 23 chars after object name */
} else { /* non numeric value */
l = 21 - ln; /* text right justified if possible */
/* m = 1; */
m = 23 - l - ln;
}
if (m < 1) m = 1;
if (listTail == NULL) listTail = "";
m += strlen(listTail);
if (l <= 0) l = 1;
saved = "";
logged = "";
if (cmdArgc > 0 && 0 == strcasecmp(cmdArgs[0], "all")) {
if (!par->log) {
logged = " (not logged)";
}
if (par->saveIt) {
saved = " (saved)";
}
}
ParPrintf(NULL, eStatus, "%s %*s%*s%s%s", buffer, l, p, m, listTail, logged, saved);
break;
case PAR_SHOW:
if (parName[0]) { p=" "; } else { p=""; }
ParPrintf(NULL, eValue, "%s%s%s = %s", obj->name, p, parName, buf);
break;
case PAR_SET:
if (parName[0]) { p=" "; } else { p=""; }
ParPrintf(NULL, eValue, "%s%s%s = %s", obj->name, p, parName, buf);
if (!obj->logPending) {
obj->logPending = 1;
TaskRegister(pServ->pTasker, ParLog, NULL, NULL, obj, 0); /* schedule ParLog */
}
break;
case PAR_LOG:
if (par->log) {
if (par->state == PAR_NOW_READY) {
par->state = PAR_NOT_READY;
last = LoggerLastTime(par->log);
if (last != 0 && now - obj->period > last) {
LoggerWrite(par->log, now - obj->period, obj->period, buf);
}
} else if (par->state != PAR_ALWAYS_READY) {
break;
}
if (showTime && obj->pCall) {
snprintf(buffer, sizeof buffer, "<time> = %ld", (long)now);
InvokeCallBack(obj->pCall, VALUECHANGE, buffer);
showTime = 0;
}
iret = LoggerWrite(par->log, now, obj->period, buf);
if (iret && obj->pCall) {
snprintf(buffer, sizeof buffer, "%s = %s", LoggerName(par->log), buf);
InvokeCallBack(obj->pCall, VALUECHANGE, buffer);
}
}
break;
case PAR_SAVE:
fprintf(saveFile, " %s %s %s\n", obj->name, parName, buf);
break;
default: break;
}
}
/*----------------------------------------------------------------------------*/
void ParLogReady(ReadyState state) {
if (action == PAR_LOG && par) {
par->state = state;
}
}
/*----------------------------------------------------------------------------*/
void ParFmt(char *format) {
outputFormat = format; /* used for various actions */
}
/*----------------------------------------------------------------------------*/
void ParAccess(int accessRights) {
access = accessRights; /* used for PAR_SET & PAR_INIT */
}
/*----------------------------------------------------------------------------*/
void ParEnum(char *list[]) {
enumList = list; /* used for various actions */
}
/*----------------------------------------------------------------------------*/
void ParSave(int saveIt) {
if (action == PAR_INIT) {
doit = saveIt;
}
}
/*----------------------------------------------------------------------------*/
void ParList(char *group) {
if (action == PAR_LIST) {
if (group == NULL && cmdArgc == 0) {
doit = 1;
} else if (cmdArgc > 0 && group != NULL && 0 == strcasecmp(cmdArgs[0], group)) {
doit = 1;
} else if (doit < 0) {
doit = 0;
}
}
}
/*----------------------------------------------------------------------------*/
void ParTail(char *tail) {
if (action == PAR_LIST) {
listTail = tail;
}
}
/*----------------------------------------------------------------------------*/
void ParLogAs(char *name) {
if (action == PAR_INIT) {
logName = name;
}
}
/*----------------------------------------------------------------------------*/
void ParLogExact(int arg) {
exact = arg;
}
/*----------------------------------------------------------------------------*/
void ParHasChanged(void) {
if (par) {
if (RestoreMode()) {
par->saveIt = 1;
};
if (par->saveIt) {
SCparChange(sicsConnection);
}
}
}
/*----------------------------------------------------------------------------*/
void ParFloat(float *value, float defValue) {
char *endp;
float f;
char buf[132];
switch (ParWhat(1)) {
case SET_OP:
if (cmdArgc > 1) {
returnValue = ILLARGC;
return;
}
f = strtod(cmdArgs[0], &endp);
if (endp == cmdArgs[0]) {
f = ParText2Int(cmdArgs[0]);
if (f < 0) {
returnValue = ILLNUM;
break;
}
}
*value = f;
ParHasChanged();
/* fall through */
case FMT_OP:
if (*value == PAR_NAN) {
outputFormat = NULL;
ParOut("undefined");
} else {
if (outputFormat == NULL) {
outputFormat = "%#.5g";
}
snprintf(buf, sizeof buf, outputFormat, *value);
outputFormat = NULL;
ParOut(buf);
}
break;
case GET_OP:
floatValue = *value;
returnValue = 1;
break;
case INIT_OP:
*value = defValue;
break;
case NO_OP: break;
}
}
/*----------------------------------------------------------------------------*/
void ParInt(int *value, int defValue) {
char *endp;
int i;
char buf[132];
switch (ParWhat(1)) {
case SET_OP:
if (cmdArgc > 1) {
returnValue = ILLARGC;
return;
}
i = strtol(cmdArgs[0], &endp, 0);
if (endp == cmdArgs[0]) {
i = ParText2Int(cmdArgs[0]);
if (i < 0) {
returnValue = ILLNUM;
break;
}
}
*value = i;
ParHasChanged();
/* fall through */
case FMT_OP:
if (*value == PAR_LNAN) {
ParOut("undefined");
} else {
snprintf(buf, sizeof buf, "%d", *value);
ParOut(buf);
}
break;
case INIT_OP:
*value = defValue;
break;
default: break;
}
}
/*----------------------------------------------------------------------------*/
void ParStr(char **value, char *defValue) {
static char *empty="";
switch (ParWhat(0)) {
case SET_OP:
if (*value != NULL) free(*value);
*value = ParArg2Text(cmdArgc, cmdArgs, NULL, 0);
ParHasChanged();
/* fall through */
case FMT_OP:
if (*value == NULL) value = &empty;
ParOut(*value);
break;
case INIT_OP:
if (defValue != NULL) {
*value = strdup(defValue);
}
break;
default:
if (act == PAR_KILL && *value != NULL) {
free(*value);
*value = NULL;
}
break;
}
}
/*----------------------------------------------------------------------------*/
void ParFixedStr(char *value, int maxsize, char *defValue) {
switch (ParWhat(0)) {
case SET_OP:
ParArg2Text(cmdArgc, cmdArgs, value, maxsize);
ParHasChanged();
/* fall through */
case FMT_OP:
if (value == NULL) value = "";
ParOut(value);
break;
case INIT_OP:
if (defValue != NULL) {
snprintf(value, maxsize, "%s", defValue);
}
break;
default:
break;
}
}
/*----------------------------------------------------------------------------*/
int ParCmd(ParCommand cmd, void *userarg) {
int iret;
if (action != PAR_SHOW && action != PAR_SET) return 0;
if (access < 0) access=usUser;
if (access < SCGetRights(sicsConnection)) {
returnValue = ILLPRIV;
action = PAR_NOOP;
return 0;
}
returnValue = 1;
return cmd(obj, userarg, cmdArgc, cmdArgs);
}
/*----------------------------------------------------------------------------*/
int ParActionIs(ParAct a) {
if (action == a) return 1;
if (act == a) return -1;
return 0;
}
/*----------------------------------------------------------------------------*/
void *ParObject(void) {
return obj;
}
/*----------------------------------------------------------------------------*/
void ParStdDef(void) {
ParName("verbose"); ParAccess(usUser); ParSave(0); ParLogAs(NULL); ParInt(&obj->verbose, 1);
ParName("driver"); ParLogAs(NULL); ParStr(&obj->desc->name, NULL);
ParName("creationCmd"); ParLogAs(NULL); ParStr(&obj->creationCmd, NULL);
}
/*----------------------------------------------------------------------------*/
void ParGetFloat(SConnection *con, void *object, char *name, float *value) {
ParData *o = ParCheck(&parClass, object);
ParDo(con, o, PAR_GET, name);
if (returnValue == 1) {
*value = floatValue;
} else {
if (returnValue == 0) {
returnValue = UNKPAR;
}
if (con != NULL) {
ParOutError(con, o);
}
}
}
/*----------------------------------------------------------------------------*/
void ParKill(void *object) {
ParData *o = ParCheck(&parClass, object);
ParInfo *p, *q;
ParDo(NULL, o, PAR_KILL, NULL); /* free dynamic strings and custom content */
if (o->name) free(o->name);
if (o->creationCmd) free(o->creationCmd);
if (o->pCall) DeleteCallBackInterface(o->pCall);
if (o->desc) DeleteDescriptor(o->desc);
p = o->infoList;
while (p) {
q = p->next;
p->next = NULL;
KillLogger(p);
free(p);
p = q;
}
free(o);
}
/*----------------------------------------------------------------------------*/
void *ParMake(SConnection *con, char *name, ParClass *class, ParDef pardef,
char *creationCmd) {
ParData *o;
int i;
assert(pardef);
o = FindCommandData(pServ->pSics, name, class->name);
if (o != NULL) {
SCPrintf(con, eStatus, "overwrite '%s'", name);
RemoveCommand(pServ->pSics, name);
}
o = calloc(1, class->size);
assert(o);
o->class = class;
ParCheck(&parClass, o);
if (! AddCommand(pServ->pSics, name, ParExecute, ParKill, o)) {
SCPrintf(con, eError, "'%s' already exists as different object", name);
free(o);
return NULL;
}
o->name = strdup(name);
assert(o->name);
o->desc = CreateDescriptor(class->name);
assert(o->desc);
o->desc->SaveStatus = ParSaveAll;
o->creationCmd = creationCmd;
o->pCall = NULL;
o->logTime = 0;
o->period = 5;
o->infoList = NULL;
o->verbose = 0;
SCSave(&o->conn, con);
o->pardef = pardef;
ParDo(con, o, PAR_INIT, NULL);
SCparChange(con);
return o;
}
/*----------------------------------------------------------------------------*/
void ParStartup(void) {
}