diff --git a/.cdtproject b/.cdtproject
new file mode 100644
index 00000000..9a0d3e73
--- /dev/null
+++ b/.cdtproject
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+-
+
+
+
+
+-
+
+
+
+-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 00000000..ad6d1038
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,2 @@
+emergency.scn
+recover.bin
diff --git a/.project b/.project
new file mode 100644
index 00000000..8fb722c3
--- /dev/null
+++ b/.project
@@ -0,0 +1,141 @@
+
+
+ sics
+
+
+
+
+
+ org.eclipse.cdt.make.core.makeBuilder
+ clean,full,incremental,
+
+
+ org.eclipse.cdt.make.core.build.arguments
+ -f makefile_slinux
+
+
+ org.eclipse.cdt.core.errorOutputParser
+ org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser;
+
+
+ org.eclipse.cdt.make.core.fullBuildTarget
+ clean all
+
+
+ org.eclipse.cdt.make.core.incrementalBuildTarget
+ all
+
+
+ org.eclipse.cdt.make.core.environment
+
+
+
+ org.eclipse.cdt.make.core.enableAutoBuild
+ false
+
+
+ org.eclipse.cdt.make.core.buildLocation
+
+
+
+ org.eclipse.cdt.make.core.build.target.inc
+ all
+
+
+ org.eclipse.cdt.make.core.enableFullBuild
+ true
+
+
+ org.eclipse.cdt.make.core.enabledIncrementalBuild
+ true
+
+
+ org.eclipse.cdt.make.core.build.location
+
+
+
+ org.eclipse.cdt.make.core.build.target.clean
+ clean
+
+
+ org.eclipse.cdt.make.core.build.command
+ make
+
+
+ org.eclipse.cdt.make.core.enableCleanBuild
+ true
+
+
+ org.eclipse.cdt.make.core.cleanBuildTarget
+ clean
+
+
+ org.eclipse.cdt.make.core.append_environment
+ true
+
+
+ org.eclipse.cdt.make.core.useDefaultBuildCmd
+ false
+
+
+ org.eclipse.cdt.make.core.buildArguments
+ -f makefile_slinux
+
+
+ org.eclipse.cdt.make.core.buildCommand
+ make
+
+
+ org.eclipse.cdt.make.core.autoBuildTarget
+ all
+
+
+ org.eclipse.cdt.make.core.stopOnError
+ false
+
+
+ org.eclipse.cdt.make.core.build.target.auto
+ all
+
+
+
+
+ org.eclipse.cdt.make.core.ScannerConfigBuilder
+
+
+ org.eclipse.cdt.make.core.ScannerConfigDiscoveryEnabled
+ true
+
+
+ org.eclipse.cdt.make.core.makeBuilderParserId
+ org.eclipse.cdt.make.core.GCCScannerInfoConsoleParser
+
+
+ org.eclipse.cdt.make.core.esiProviderCommandEnabled
+ true
+
+
+ org.eclipse.cdt.make.core.siProblemGenerationEnabled
+ true
+
+
+ org.eclipse.cdt.make.core.useDefaultESIProviderCmd
+ true
+
+
+ org.eclipse.cdt.make.core.makeBuilderParserEnabled
+ true
+
+
+ org.eclipse.cdt.make.core.esiProviderParserId
+ org.eclipse.cdt.make.core.GCCSpecsConsoleParser
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.make.core.makeNature
+ org.eclipse.cdt.make.core.ScannerConfigNature
+
+
diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs
new file mode 100644
index 00000000..b0b2face
--- /dev/null
+++ b/.settings/org.eclipse.cdt.core.prefs
@@ -0,0 +1,3 @@
+#Thu Jan 11 14:43:46 CET 2007
+eclipse.preferences.version=1
+indexerId=org.eclipse.cdt.core.fastIndexer
diff --git a/Busy.c b/Busy.c
index 55e7c817..44b0d315 100644
--- a/Busy.c
+++ b/Busy.c
@@ -12,104 +12,119 @@
typedef struct BUSY__ {
pObjectDescriptor pDes;
int iBusy;
- }Busy;
+} Busy;
/*---------------------------------------------------------------------*/
-busyPtr makeBusy(void){
+busyPtr makeBusy(void)
+{
busyPtr result = NULL;
- result = (busyPtr)malloc(sizeof(Busy));
- if(!result){
+ result = (busyPtr) malloc(sizeof(Busy));
+ if (!result) {
return NULL;
}
result->pDes = CreateDescriptor("BusyFlag");
- if(!result->pDes){
+ if (!result->pDes) {
free(result);
return NULL;
}
result->iBusy = 0;
return result;
}
+
/*---------------------------------------------------------------------*/
-void killBusy(void *self){
+void killBusy(void *self)
+{
busyPtr busy;
- if(self != NULL){
- busy = (busyPtr)self;
- if(busy->pDes != NULL){
+ if (self != NULL) {
+ busy = (busyPtr) self;
+ if (busy->pDes != NULL) {
DeleteDescriptor(busy->pDes);
}
free(busy);
}
}
+
/*---------------------------------------------------------------------*/
-void incrementBusy(busyPtr self){
+void incrementBusy(busyPtr self)
+{
assert(self != NULL);
self->iBusy++;
}
+
/*--------------------------------------------------------------------*/
-void decrementBusy(busyPtr self){
+void decrementBusy(busyPtr self)
+{
assert(self != NULL);
self->iBusy--;
- if(self->iBusy < 0){
+ if (self->iBusy < 0) {
self->iBusy = 0;
}
}
+
/*--------------------------------------------------------------------*/
-void clearBusy(busyPtr self){
+void clearBusy(busyPtr self)
+{
assert(self != NULL);
self->iBusy = 0;
}
+
/*--------------------------------------------------------------------*/
-void setBusy(busyPtr self, int val){
+void setBusy(busyPtr self, int val)
+{
assert(self != NULL);
self->iBusy = val;
}
+
/*--------------------------------------------------------------------*/
-int isBusy(busyPtr self){
+int isBusy(busyPtr self)
+{
assert(self != NULL);
return self->iBusy;
}
+
/*--------------------------------------------------------------------*/
-int BusyAction(SConnection *pCon,SicsInterp *pSics, void *pData,
- int argc, char *argv[]){
+int BusyAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
busyPtr self = NULL;
char pBuffer[80];
- self = (busyPtr)pData;
+ self = (busyPtr) pData;
assert(self != NULL);
- if(argc > 1){
+ if (argc > 1) {
strtolower(argv[1]);
- if(usUser < SCGetRights(pCon)){
- SCWrite(pCon,"ERROR: no privilege to manipulate busy flag",eError);
+ if (usUser < SCGetRights(pCon)) {
+ SCWrite(pCon, "ERROR: no privilege to manipulate busy flag", eError);
return 0;
}
- if(strcmp(argv[1],"incr") == 0){
+ if (strcmp(argv[1], "incr") == 0) {
incrementBusy(self);
SCSendOK(pCon);
return 1;
- } else if(strcmp(argv[1],"decr") == 0){
+ } else if (strcmp(argv[1], "decr") == 0) {
decrementBusy(self);
SCSendOK(pCon);
return 1;
- } else if(strcmp(argv[1],"clear") == 0){
+ } else if (strcmp(argv[1], "clear") == 0) {
clearBusy(self);
SCSendOK(pCon);
return 1;
}
}
-
- sprintf(pBuffer,"Busy = %d", isBusy(self));
- SCWrite(pCon,pBuffer,eValue);
+
+ sprintf(pBuffer, "Busy = %d", isBusy(self));
+ SCWrite(pCon, pBuffer, eValue);
return 1;
}
+
/*---------------------------------------------------------------------*/
-busyPtr findBusy(SicsInterp *pInter){
+busyPtr findBusy(SicsInterp * pInter)
+{
CommandList *pCom = NULL;
- pCom = FindCommand(pInter,"busy");
- if(pCom != NULL){
- return (busyPtr)pCom->pData;
+ pCom = FindCommand(pInter, "busy");
+ if (pCom != NULL) {
+ return (busyPtr) pCom->pData;
}
}
-
-
diff --git a/Busy.h b/Busy.h
index 6718146d..65a48c5d 100644
--- a/Busy.h
+++ b/Busy.h
@@ -20,9 +20,8 @@ void setBusy(busyPtr self, int val);
int isBusy(busyPtr self);
-int BusyAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int BusyAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
-busyPtr findBusy(SicsInterp *pInter);
+busyPtr findBusy(SicsInterp * pInter);
#endif
-
diff --git a/Dbg.c b/Dbg.c
index eb0f6105..71d5c71d 100644
--- a/Dbg.c
+++ b/Dbg.c
@@ -40,8 +40,8 @@ char *Dbg_VarName = "dbg";
#define DEFAULT_COMPRESS 0
static int compress = DEFAULT_COMPRESS;
-#define DEFAULT_WIDTH 75 /* leave a little space for printing */
- /* stack level */
+#define DEFAULT_WIDTH 75 /* leave a little space for printing */
+ /* stack level */
static int buf_width = DEFAULT_WIDTH;
static int main_argc = 1;
@@ -49,148 +49,151 @@ static char *default_argv = "application";
static char **main_argv = &default_argv;
static Tcl_Trace debug_handle;
-static int step_count = 1; /* count next/step */
+static int step_count = 1; /* count next/step */
-#define FRAMENAMELEN 10 /* enough to hold strings like "#4" */
-static char viewFrameName[FRAMENAMELEN];/* destination frame name for up/down */
+#define FRAMENAMELEN 10 /* enough to hold strings like "#4" */
+static char viewFrameName[FRAMENAMELEN]; /* destination frame name for up/down */
-static CallFrame *goalFramePtr; /* destination for next/return */
-static int goalNumLevel; /* destination for Next */
+static CallFrame *goalFramePtr; /* destination for next/return */
+static int goalNumLevel; /* destination for Next */
static enum debug_cmd {
- none, step, next, ret, cont, up, down, where, Next
+ none, step, next, ret, cont, up, down, where, Next
} debug_cmd;
/* this acts as a strobe (while testing breakpoints). It is set to true */
/* every time a new debugger command is issued that is an action */
static debug_new_action;
-#define NO_LINE -1 /* if break point is not set by line number */
+#define NO_LINE -1 /* if break point is not set by line number */
struct breakpoint {
- int id;
- char *file; /* file where breakpoint is */
- int line; /* line where breakpoint is */
- char *pat; /* pattern defining where breakpoint can be */
- regexp *re; /* regular expression to trigger breakpoint */
- char *expr; /* expr to trigger breakpoint */
- char *cmd; /* cmd to eval at breakpoint */
- struct breakpoint *next, *previous;
+ int id;
+ char *file; /* file where breakpoint is */
+ int line; /* line where breakpoint is */
+ char *pat; /* pattern defining where breakpoint can be */
+ regexp *re; /* regular expression to trigger breakpoint */
+ char *expr; /* expr to trigger breakpoint */
+ char *cmd; /* cmd to eval at breakpoint */
+ struct breakpoint *next, *previous;
};
static struct breakpoint *break_base = 0;
static int breakpoint_max_id = 0;
-static struct breakpoint *
-breakpoint_new()
+static struct breakpoint *breakpoint_new()
{
- struct breakpoint *b = (struct breakpoint *)ckalloc(sizeof(struct breakpoint));
- if (break_base) break_base->previous = b;
- b->next = break_base;
- b->previous = 0;
- b->id = breakpoint_max_id++;
- b->file = 0;
- b->line = NO_LINE;
- b->pat = 0;
- b->re = 0;
- b->expr = 0;
- b->cmd = 0;
- break_base = b;
- return(b);
+ struct breakpoint *b =
+ (struct breakpoint *) ckalloc(sizeof(struct breakpoint));
+ if (break_base)
+ break_base->previous = b;
+ b->next = break_base;
+ b->previous = 0;
+ b->id = breakpoint_max_id++;
+ b->file = 0;
+ b->line = NO_LINE;
+ b->pat = 0;
+ b->re = 0;
+ b->expr = 0;
+ b->cmd = 0;
+ break_base = b;
+ return (b);
}
static
-void
-breakpoint_print(interp,b)
+void breakpoint_print(interp, b)
Tcl_Interp *interp;
struct breakpoint *b;
{
- print(interp,"breakpoint %d: ",b->id);
+ print(interp, "breakpoint %d: ", b->id);
- if (b->re) {
- print(interp,"-re \"%s\" ",b->pat);
- } else if (b->pat) {
- print(interp,"-glob \"%s\" ",b->pat);
- } else if (b->line != NO_LINE) {
- if (b->file) {
- print(interp,"%s:",b->file);
- }
- print(interp,"%d ",b->line);
- }
+ if (b->re) {
+ print(interp, "-re \"%s\" ", b->pat);
+ } else if (b->pat) {
+ print(interp, "-glob \"%s\" ", b->pat);
+ } else if (b->line != NO_LINE) {
+ if (b->file) {
+ print(interp, "%s:", b->file);
+ }
+ print(interp, "%d ", b->line);
+ }
- if (b->expr)
- print(interp,"if {%s} ",b->expr);
+ if (b->expr)
+ print(interp, "if {%s} ", b->expr);
- if (b->cmd)
- print(interp,"then {%s}",b->cmd);
+ if (b->cmd)
+ print(interp, "then {%s}", b->cmd);
- putchar('\n');
+ putchar('\n');
}
-static void
-save_re_matches(interp,re)
+static void save_re_matches(interp, re)
Tcl_Interp *interp;
regexp *re;
{
- int i;
- char name[20];
- char match_char;/* place to hold char temporarily */
- /* uprooted by a NULL */
+ int i;
+ char name[20];
+ char match_char; /* place to hold char temporarily */
+ /* uprooted by a NULL */
- for (i=0;istartp[i] == 0) break;
+ for (i = 0; i < NSUBEXP; i++) {
+ if (re->startp[i] == 0)
+ break;
- sprintf(name,"%d",i);
- /* temporarily null-terminate in middle */
- match_char = *re->endp[i];
- *re->endp[i] = 0;
- Tcl_SetVar2(interp,Dbg_VarName,name,re->startp[i],0);
+ sprintf(name, "%d", i);
+ /* temporarily null-terminate in middle */
+ match_char = *re->endp[i];
+ *re->endp[i] = 0;
+ Tcl_SetVar2(interp, Dbg_VarName, name, re->startp[i], 0);
- /* undo temporary null-terminator */
- *re->endp[i] = match_char;
- }
+ /* undo temporary null-terminator */
+ *re->endp[i] = match_char;
+ }
}
/* return 1 to break, 0 to continue */
-static int
-breakpoint_test(interp,cmd,bp)
+static int breakpoint_test(interp, cmd, bp)
Tcl_Interp *interp;
-char *cmd; /* command about to be executed */
-struct breakpoint *bp; /* breakpoint to test */
+char *cmd; /* command about to be executed */
+struct breakpoint *bp; /* breakpoint to test */
{
- if (bp->re) {
+ if (bp->re) {
#if TCL_MAJOR_VERSION == 6
- if (0 == regexec(bp->re,cmd)) return 0;
+ if (0 == regexec(bp->re, cmd))
+ return 0;
#else
- if (0 == TclRegExec(bp->re,cmd,cmd)) return 0;
+ if (0 == TclRegExec(bp->re, cmd, cmd))
+ return 0;
#endif
- save_re_matches(interp,bp->re);
- } else if (bp->pat) {
- if (0 == Tcl_StringMatch(cmd,bp->pat)) return 0;
- } else if (bp->line != NO_LINE) {
- /* not yet implemented - awaiting support from Tcl */
- return 0;
- }
+ save_re_matches(interp, bp->re);
+ } else if (bp->pat) {
+ if (0 == Tcl_StringMatch(cmd, bp->pat))
+ return 0;
+ } else if (bp->line != NO_LINE) {
+ /* not yet implemented - awaiting support from Tcl */
+ return 0;
+ }
- if (bp->expr) {
- int value;
+ if (bp->expr) {
+ int value;
- /* ignore errors, since they are likely due to */
- /* simply being out of scope a lot */
- if (TCL_OK != Tcl_ExprBoolean(interp,bp->expr,&value)) return 0;
- }
+ /* ignore errors, since they are likely due to */
+ /* simply being out of scope a lot */
+ if (TCL_OK != Tcl_ExprBoolean(interp, bp->expr, &value))
+ return 0;
+ }
- if (bp->cmd) {
+ if (bp->cmd) {
#if TCL_MAJOR_VERSION == 6
- Tcl_Eval(interp,bp->cmd,0,(char **)0);
+ Tcl_Eval(interp, bp->cmd, 0, (char **) 0);
#else
- Tcl_Eval(interp,bp->cmd);
+ Tcl_Eval(interp, bp->cmd);
#endif
- } else {
- breakpoint_print(interp,bp);
- }
+ } else {
+ breakpoint_print(interp, bp);
+ }
- return 1;
+ return 1;
}
static char *already_at_top_level = "already at top level";
@@ -201,243 +204,258 @@ If direction is down, simulate searching down stack by
seaching up stack from origFrame
*/
static
-int
-TclGetFrame2(interp, origFramePtr, string, framePtrPtr, dir)
- Tcl_Interp *interp;
- CallFrame *origFramePtr; /* frame that is true top-of-stack */
- char *string; /* String describing frame. */
- CallFrame **framePtrPtr; /* Store pointer to frame here (or NULL
- * if global frame indicated). */
- enum debug_cmd dir; /* look up or down the stack */
+int TclGetFrame2(interp, origFramePtr, string, framePtrPtr, dir)
+Tcl_Interp *interp;
+CallFrame *origFramePtr; /* frame that is true top-of-stack */
+char *string; /* String describing frame. */
+CallFrame **framePtrPtr; /* Store pointer to frame here (or NULL
+ * if global frame indicated). */
+enum debug_cmd dir; /* look up or down the stack */
{
- Interp *iPtr = (Interp *) interp;
- int level, result;
- CallFrame *framePtr; /* frame currently being searched */
+ Interp *iPtr = (Interp *) interp;
+ int level, result;
+ CallFrame *framePtr; /* frame currently being searched */
- CallFrame *curFramePtr = iPtr->varFramePtr;
+ CallFrame *curFramePtr = iPtr->varFramePtr;
- /*
- * Parse string to figure out which level number to go to.
- */
+ /*
+ * Parse string to figure out which level number to go to.
+ */
- result = 1;
- if (*string == '#') {
- if (Tcl_GetInt(interp, string+1, &level) != TCL_OK) {
- return TCL_ERROR;
- }
- if (level < 0) {
- levelError:
- Tcl_AppendResult(interp, "bad level \"", string, "\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- framePtr = origFramePtr; /* start search here */
-
- } else if (isdigit(*string)) {
- if (Tcl_GetInt(interp, string, &level) != TCL_OK) {
- return TCL_ERROR;
- }
- if (dir == up) {
- if (curFramePtr == 0) {
- Tcl_SetResult(interp,already_at_top_level,TCL_STATIC);
- return TCL_ERROR;
- }
- level = curFramePtr->level - level;
- framePtr = curFramePtr; /* start search here */
- } else {
- if (curFramePtr != 0) {
- level = curFramePtr->level + level;
- }
- framePtr = origFramePtr; /* start search here */
- }
- } else {
- level = curFramePtr->level - 1;
- result = 0;
+ result = 1;
+ if (*string == '#') {
+ if (Tcl_GetInt(interp, string + 1, &level) != TCL_OK) {
+ return TCL_ERROR;
}
-
- /*
- * Figure out which frame to use.
- */
-
- if (level == 0) {
- framePtr = NULL;
- } else {
- for (;framePtr != NULL; framePtr = framePtr->callerVarPtr) {
- if (framePtr->level == level) {
- break;
- }
- }
- if (framePtr == NULL) {
- goto levelError;
- }
+ if (level < 0) {
+ levelError:
+ Tcl_AppendResult(interp, "bad level \"", string, "\"",
+ (char *) NULL);
+ return TCL_ERROR;
}
- *framePtrPtr = framePtr;
- return result;
+ framePtr = origFramePtr; /* start search here */
+
+ } else if (isdigit(*string)) {
+ if (Tcl_GetInt(interp, string, &level) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (dir == up) {
+ if (curFramePtr == 0) {
+ Tcl_SetResult(interp, already_at_top_level, TCL_STATIC);
+ return TCL_ERROR;
+ }
+ level = curFramePtr->level - level;
+ framePtr = curFramePtr; /* start search here */
+ } else {
+ if (curFramePtr != 0) {
+ level = curFramePtr->level + level;
+ }
+ framePtr = origFramePtr; /* start search here */
+ }
+ } else {
+ level = curFramePtr->level - 1;
+ result = 0;
+ }
+
+ /*
+ * Figure out which frame to use.
+ */
+
+ if (level == 0) {
+ framePtr = NULL;
+ } else {
+ for (; framePtr != NULL; framePtr = framePtr->callerVarPtr) {
+ if (framePtr->level == level) {
+ break;
+ }
+ }
+ if (framePtr == NULL) {
+ goto levelError;
+ }
+ }
+ *framePtrPtr = framePtr;
+ return result;
}
static char *printify(s)
char *s;
{
- static int destlen = 0;
- char *d; /* ptr into dest */
- unsigned int need;
- static char buf_basic[DEFAULT_WIDTH+1];
- static char *dest = buf_basic;
+ static int destlen = 0;
+ char *d; /* ptr into dest */
+ unsigned int need;
+ static char buf_basic[DEFAULT_WIDTH + 1];
+ static char *dest = buf_basic;
- if (s == 0) return("");
+ if (s == 0)
+ return ("");
- /* worst case is every character takes 4 to printify */
- need = strlen(s)*4;
- if (need > destlen) {
- if (dest && (dest != buf_basic)) free(dest);
- dest = (char *)ckalloc(need+1);
- destlen = need;
- }
+ /* worst case is every character takes 4 to printify */
+ need = strlen(s) * 4;
+ if (need > destlen) {
+ if (dest && (dest != buf_basic))
+ free(dest);
+ dest = (char *) ckalloc(need + 1);
+ destlen = need;
+ }
- for (d = dest;*s;s++) {
- /* since we check at worst by every 4 bytes, play */
- /* conservative and subtract 4 from the limit */
- if (d-dest > destlen-4) break;
+ for (d = dest; *s; s++) {
+ /* since we check at worst by every 4 bytes, play */
+ /* conservative and subtract 4 from the limit */
+ if (d - dest > destlen - 4)
+ break;
- if (*s == '\b') {
- strcpy(d,"\\b"); d += 2;
- } else if (*s == '\f') {
- strcpy(d,"\\f"); d += 2;
- } else if (*s == '\v') {
- strcpy(d,"\\v"); d += 2;
- } else if (*s == '\r') {
- strcpy(d,"\\r"); d += 2;
- } else if (*s == '\n') {
- strcpy(d,"\\n"); d += 2;
- } else if (*s == '\t') {
- strcpy(d,"\\t"); d += 2;
- } else if ((unsigned)*s < 0x20) { /* unsigned strips parity */
- sprintf(d,"\\%03o",*s); d += 4;
- } else if (*s == 0177) {
- strcpy(d,"\\177"); d += 4;
- } else {
- *d = *s; d += 1;
- }
- }
- *d = '\0';
- return(dest);
+ if (*s == '\b') {
+ strcpy(d, "\\b");
+ d += 2;
+ } else if (*s == '\f') {
+ strcpy(d, "\\f");
+ d += 2;
+ } else if (*s == '\v') {
+ strcpy(d, "\\v");
+ d += 2;
+ } else if (*s == '\r') {
+ strcpy(d, "\\r");
+ d += 2;
+ } else if (*s == '\n') {
+ strcpy(d, "\\n");
+ d += 2;
+ } else if (*s == '\t') {
+ strcpy(d, "\\t");
+ d += 2;
+ } else if ((unsigned) *s < 0x20) { /* unsigned strips parity */
+ sprintf(d, "\\%03o", *s);
+ d += 4;
+ } else if (*s == 0177) {
+ strcpy(d, "\\177");
+ d += 4;
+ } else {
+ *d = *s;
+ d += 1;
+ }
+ }
+ *d = '\0';
+ return (dest);
}
static
-char *
-print_argv(interp,argc,argv)
+char *print_argv(interp, argc, argv)
Tcl_Interp *interp;
int argc;
char *argv[];
{
- static int buf_width_max = DEFAULT_WIDTH;
- static char buf_basic[DEFAULT_WIDTH+1]; /* basic buffer */
- static char *buf = buf_basic;
- int space; /* space remaining in buf */
- int len;
- char *bufp;
- int proc; /* if current command is "proc" */
- int arg_index;
+ static int buf_width_max = DEFAULT_WIDTH;
+ static char buf_basic[DEFAULT_WIDTH + 1]; /* basic buffer */
+ static char *buf = buf_basic;
+ int space; /* space remaining in buf */
+ int len;
+ char *bufp;
+ int proc; /* if current command is "proc" */
+ int arg_index;
- if (buf_width > buf_width_max) {
- if (buf && (buf != buf_basic)) ckfree(buf);
- buf = (char *)ckalloc(buf_width + 1);
- buf_width_max = buf_width;
- }
+ if (buf_width > buf_width_max) {
+ if (buf && (buf != buf_basic))
+ ckfree(buf);
+ buf = (char *) ckalloc(buf_width + 1);
+ buf_width_max = buf_width;
+ }
- proc = (0 == strcmp("proc",argv[0]));
- sprintf(buf,"%.*s",buf_width,argv[0]);
- len = strlen(buf);
- space = buf_width - len;
- bufp = buf + len;
- argc--; argv++;
- arg_index = 1;
-
- while (argc && (space > 0)) {
- char *elementPtr;
- char *nextPtr;
- int wrap;
+ proc = (0 == strcmp("proc", argv[0]));
+ sprintf(buf, "%.*s", buf_width, argv[0]);
+ len = strlen(buf);
+ space = buf_width - len;
+ bufp = buf + len;
+ argc--;
+ argv++;
+ arg_index = 1;
- /* braces/quotes have been stripped off arguments */
- /* so put them back. We wrap everything except lists */
- /* with one argument. One exception is to always wrap */
- /* proc's 2nd arg (the arg list), since people are */
- /* used to always seeing it this way. */
+ while (argc && (space > 0)) {
+ char *elementPtr;
+ char *nextPtr;
+ int wrap;
- if (proc && (arg_index > 1)) wrap = TRUE;
- else {
- (void) TclFindElement(interp,*argv,&elementPtr,
- &nextPtr,(int *)0,(int *)0);
- if (*elementPtr == '\0') wrap = TRUE;
- else if (*nextPtr == '\0') wrap = FALSE;
- else wrap = TRUE;
- }
+ /* braces/quotes have been stripped off arguments */
+ /* so put them back. We wrap everything except lists */
+ /* with one argument. One exception is to always wrap */
+ /* proc's 2nd arg (the arg list), since people are */
+ /* used to always seeing it this way. */
- /* wrap lists (or null) in braces */
- if (wrap) {
- sprintf(bufp," {%.*s}",space-3,*argv);
- } else {
- sprintf(bufp," %.*s",space-1,*argv);
- }
- len = strlen(buf);
- space = buf_width - len;
- bufp = buf + len;
- argc--; argv++;
- arg_index++;
- }
+ if (proc && (arg_index > 1))
+ wrap = TRUE;
+ else {
+ (void) TclFindElement(interp, *argv, &elementPtr,
+ &nextPtr, (int *) 0, (int *) 0);
+ if (*elementPtr == '\0')
+ wrap = TRUE;
+ else if (*nextPtr == '\0')
+ wrap = FALSE;
+ else
+ wrap = TRUE;
+ }
- if (compress) {
- /* this copies from our static buf to printify's static buf */
- /* and back to our static buf */
- strncpy(buf,printify(buf),buf_width);
- }
+ /* wrap lists (or null) in braces */
+ if (wrap) {
+ sprintf(bufp, " {%.*s}", space - 3, *argv);
+ } else {
+ sprintf(bufp, " %.*s", space - 1, *argv);
+ }
+ len = strlen(buf);
+ space = buf_width - len;
+ bufp = buf + len;
+ argc--;
+ argv++;
+ arg_index++;
+ }
- /* usually but not always right, but assume truncation if buffer is */
- /* full. this avoids tiny but odd-looking problem of appending "}" */
- /* to truncated lists during {}-wrapping earlier */
- if (strlen(buf) == buf_width) {
- buf[buf_width-1] = buf[buf_width-2] = buf[buf_width-3] = '.';
- }
+ if (compress) {
+ /* this copies from our static buf to printify's static buf */
+ /* and back to our static buf */
+ strncpy(buf, printify(buf), buf_width);
+ }
- return(buf);
+ /* usually but not always right, but assume truncation if buffer is */
+ /* full. this avoids tiny but odd-looking problem of appending "}" */
+ /* to truncated lists during {}-wrapping earlier */
+ if (strlen(buf) == buf_width) {
+ buf[buf_width - 1] = buf[buf_width - 2] = buf[buf_width - 3] = '.';
+ }
+
+ return (buf);
}
static
-void
-PrintStackBelow(interp,curf,viewf)
+void PrintStackBelow(interp, curf, viewf)
Tcl_Interp *interp;
-CallFrame *curf; /* current FramePtr */
-CallFrame *viewf; /* view FramePtr */
+CallFrame *curf; /* current FramePtr */
+CallFrame *viewf; /* view FramePtr */
{
- char ptr; /* graphically indicate where we are in the stack */
+ char ptr; /* graphically indicate where we are in the stack */
- /* indicate where we are in the stack */
- ptr = ((curf == viewf)?'*':' ');
+ /* indicate where we are in the stack */
+ ptr = ((curf == viewf) ? '*' : ' ');
- if (curf == 0) {
- print(interp,"%c0: %s\n",
- ptr,print_argv(interp,main_argc,main_argv));
- } else {
- PrintStackBelow(interp,curf->callerVarPtr,viewf);
- print(interp,"%c%d: %s\n",ptr,curf->level,
- print_argv(interp,curf->argc,curf->argv));
- }
+ if (curf == 0) {
+ print(interp, "%c0: %s\n",
+ ptr, print_argv(interp, main_argc, main_argv));
+ } else {
+ PrintStackBelow(interp, curf->callerVarPtr, viewf);
+ print(interp, "%c%d: %s\n", ptr, curf->level,
+ print_argv(interp, curf->argc, curf->argv));
+ }
}
static
-void
-PrintStack(interp,curf,viewf,argc,argv,level)
+void PrintStack(interp, curf, viewf, argc, argv, level)
Tcl_Interp *interp;
-CallFrame *curf; /* current FramePtr */
-CallFrame *viewf; /* view FramePtr */
+CallFrame *curf; /* current FramePtr */
+CallFrame *viewf; /* view FramePtr */
int argc;
char *argv[];
char *level;
{
- PrintStackBelow(interp,curf,viewf);
-
- print(interp," %s: %s\n",level,print_argv(interp,argc,argv));
+ PrintStackBelow(interp, curf, viewf);
+
+ print(interp, " %s: %s\n", level, print_argv(interp, argc, argv));
}
/* return 0 if goal matches current frame or goal can't be found */
@@ -448,759 +466,778 @@ char *level;
/* or Tcl_Eval. These builtin calls to Tcl_Eval lose any knowledge */
/* the FramePtr from the proc, so we have to search the entire */
/* stack frame to see if it's still there. */
-static int
-GoalFrame(goal,iptr)
+static int GoalFrame(goal, iptr)
CallFrame *goal;
Interp *iptr;
{
- CallFrame *cf = iptr->varFramePtr;
+ CallFrame *cf = iptr->varFramePtr;
- /* if at current level, return success immediately */
- if (goal == cf) return 0;
+ /* if at current level, return success immediately */
+ if (goal == cf)
+ return 0;
- while (cf) {
- cf = cf->callerVarPtr;
- if (goal == cf) {
- /* found, but since it's above us, fail */
- return 1;
- }
- }
- return 0;
+ while (cf) {
+ cf = cf->callerVarPtr;
+ if (goal == cf) {
+ /* found, but since it's above us, fail */
+ return 1;
+ }
+ }
+ return 0;
}
/* debugger's trace handler */
-/*ARGSUSED*/
-static void
-debugger_trap(clientData,interp,level,command,cmdProc,cmdClientData,argc,argv)
-ClientData clientData; /* not used */
+ /*ARGSUSED*/
+ static void
+debugger_trap(clientData, interp, level, command, cmdProc, cmdClientData,
+ argc, argv)
+ClientData clientData; /* not used */
Tcl_Interp *interp;
-int level; /* positive number if called by Tcl, -1 if */
- /* called by Dbg_On in which case we don't */
- /* know the level */
+int level; /* positive number if called by Tcl, -1 if */
+ /* called by Dbg_On in which case we don't */
+ /* know the level */
char *command;
-int (*cmdProc)(); /* not used */
+int (*cmdProc) (); /* not used */
ClientData cmdClientData;
int argc;
char *argv[];
{
- char level_text[6]; /* textual representation of level */
+ char level_text[6]; /* textual representation of level */
- int break_status;
- Interp *iPtr = (Interp *)interp;
+ int break_status;
+ Interp *iPtr = (Interp *) interp;
- CallFrame *trueFramePtr; /* where the pc is */
- CallFrame *viewFramePtr; /* where up/down are */
+ CallFrame *trueFramePtr; /* where the pc is */
+ CallFrame *viewFramePtr; /* where up/down are */
- int print_command_first_time = TRUE;
- static int debug_suspended = FALSE;
+ int print_command_first_time = TRUE;
+ static int debug_suspended = FALSE;
- struct breakpoint *b;
+ struct breakpoint *b;
- /* skip commands that are invoked interactively */
- if (debug_suspended) return;
+ /* skip commands that are invoked interactively */
+ if (debug_suspended)
+ return;
- /* skip debugger commands */
- if (argv[0][1] == '\0') {
- switch (argv[0][0]) {
- case 'n':
- case 's':
- case 'c':
- case 'r':
- case 'w':
- case 'b':
- case 'u':
- case 'd': return;
- }
- }
+ /* skip debugger commands */
+ if (argv[0][1] == '\0') {
+ switch (argv[0][0]) {
+ case 'n':
+ case 's':
+ case 'c':
+ case 'r':
+ case 'w':
+ case 'b':
+ case 'u':
+ case 'd':
+ return;
+ }
+ }
- if ((*ignoreproc)(interp,argv[0])) return;
+ if ((*ignoreproc) (interp, argv[0]))
+ return;
- /* if level is unknown, use "?" */
- sprintf(level_text,(level == -1)?"?":"%d",level);
+ /* if level is unknown, use "?" */
+ sprintf(level_text, (level == -1) ? "?" : "%d", level);
- /* save so we can restore later */
- trueFramePtr = iPtr->varFramePtr;
+ /* save so we can restore later */
+ trueFramePtr = iPtr->varFramePtr;
- /* test all breakpoints to see if we should break */
- debug_suspended = TRUE;
+ /* test all breakpoints to see if we should break */
+ debug_suspended = TRUE;
- /* if any successful breakpoints, start interactor */
- debug_new_action = FALSE; /* reset strobe */
- break_status = FALSE; /* no successful breakpoints yet */
- for (b = break_base;b;b=b->next) {
- break_status |= breakpoint_test(interp,command,b);
- }
- if (!debug_new_action && break_status) goto start_interp;
+ /* if any successful breakpoints, start interactor */
+ debug_new_action = FALSE; /* reset strobe */
+ break_status = FALSE; /* no successful breakpoints yet */
+ for (b = break_base; b; b = b->next) {
+ break_status |= breakpoint_test(interp, command, b);
+ }
+ if (!debug_new_action && break_status)
+ goto start_interp;
- /* if s or n triggered by breakpoint, make "s 1" (and so on) */
- /* refer to next command, not this one */
- if (debug_new_action) step_count++;
+ /* if s or n triggered by breakpoint, make "s 1" (and so on) */
+ /* refer to next command, not this one */
+ if (debug_new_action)
+ step_count++;
- switch (debug_cmd) {
- case cont:
- goto finish;
- case step:
- step_count--;
- if (step_count > 0) goto finish;
- goto start_interp;
- case next:
- /* check if we are back at the same level where the next */
- /* command was issued. Also test */
- /* against all FramePtrs and if no match, assume that */
- /* we've missed a return, and so we should break */
+ switch (debug_cmd) {
+ case cont:
+ goto finish;
+ case step:
+ step_count--;
+ if (step_count > 0)
+ goto finish;
+ goto start_interp;
+ case next:
+ /* check if we are back at the same level where the next */
+ /* command was issued. Also test */
+ /* against all FramePtrs and if no match, assume that */
+ /* we've missed a return, and so we should break */
/* if (goalFramePtr != iPtr->varFramePtr) goto finish;*/
- if (GoalFrame(goalFramePtr,iPtr)) goto finish;
- step_count--;
- if (step_count > 0) goto finish;
- goto start_interp;
- case Next:
- /* check if we are back at the same level where the next */
- /* command was issued. */
- if (goalNumLevel < iPtr->numLevels) goto finish;
- step_count--;
- if (step_count > 0) goto finish;
- goto start_interp;
- case ret:
- /* same comment as in "case next" */
- if (goalFramePtr != iPtr->varFramePtr) goto finish;
- goto start_interp;
- }
+ if (GoalFrame(goalFramePtr, iPtr))
+ goto finish;
+ step_count--;
+ if (step_count > 0)
+ goto finish;
+ goto start_interp;
+ case Next:
+ /* check if we are back at the same level where the next */
+ /* command was issued. */
+ if (goalNumLevel < iPtr->numLevels)
+ goto finish;
+ step_count--;
+ if (step_count > 0)
+ goto finish;
+ goto start_interp;
+ case ret:
+ /* same comment as in "case next" */
+ if (goalFramePtr != iPtr->varFramePtr)
+ goto finish;
+ goto start_interp;
+ }
start_interp:
- if (print_command_first_time) {
- print(interp,"%s: %s\n",
- level_text,print_argv(interp,1,&command));
- print_command_first_time = FALSE;
- }
- /* since user is typing a command, don't interrupt it immediately */
- debug_cmd = cont;
- debug_suspended = FALSE;
+ if (print_command_first_time) {
+ print(interp, "%s: %s\n", level_text, print_argv(interp, 1, &command));
+ print_command_first_time = FALSE;
+ }
+ /* since user is typing a command, don't interrupt it immediately */
+ debug_cmd = cont;
+ debug_suspended = FALSE;
- /* interactor won't return until user gives a debugger cmd */
- (*interactor)(interp);
+ /* interactor won't return until user gives a debugger cmd */
+ (*interactor) (interp);
- /* save this so it can be restored after "w" command */
- viewFramePtr = iPtr->varFramePtr;
+ /* save this so it can be restored after "w" command */
+ viewFramePtr = iPtr->varFramePtr;
- if (debug_cmd == up || debug_cmd == down) {
- /* calculate new frame */
- if (-1 == TclGetFrame2(interp,trueFramePtr,viewFrameName,
- &iPtr->varFramePtr,debug_cmd)) {
- print(interp,"%s\n",interp->result);
- Tcl_ResetResult(interp);
- }
- goto start_interp;
- }
+ if (debug_cmd == up || debug_cmd == down) {
+ /* calculate new frame */
+ if (-1 == TclGetFrame2(interp, trueFramePtr, viewFrameName,
+ &iPtr->varFramePtr, debug_cmd)) {
+ print(interp, "%s\n", interp->result);
+ Tcl_ResetResult(interp);
+ }
+ goto start_interp;
+ }
- /* reset view back to normal */
- iPtr->varFramePtr = trueFramePtr;
+ /* reset view back to normal */
+ iPtr->varFramePtr = trueFramePtr;
- /* allow trapping */
- debug_suspended = FALSE;
+ /* allow trapping */
+ debug_suspended = FALSE;
- switch (debug_cmd) {
- case cont:
- case step:
- goto finish;
- case next:
- goalFramePtr = iPtr->varFramePtr;
- goto finish;
- case Next:
- goalNumLevel = iPtr->numLevels;
- goto finish;
- case ret:
- goalFramePtr = iPtr->varFramePtr;
- if (goalFramePtr == 0) {
- print(interp,"nowhere to return to\n");
- break;
- }
- goalFramePtr = goalFramePtr->callerVarPtr;
- goto finish;
- case where:
- PrintStack(interp,iPtr->varFramePtr,viewFramePtr,argc,argv,level_text);
- break;
- }
+ switch (debug_cmd) {
+ case cont:
+ case step:
+ goto finish;
+ case next:
+ goalFramePtr = iPtr->varFramePtr;
+ goto finish;
+ case Next:
+ goalNumLevel = iPtr->numLevels;
+ goto finish;
+ case ret:
+ goalFramePtr = iPtr->varFramePtr;
+ if (goalFramePtr == 0) {
+ print(interp, "nowhere to return to\n");
+ break;
+ }
+ goalFramePtr = goalFramePtr->callerVarPtr;
+ goto finish;
+ case where:
+ PrintStack(interp, iPtr->varFramePtr, viewFramePtr, argc, argv,
+ level_text);
+ break;
+ }
- /* restore view and restart interactor */
- iPtr->varFramePtr = viewFramePtr;
- goto start_interp;
+ /* restore view and restart interactor */
+ iPtr->varFramePtr = viewFramePtr;
+ goto start_interp;
- finish:
- debug_suspended = FALSE;
+finish:
+ debug_suspended = FALSE;
}
-/*ARGSUSED*/
-static
-int
-cmdNext(clientData, interp, argc, argv)
+ /*ARGSUSED*/ static
+int cmdNext(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
- debug_cmd = *(enum debug_cmd *)clientData;
- debug_new_action = TRUE;
+ debug_cmd = *(enum debug_cmd *) clientData;
+ debug_new_action = TRUE;
- step_count = (argc == 1)?1:atoi(argv[1]);
- return(TCL_RETURN);
+ step_count = (argc == 1) ? 1 : atoi(argv[1]);
+ return (TCL_RETURN);
}
-/*ARGSUSED*/
-static
-int
-cmdDir(clientData, interp, argc, argv)
+ /*ARGSUSED*/ static
+int cmdDir(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
- debug_cmd = *(enum debug_cmd *)clientData;
+ debug_cmd = *(enum debug_cmd *) clientData;
- if (argc == 1) argv[1] = "1";
- strncpy(viewFrameName,argv[1],FRAMENAMELEN);
+ if (argc == 1)
+ argv[1] = "1";
+ strncpy(viewFrameName, argv[1], FRAMENAMELEN);
- return TCL_RETURN;
+ return TCL_RETURN;
}
-/*ARGSUSED*/
-static
-int
-cmdSimple(clientData, interp, argc, argv)
+ /*ARGSUSED*/ static
+int cmdSimple(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
- debug_cmd = *(enum debug_cmd *)clientData;
- debug_new_action = TRUE;
- return TCL_RETURN;
+ debug_cmd = *(enum debug_cmd *) clientData;
+ debug_new_action = TRUE;
+ return TCL_RETURN;
}
static
-void
-breakpoint_destroy(b)
+void breakpoint_destroy(b)
struct breakpoint *b;
{
- if (b->file) ckfree(b->file);
- if (b->pat) ckfree(b->pat);
- if (b->re) ckfree((char *)b->re);
- if (b->cmd) ckfree(b->cmd);
+ if (b->file)
+ ckfree(b->file);
+ if (b->pat)
+ ckfree(b->pat);
+ if (b->re)
+ ckfree((char *) b->re);
+ if (b->cmd)
+ ckfree(b->cmd);
- /* unlink from chain */
- if ((b->previous == 0) && (b->next == 0)) {
- break_base = 0;
- } else if (b->previous == 0) {
- break_base = b->next;
- b->next->previous = 0;
- } else if (b->next == 0) {
- b->previous->next = 0;
- } else {
- b->previous->next = b->next;
- b->next->previous = b->previous;
- }
+ /* unlink from chain */
+ if ((b->previous == 0) && (b->next == 0)) {
+ break_base = 0;
+ } else if (b->previous == 0) {
+ break_base = b->next;
+ b->next->previous = 0;
+ } else if (b->next == 0) {
+ b->previous->next = 0;
+ } else {
+ b->previous->next = b->next;
+ b->next->previous = b->previous;
+ }
- ckfree((char *)b);
+ ckfree((char *) b);
}
-static void
-savestr(straddr,str)
+static void savestr(straddr, str)
char **straddr;
char *str;
{
- *straddr = ckalloc(strlen(str)+1);
- strcpy(*straddr,str);
+ *straddr = ckalloc(strlen(str) + 1);
+ strcpy(*straddr, str);
}
/* return 1 if a string is substring of a flag */
-static int
-flageq(flag,string,minlen)
+static int flageq(flag, string, minlen)
char *flag;
char *string;
-int minlen; /* at least this many chars must match */
+int minlen; /* at least this many chars must match */
{
- for (;*flag;flag++,string++,minlen--) {
- if (*string == '\0') break;
- if (*string != *flag) return 0;
- }
- if (*string == '\0' && minlen <= 0) return 1;
- return 0;
+ for (; *flag; flag++, string++, minlen--) {
+ if (*string == '\0')
+ break;
+ if (*string != *flag)
+ return 0;
+ }
+ if (*string == '\0' && minlen <= 0)
+ return 1;
+ return 0;
}
-/*ARGSUSED*/
-static
-int
-cmdWhere(clientData, interp, argc, argv)
+ /*ARGSUSED*/ static
+int cmdWhere(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
- if (argc == 1) {
- debug_cmd = where;
- return TCL_RETURN;
- }
+ if (argc == 1) {
+ debug_cmd = where;
+ return TCL_RETURN;
+ }
- argc--; argv++;
+ argc--;
+ argv++;
- while (argc) {
- if (flageq("-width",*argv,2)) {
- argc--; argv++;
- if (*argv) {
- buf_width = atoi(*argv);
- argc--; argv++;
- } else print(interp,"%d\n",buf_width);
- } else if (flageq("-compress",*argv,2)) {
- argc--; argv++;
- if (*argv) {
- compress = atoi(*argv);
- argc--; argv++;
- } else print(interp,"%d\n",compress);
- } else {
- print(interp,"usage: w [-width #] [-compress 0|1]\n");
- return TCL_ERROR;
- }
- }
- return TCL_OK;
+ while (argc) {
+ if (flageq("-width", *argv, 2)) {
+ argc--;
+ argv++;
+ if (*argv) {
+ buf_width = atoi(*argv);
+ argc--;
+ argv++;
+ } else
+ print(interp, "%d\n", buf_width);
+ } else if (flageq("-compress", *argv, 2)) {
+ argc--;
+ argv++;
+ if (*argv) {
+ compress = atoi(*argv);
+ argc--;
+ argv++;
+ } else
+ print(interp, "%d\n", compress);
+ } else {
+ print(interp, "usage: w [-width #] [-compress 0|1]\n");
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
}
#define breakpoint_fail(msg) {error_msg = msg; goto break_fail;}
-/*ARGSUSED*/
-static
-int
-cmdBreak(clientData, interp, argc, argv)
+ /*ARGSUSED*/ static
+int cmdBreak(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
- struct breakpoint *b;
- char *error_msg;
+ struct breakpoint *b;
+ char *error_msg;
- argc--; argv++;
+ argc--;
+ argv++;
- if (argc < 1) {
- for (b = break_base;b;b=b->next) breakpoint_print(interp,b);
- return(TCL_OK);
- }
+ if (argc < 1) {
+ for (b = break_base; b; b = b->next)
+ breakpoint_print(interp, b);
+ return (TCL_OK);
+ }
- if (argv[0][0] == '-') {
- if (argv[0][1] == '\0') {
- while (break_base) {
- breakpoint_destroy(break_base);
- }
- breakpoint_max_id = 0;
- return(TCL_OK);
- } else if (isdigit(argv[0][1])) {
- int id = atoi(argv[0]+1);
+ if (argv[0][0] == '-') {
+ if (argv[0][1] == '\0') {
+ while (break_base) {
+ breakpoint_destroy(break_base);
+ }
+ breakpoint_max_id = 0;
+ return (TCL_OK);
+ } else if (isdigit(argv[0][1])) {
+ int id = atoi(argv[0] + 1);
- for (b = break_base;b;b=b->next) {
- if (b->id == id) {
- breakpoint_destroy(b);
- if (!break_base) breakpoint_max_id = 0;
- return(TCL_OK);
- }
- }
- Tcl_SetResult(interp,"no such breakpoint",TCL_STATIC);
- return(TCL_ERROR);
- }
- }
+ for (b = break_base; b; b = b->next) {
+ if (b->id == id) {
+ breakpoint_destroy(b);
+ if (!break_base)
+ breakpoint_max_id = 0;
+ return (TCL_OK);
+ }
+ }
+ Tcl_SetResult(interp, "no such breakpoint", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+ }
- b = breakpoint_new();
+ b = breakpoint_new();
- if (flageq("-regexp",argv[0],2)) {
- argc--; argv++;
+ if (flageq("-regexp", argv[0], 2)) {
+ argc--;
+ argv++;
#if TCL_MAJOR_VERSION == 6
- if ((argc > 0) && (b->re = regcomp(argv[0]))) {
+ if ((argc > 0) && (b->re = regcomp(argv[0]))) {
#else
- if ((argc > 0) && (b->re = TclRegComp(argv[0]))) {
+ if ((argc > 0) && (b->re = TclRegComp(argv[0]))) {
#endif
- savestr(&b->pat,argv[0]);
- argc--; argv++;
- } else {
- breakpoint_fail("bad regular expression")
- }
- } else if (flageq("-glob",argv[0],2)) {
- argc--; argv++;
- if (argc > 0) {
- savestr(&b->pat,argv[0]);
- argc--; argv++;
- } else {
- breakpoint_fail("no pattern?");
- }
- } else if ((!(flageq("if",*argv,1)) && (!(flageq("then",*argv,1))))) {
- /* look for [file:]line */
- char *colon;
- char *linep; /* pointer to beginning of line number */
+ savestr(&b->pat, argv[0]);
+ argc--;
+ argv++;
+ } else {
+ breakpoint_fail("bad regular expression")
+ }
+ } else if (flageq("-glob", argv[0], 2)) {
+ argc--;
+ argv++;
+ if (argc > 0) {
+ savestr(&b->pat, argv[0]);
+ argc--;
+ argv++;
+ } else {
+ breakpoint_fail("no pattern?");
+ }
+ } else if ((!(flageq("if", *argv, 1)) && (!(flageq("then", *argv, 1))))) {
+ /* look for [file:]line */
+ char *colon;
+ char *linep; /* pointer to beginning of line number */
- colon = strchr(argv[0],':');
- if (colon) {
- *colon = '\0';
- savestr(&b->file,argv[0]);
- *colon = ':';
- linep = colon + 1;
- } else {
- linep = argv[0];
- /* get file from current scope */
- /* savestr(&b->file, ?); */
- }
+ colon = strchr(argv[0], ':');
+ if (colon) {
+ *colon = '\0';
+ savestr(&b->file, argv[0]);
+ *colon = ':';
+ linep = colon + 1;
+ } else {
+ linep = argv[0];
+ /* get file from current scope */
+ /* savestr(&b->file, ?); */
+ }
- if (TCL_OK == Tcl_GetInt(interp,linep,&b->line)) {
- argc--; argv++;
- print(interp,"setting breakpoints by line number is currently unimplemented - use patterns or expressions\n");
- } else {
- /* not an int? - unwind & assume it is an expression */
+ if (TCL_OK == Tcl_GetInt(interp, linep, &b->line)) {
+ argc--;
+ argv++;
+ print(interp,
+ "setting breakpoints by line number is currently unimplemented - use patterns or expressions\n");
+ } else {
+ /* not an int? - unwind & assume it is an expression */
- if (b->file) ckfree(b->file);
- }
- }
+ if (b->file)
+ ckfree(b->file);
+ }
+ }
- if (argc > 0) {
- int do_if = FALSE;
+ if (argc > 0) {
+ int do_if = FALSE;
- if (flageq("if",argv[0],1)) {
- argc--; argv++;
- do_if = TRUE;
- } else if (!flageq("then",argv[0],1)) {
- do_if = TRUE;
- }
+ if (flageq("if", argv[0], 1)) {
+ argc--;
+ argv++;
+ do_if = TRUE;
+ } else if (!flageq("then", argv[0], 1)) {
+ do_if = TRUE;
+ }
- if (do_if) {
- if (argc < 1) {
- breakpoint_fail("if what");
- }
+ if (do_if) {
+ if (argc < 1) {
+ breakpoint_fail("if what");
+ }
- savestr(&b->expr,argv[0]);
- argc--; argv++;
- }
- }
+ savestr(&b->expr, argv[0]);
+ argc--;
+ argv++;
+ }
+ }
- if (argc > 0) {
- if (flageq("then",argv[0],1)) {
- argc--; argv++;
- }
+ if (argc > 0) {
+ if (flageq("then", argv[0], 1)) {
+ argc--;
+ argv++;
+ }
- if (argc < 1) {
- breakpoint_fail("then what?");
- }
+ if (argc < 1) {
+ breakpoint_fail("then what?");
+ }
- savestr(&b->cmd,argv[0]);
- }
+ savestr(&b->cmd, argv[0]);
+ }
- sprintf(interp->result,"%d",b->id);
- return(TCL_OK);
+ sprintf(interp->result, "%d", b->id);
+ return (TCL_OK);
- break_fail:
- breakpoint_destroy(b);
- Tcl_SetResult(interp,error_msg,TCL_STATIC);
- return(TCL_ERROR);
+break_fail:
+ breakpoint_destroy(b);
+ Tcl_SetResult(interp, error_msg, TCL_STATIC);
+ return (TCL_ERROR);
}
static char *help[] = {
-"s [#] step into procedure",
-"n [#] step over procedure",
-"N [#] step over procedures, commands, and arguments",
-"c continue",
-"r continue until return to caller",
-"u [#] move scope up level",
-"d [#] move scope down level",
-" go to absolute frame if # is prefaced by \"#\"",
-"w show stack (\"where\")",
-"w -w [#] show/set width",
-"w -c [0|1] show/set compress",
-"b show breakpoints",
-"b [-r regexp-pattern] [if expr] [then command]",
-"b [-g glob-pattern] [if expr] [then command]",
-"b [[file:]#] [if expr] [then command]",
-" if pattern given, break if command resembles pattern",
-" if # given, break on line #",
-" if expr given, break if expr true",
-" if command given, execute command at breakpoint",
-"b -# delete breakpoint",
-"b - delete all breakpoints",
-0};
+ "s [#] step into procedure",
+ "n [#] step over procedure",
+ "N [#] step over procedures, commands, and arguments",
+ "c continue",
+ "r continue until return to caller",
+ "u [#] move scope up level",
+ "d [#] move scope down level",
+ " go to absolute frame if # is prefaced by \"#\"",
+ "w show stack (\"where\")",
+ "w -w [#] show/set width",
+ "w -c [0|1] show/set compress",
+ "b show breakpoints",
+ "b [-r regexp-pattern] [if expr] [then command]",
+ "b [-g glob-pattern] [if expr] [then command]",
+ "b [[file:]#] [if expr] [then command]",
+ " if pattern given, break if command resembles pattern",
+ " if # given, break on line #",
+ " if expr given, break if expr true",
+ " if command given, execute command at breakpoint",
+ "b -# delete breakpoint",
+ "b - delete all breakpoints",
+ 0
+};
-/*ARGSUSED*/
-static
-int
-cmdHelp(clientData, interp, argc, argv)
+ /*ARGSUSED*/ static
+int cmdHelp(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
- char **hp;
+ char **hp;
- for (hp=help;*hp;hp++) {
- print(interp,"%s\n",*hp);
- }
+ for (hp = help; *hp; hp++) {
+ print(interp, "%s\n", *hp);
+ }
- return(TCL_OK);
+ return (TCL_OK);
}
/* this may seem excessive, but this avoids the explicit test for non-zero */
/* in the caller, and chances are that that test will always be pointless */
-/*ARGSUSED*/
-static int zero(interp,string)
+ /*ARGSUSED*/ static int zero(interp, string)
Tcl_Interp *interp;
char *string;
{
- return 0;
+ return 0;
}
-static int
-simple_interactor(interp)
+static int simple_interactor(interp)
Tcl_Interp *interp;
{
- int rc;
- char *ccmd; /* pointer to complete command */
- char line[BUFSIZ+1]; /* space for partial command */
- int newcmd = TRUE;
- Interp *iPtr = (Interp *)interp;
+ int rc;
+ char *ccmd; /* pointer to complete command */
+ char line[BUFSIZ + 1]; /* space for partial command */
+ int newcmd = TRUE;
+ Interp *iPtr = (Interp *) interp;
#if TCL_MAJOR_VERSION == 6
- Tcl_CmdBuf buffer;
+ Tcl_CmdBuf buffer;
- if (!(buffer = Tcl_CreateCmdBuf())) {
- Tcl_AppendElement(interp,"no more space for cmd buffer",0);
- return(TCL_ERROR);
- }
+ if (!(buffer = Tcl_CreateCmdBuf())) {
+ Tcl_AppendElement(interp, "no more space for cmd buffer", 0);
+ return (TCL_ERROR);
+ }
#else
- Tcl_DString dstring;
- Tcl_DStringInit(&dstring);
+ Tcl_DString dstring;
+ Tcl_DStringInit(&dstring);
#endif
- newcmd = TRUE;
- while (TRUE) {
- if (newcmd) {
- print(interp,"dbg%d.%d> ",iPtr->numLevels,iPtr->curEventNum+1);
- } else {
- print(interp,"dbg+> ");
- }
- fflush(stdout);
+ newcmd = TRUE;
+ while (TRUE) {
+ if (newcmd) {
+ print(interp, "dbg%d.%d> ", iPtr->numLevels, iPtr->curEventNum + 1);
+ } else {
+ print(interp, "dbg+> ");
+ }
+ fflush(stdout);
- if (0 >= (rc = read(0,line,BUFSIZ))) {
- if (!newcmd) line[0] = 0;
- else exit(0);
- } else line[rc] = '\0';
+ if (0 >= (rc = read(0, line, BUFSIZ))) {
+ if (!newcmd)
+ line[0] = 0;
+ else
+ exit(0);
+ } else
+ line[rc] = '\0';
#if TCL_MAJOR_VERSION == 6
- if (NULL == (ccmd = Tcl_AssembleCmd(buffer,line))) {
+ if (NULL == (ccmd = Tcl_AssembleCmd(buffer, line))) {
#else
- ccmd = Tcl_DStringAppend(&dstring,line,rc);
- if (!Tcl_CommandComplete(ccmd)) {
+ ccmd = Tcl_DStringAppend(&dstring, line, rc);
+ if (!Tcl_CommandComplete(ccmd)) {
#endif
- newcmd = FALSE;
- continue; /* continue collecting command */
- }
- newcmd = TRUE;
+ newcmd = FALSE;
+ continue; /* continue collecting command */
+ }
+ newcmd = TRUE;
- rc = Tcl_RecordAndEval(interp,ccmd,0);
+ rc = Tcl_RecordAndEval(interp, ccmd, 0);
#if TCL_MAJOR_VERSION != 6
- Tcl_DStringFree(&dstring);
+ Tcl_DStringFree(&dstring);
#endif
- switch (rc) {
- case TCL_OK:
- if (*interp->result != 0)
- print(interp,"%s\n",interp->result);
- continue;
- case TCL_ERROR:
- print(interp,"%s\n",Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY));
- /* since user is typing by hand, we expect lots
- of errors, and want to give another chance */
- continue;
- case TCL_BREAK:
- case TCL_CONTINUE:
+ switch (rc) {
+ case TCL_OK:
+ if (*interp->result != 0)
+ print(interp, "%s\n", interp->result);
+ continue;
+ case TCL_ERROR:
+ print(interp, "%s\n",
+ Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY));
+ /* since user is typing by hand, we expect lots
+ of errors, and want to give another chance */
+ continue;
+ case TCL_BREAK:
+ case TCL_CONTINUE:
#define finish(x) {rc = x; goto done;}
- finish(rc);
- case TCL_RETURN:
- finish(TCL_OK);
- default:
- /* note that ccmd has trailing newline */
- print(interp,"error %d: %s\n",rc,ccmd);
- continue;
- }
- }
- /* cannot fall thru here, must jump to label */
- done:
+ finish(rc);
+ case TCL_RETURN:
+ finish(TCL_OK);
+ default:
+ /* note that ccmd has trailing newline */
+ print(interp, "error %d: %s\n", rc, ccmd);
+ continue;
+ }
+ }
+ /* cannot fall thru here, must jump to label */
+done:
#if TCL_MAJOR_VERSION == 6
- /* currently, code guarantees buffer is valid */
- Tcl_DeleteCmdBuf(buffer);
+ /* currently, code guarantees buffer is valid */
+ Tcl_DeleteCmdBuf(buffer);
#else
- Tcl_DStringFree(&dstring);
+ Tcl_DStringFree(&dstring);
#endif
- return(rc);
+ return (rc);
}
/* occasionally, we print things larger buf_max but not by much */
/* see print statements in PrintStack routines for examples */
#define PAD 80
-static void
-print(va_alist )
+static void print(va_alist)
va_dcl
{
- Tcl_Interp *interp;
- char *fmt;
- va_list args;
+ Tcl_Interp *interp;
+ char *fmt;
+ va_list args;
- va_start(args);
- interp = va_arg(args,Tcl_Interp *);
- fmt = va_arg(args,char *);
- if (!printproc) vprintf(fmt,args);
- else {
- static int buf_width_max = DEFAULT_WIDTH+PAD;
- static char buf_basic[DEFAULT_WIDTH+PAD+1];
- static char *buf = buf_basic;
+ va_start(args);
+ interp = va_arg(args, Tcl_Interp *);
+ fmt = va_arg(args, char *);
+ if (!printproc)
+ vprintf(fmt, args);
+ else {
+ static int buf_width_max = DEFAULT_WIDTH + PAD;
+ static char buf_basic[DEFAULT_WIDTH + PAD + 1];
+ static char *buf = buf_basic;
- if (buf_width+PAD > buf_width_max) {
- if (buf && (buf != buf_basic)) ckfree(buf);
- buf = (char *)ckalloc(buf_width+PAD+1);
- buf_width_max = buf_width+PAD;
- }
+ if (buf_width + PAD > buf_width_max) {
+ if (buf && (buf != buf_basic))
+ ckfree(buf);
+ buf = (char *) ckalloc(buf_width + PAD + 1);
+ buf_width_max = buf_width + PAD;
+ }
- vsprintf(buf,fmt,args);
- (*printproc)(interp,buf);
- }
- va_end(args);
+ vsprintf(buf, fmt, args);
+ (*printproc) (interp, buf);
+ }
+ va_end(args);
}
-/*ARGSUSED*/
-Dbg_InterProc *
-Dbg_Interactor(interp,inter_proc)
+ /*ARGSUSED*/ Dbg_InterProc * Dbg_Interactor(interp, inter_proc)
Tcl_Interp *interp;
Dbg_InterProc *inter_proc;
{
- Dbg_InterProc *tmp = interactor;
- interactor = (inter_proc?inter_proc:simple_interactor);
- return tmp;
+ Dbg_InterProc *tmp = interactor;
+ interactor = (inter_proc ? inter_proc : simple_interactor);
+ return tmp;
}
-/*ARGSUSED*/
-Dbg_IgnoreFuncsProc *
-Dbg_IgnoreFuncs(interp,proc)
+ /*ARGSUSED*/ Dbg_IgnoreFuncsProc * Dbg_IgnoreFuncs(interp, proc)
Tcl_Interp *interp;
Dbg_IgnoreFuncsProc *proc;
{
- Dbg_IgnoreFuncsProc *tmp = ignoreproc;
- ignoreproc = (proc?proc:zero);
- return tmp;
+ Dbg_IgnoreFuncsProc *tmp = ignoreproc;
+ ignoreproc = (proc ? proc : zero);
+ return tmp;
}
-/*ARGSUSED*/
-Dbg_OutputProc *
-Dbg_Output(interp,proc)
+ /*ARGSUSED*/ Dbg_OutputProc * Dbg_Output(interp, proc)
Tcl_Interp *interp;
Dbg_OutputProc *proc;
{
- Dbg_OutputProc *tmp = printproc;
- printproc = (proc?proc:0);
- return tmp;
+ Dbg_OutputProc *tmp = printproc;
+ printproc = (proc ? proc : 0);
+ return tmp;
}
-/*ARGSUSED*/
-int
-Dbg_Active(interp)
+ /*ARGSUSED*/ int Dbg_Active(interp)
Tcl_Interp *interp;
{
- return debugger_active;
+ return debugger_active;
}
-char **
-Dbg_ArgcArgv(argc,argv,copy)
+char **Dbg_ArgcArgv(argc, argv, copy)
int argc;
char *argv[];
int copy;
{
- char **alloc;
+ char **alloc;
- if (!copy) {
- main_argv = argv;
- alloc = 0;
- } else {
- main_argv = alloc = (char **)ckalloc((argc+1)*sizeof(char *));
- while (argc-- >= 0) {
- *main_argv++ = *argv++;
- }
- main_argv = alloc;
- }
- return alloc;
+ if (!copy) {
+ main_argv = argv;
+ alloc = 0;
+ } else {
+ main_argv = alloc = (char **) ckalloc((argc + 1) * sizeof(char *));
+ while (argc-- >= 0) {
+ *main_argv++ = *argv++;
+ }
+ main_argv = alloc;
+ }
+ return alloc;
}
static struct cmd_list {
- char *cmdname;
- Tcl_CmdProc *cmdproc;
- enum debug_cmd cmdtype;
-} cmd_list[] = {{"n", cmdNext, next},
- {"s", cmdNext, step},
- {"N", cmdNext, Next},
- {"c", cmdSimple, cont},
- {"r", cmdSimple, ret},
- {"w", cmdWhere, none},
- {"b", cmdBreak, none},
- {"u", cmdDir, up},
- {"d", cmdDir, down},
- {"h", cmdHelp, none},
- {0}
+ char *cmdname;
+ Tcl_CmdProc *cmdproc;
+ enum debug_cmd cmdtype;
+} cmd_list[] = { {
+"n", cmdNext, next}, {
+"s", cmdNext, step}, {
+"N", cmdNext, Next}, {
+"c", cmdSimple, cont}, {
+"r", cmdSimple, ret}, {
+"w", cmdWhere, none}, {
+"b", cmdBreak, none}, {
+"u", cmdDir, up}, {
+"d", cmdDir, down}, {
+"h", cmdHelp, none}, {
+0}
};
-static void
-init_debugger(interp)
+static void init_debugger(interp)
Tcl_Interp *interp;
{
- struct cmd_list *c;
+ struct cmd_list *c;
- for (c = cmd_list;c->cmdname;c++) {
- Tcl_CreateCommand(interp,c->cmdname,c->cmdproc,
- (ClientData)&c->cmdtype,(Tcl_CmdDeleteProc *)0);
- }
+ for (c = cmd_list; c->cmdname; c++) {
+ Tcl_CreateCommand(interp, c->cmdname, c->cmdproc,
+ (ClientData) & c->cmdtype, (Tcl_CmdDeleteProc *) 0);
+ }
- debug_handle = Tcl_CreateTrace(interp,
- 10000,debugger_trap,(ClientData)0);
+ debug_handle = Tcl_CreateTrace(interp,
+ 10000, debugger_trap, (ClientData) 0);
- debugger_active = TRUE;
- Tcl_SetVar2(interp,Dbg_VarName,"active","1",0);
+ debugger_active = TRUE;
+ Tcl_SetVar2(interp, Dbg_VarName, "active", "1", 0);
}
/* allows any other part of the application to jump to the debugger */
-/*ARGSUSED*/
-void
-Dbg_On(interp,immediate)
+ /*ARGSUSED*/ void Dbg_On(interp, immediate)
Tcl_Interp *interp;
-int immediate; /* if true, stop immediately */
- /* should only be used in safe places */
- /* i.e., when Tcl_Eval can be called */
+int immediate; /* if true, stop immediately */
+ /* should only be used in safe places */
+ /* i.e., when Tcl_Eval can be called */
{
- if (!debugger_active) init_debugger(interp);
+ if (!debugger_active)
+ init_debugger(interp);
- debug_cmd = step;
- step_count = 1;
+ debug_cmd = step;
+ step_count = 1;
- if (immediate) {
- static char *fake_cmd = "--interrupted-- (command_unknown)";
+ if (immediate) {
+ static char *fake_cmd = "--interrupted-- (command_unknown)";
- debugger_trap((ClientData)0,interp,-1,fake_cmd,(int (*)())0,
- (ClientData)0,1,&fake_cmd);
+ debugger_trap((ClientData) 0, interp, -1, fake_cmd, (int (*)()) 0,
+ (ClientData) 0, 1, &fake_cmd);
/* (*interactor)(interp);*/
- }
+ }
}
-void
-Dbg_Off(interp)
+void Dbg_Off(interp)
Tcl_Interp *interp;
{
- struct cmd_list *c;
+ struct cmd_list *c;
- if (!debugger_active) return;
+ if (!debugger_active)
+ return;
- for (c = cmd_list;c->cmdname;c++) {
- Tcl_DeleteCommand(interp,c->cmdname);
- }
+ for (c = cmd_list; c->cmdname; c++) {
+ Tcl_DeleteCommand(interp, c->cmdname);
+ }
- Tcl_DeleteTrace(interp,debug_handle);
- debugger_active = FALSE;
- Tcl_UnsetVar(interp,Dbg_VarName,TCL_GLOBAL_ONLY);
+ Tcl_DeleteTrace(interp, debug_handle);
+ debugger_active = FALSE;
+ Tcl_UnsetVar(interp, Dbg_VarName, TCL_GLOBAL_ONLY);
}
diff --git a/Dbg.h b/Dbg.h
index 29364f4d..34add8e2 100644
--- a/Dbg.h
+++ b/Dbg.h
@@ -14,13 +14,11 @@ would appreciate credit if this program or parts of it are used.
#include "tcl.h"
-typedef int (Dbg_InterProc) _ANSI_ARGS_((Tcl_Interp *interp));
-typedef int (Dbg_IgnoreFuncsProc) _ANSI_ARGS_((
- Tcl_Interp *interp,
- char *funcname));
-typedef void (Dbg_OutputProc) _ANSI_ARGS_((
- Tcl_Interp *interp,
- char *output));
+typedef int (Dbg_InterProc) _ANSI_ARGS_((Tcl_Interp * interp));
+typedef int (Dbg_IgnoreFuncsProc) _ANSI_ARGS_((Tcl_Interp * interp,
+ char *funcname));
+typedef void (Dbg_OutputProc) _ANSI_ARGS_((Tcl_Interp * interp,
+ char *output));
EXTERN char *Dbg_VarName;
EXTERN char *Dbg_DefaultCmdName;
@@ -28,19 +26,15 @@ EXTERN char *Dbg_DefaultCmdName;
/* trivial interface, creates a "debug" command in your interp */
EXTERN int Dbg_Init _ANSI_ARGS_((Tcl_Interp *));
-EXTERN void Dbg_On _ANSI_ARGS_((Tcl_Interp *interp,
- int immediate));
-EXTERN void Dbg_Off _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN char **Dbg_ArgcArgv _ANSI_ARGS_((int argc,char *argv[],
- int copy));
-EXTERN int Dbg_Active _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN Dbg_InterProc *Dbg_Interactor _ANSI_ARGS_((
- Tcl_Interp *interp,
- Dbg_InterProc *interactor));
-EXTERN Dbg_IgnoreFuncsProc *Dbg_IgnoreFuncs _ANSI_ARGS_((
- Tcl_Interp *interp,
- Dbg_IgnoreFuncsProc *));
-EXTERN Dbg_OutputProc *Dbg_Output _ANSI_ARGS_((
- Tcl_Interp *interp,
- Dbg_OutputProc *));
-#endif /* _NIST_DBG */
+EXTERN void Dbg_On _ANSI_ARGS_((Tcl_Interp * interp, int immediate));
+EXTERN void Dbg_Off _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN char **Dbg_ArgcArgv _ANSI_ARGS_((int argc, char *argv[], int copy));
+EXTERN int Dbg_Active _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN Dbg_InterProc *Dbg_Interactor _ANSI_ARGS_((Tcl_Interp * interp,
+ Dbg_InterProc *
+ interactor));
+EXTERN Dbg_IgnoreFuncsProc *Dbg_IgnoreFuncs
+_ANSI_ARGS_((Tcl_Interp * interp, Dbg_IgnoreFuncsProc *));
+EXTERN Dbg_OutputProc *Dbg_Output
+_ANSI_ARGS_((Tcl_Interp * interp, Dbg_OutputProc *));
+#endif /* _NIST_DBG */
diff --git a/Dbg_cmd.c b/Dbg_cmd.c
index 9ab2ceda..e1a3a28b 100644
--- a/Dbg_cmd.c
+++ b/Dbg_cmd.c
@@ -14,51 +14,48 @@ would appreciate credit if this program or parts of it are used.
char *Dbg_DefaultCmdName = "debug";
-/*ARGSUSED*/
-static int
-App_DebugCmd(clientData, interp, argc, argv)
+ /*ARGSUSED*/ static int App_DebugCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
- int now = 0; /* soon if 0, now if 1 */
+ int now = 0; /* soon if 0, now if 1 */
- if (argc > 3) goto usage;
+ if (argc > 3)
+ goto usage;
- argv++;
+ argv++;
- while (*argv) {
- if (0 == strcmp(*argv,"-now")) {
- now = 1;
- argv++;
- }
- else break;
- }
+ while (*argv) {
+ if (0 == strcmp(*argv, "-now")) {
+ now = 1;
+ argv++;
+ } else
+ break;
+ }
- if (!*argv) {
- if (now) {
- Dbg_On(interp,1);
- } else {
- goto usage;
- }
- } else if (0 == strcmp(*argv,"0")) {
- Dbg_Off(interp);
- } else {
- Dbg_On(interp,now);
- }
- return(TCL_OK);
- usage:
- interp->result = "usage: [[-now] 1|0]";
- return TCL_ERROR;
+ if (!*argv) {
+ if (now) {
+ Dbg_On(interp, 1);
+ } else {
+ goto usage;
+ }
+ } else if (0 == strcmp(*argv, "0")) {
+ Dbg_Off(interp);
+ } else {
+ Dbg_On(interp, now);
+ }
+ return (TCL_OK);
+usage:
+ interp->result = "usage: [[-now] 1|0]";
+ return TCL_ERROR;
}
-int
-Dbg_Init(interp)
+int Dbg_Init(interp)
Tcl_Interp *interp;
{
- Tcl_CreateCommand(interp,Dbg_DefaultCmdName,App_DebugCmd,
- (ClientData)0,(void (*)())0);
- return TCL_OK;
+ Tcl_CreateCommand(interp, Dbg_DefaultCmdName, App_DebugCmd,
+ (ClientData) 0, (void (*)()) 0);
+ return TCL_OK;
}
-
diff --git a/HistMem.h b/HistMem.h
index 6ffc568b..6ceb50ab 100644
--- a/HistMem.h
+++ b/HistMem.h
@@ -13,34 +13,34 @@
#define SICSHISTMEM
#define MAXDIM 3
- typedef struct __HistDriver *pHistDriver;
- typedef struct __HistMem *pHistMem;
+typedef struct __HistDriver *pHistDriver;
+typedef struct __HistMem *pHistMem;
/*-------------------------------------------------------------------------*/
- typedef int HistInt;
+typedef int HistInt;
/*
32 bit integer on a DigitalUnix
*/
#line 9 "histogram.w"
- typedef enum {
- eHTransparent,
- eHNormal,
- eHTOF,
- eHStrobo,
- eHRPT,
- ePSD,
- eSANSTOF
- } HistMode;
+typedef enum {
+ eHTransparent,
+ eHNormal,
+ eHTOF,
+ eHStrobo,
+ eHRPT,
+ ePSD,
+ eSANSTOF
+} HistMode;
#line 36 "histogram.w"
- typedef enum {
- eOIgnore,
- eOCeil,
- eOCount,
- eReflect
- } OverFlowMode;
+typedef enum {
+ eOIgnore,
+ eOCeil,
+ eOCount,
+ eReflect
+} OverFlowMode;
#line 460 "histogram.w"
@@ -48,51 +48,52 @@
#line 292 "histogram.w"
- pHistMem CreateHistMemory(char *drivername);
- void DeleteHistMemory(void *self);
+pHistMem CreateHistMemory(char *drivername);
+void DeleteHistMemory(void *self);
#line 308 "histogram.w"
- int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);
- int HistSetOption(pHistMem self, char *name, char *value);
- int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics);
+int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);
+int HistSetOption(pHistMem self, char *name, char *value);
+int HistConfigure(pHistMem self, SConnection * pCon, SicsInterp * pSics);
#line 336 "histogram.w"
- float GetHistPreset(pHistMem self);
- int SetHistPreset(pHistMem self, float fVal);
- CounterMode GetHistCountMode(pHistMem self);
- int SetHistCountMode(pHistMem self, CounterMode eNew);
- long GetHistMonitor(pHistMem self, int i, SConnection *pCon);
- const float *GetHistTimeBin(pHistMem self, int *iLength);
- int GetHistLength(pHistMem self);
- int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim);
- float GetHistCountTime(pHistMem self,SConnection *pCon);
- int HistDoCount(pHistMem self, SConnection *pCon);
- int HistBlockCount(pHistMem self, SConnection *pCon);
- void HistDirty(pHistMem self);
+float GetHistPreset(pHistMem self);
+int SetHistPreset(pHistMem self, float fVal);
+CounterMode GetHistCountMode(pHistMem self);
+int SetHistCountMode(pHistMem self, CounterMode eNew);
+long GetHistMonitor(pHistMem self, int i, SConnection * pCon);
+const float *GetHistTimeBin(pHistMem self, int *iLength);
+int GetHistLength(pHistMem self);
+int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim);
+float GetHistCountTime(pHistMem self, SConnection * pCon);
+int HistDoCount(pHistMem self, SConnection * pCon);
+int HistBlockCount(pHistMem self, SConnection * pCon);
+void HistDirty(pHistMem self);
#line 366 "histogram.w"
- int SetHistogram(pHistMem self, SConnection *pCon,
- int i,int iStart, int iEnd, HistInt *lData);
- int GetHistogram(pHistMem self, SConnection *pCon,
- int i,int iStart, int iEnd, HistInt *lData, int iDataLen);
- HistInt *GetHistogramPointer(pHistMem self,SConnection *pCon);
- int GetHistogramDirect(pHistMem self, SConnection *pCon,
- int i, int iStart, int iEnd,
- HistInt *lData, int iDataLen);
- int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal);
+int SetHistogram(pHistMem self, SConnection * pCon,
+ int i, int iStart, int iEnd, HistInt * lData);
+int GetHistogram(pHistMem self, SConnection * pCon,
+ int i, int iStart, int iEnd, HistInt * lData,
+ int iDataLen);
+HistInt *GetHistogramPointer(pHistMem self, SConnection * pCon);
+int GetHistogramDirect(pHistMem self, SConnection * pCon,
+ int i, int iStart, int iEnd,
+ HistInt * lData, int iDataLen);
+int PresetHistogram(pHistMem self, SConnection * pCon, HistInt lVal);
#line 409 "histogram.w"
- int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int MakeHistMemory(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+
+int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
- int HistAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
-
#line 462 "histogram.w"
diff --git a/SCinter.c b/SCinter.c
index 611fca13..acd616f3 100644
--- a/SCinter.c
+++ b/SCinter.c
@@ -52,6 +52,14 @@
Paul Hathaway, May 2004
Added FindAlias function, Mark Koennecke, January 2007
+
+ A new type of object function has been introduced ObjectFuncSelfParse. This
+ type of object function parses its command itself. As of now only one is
+ implemented for issuing Tcl commands from the command line, which will
+ stay a hidden feature. If more things of this type come along, then this
+ has to be expanded to become a full infrastructure.
+
+ Mark Koennecke, January 2010
---------------------------------------------------------------------------*/
#include
#include
@@ -71,13 +79,14 @@
#include "obdes.h"
#include "lld.h"
#include "dynstring.h"
+#include "commandlog.h"
/* M.Z. */
#include "definealias.h"
/* pvh */
#include "lld_str.h"
-static void printList(SConnection *pCon, int listID);
+static void printList(SConnection * pCon, int listID);
static void freeList(int listID);
#define MAXLEN 256
@@ -85,938 +94,913 @@ static void freeList(int listID);
#define MAXBUF 128
/*--------------------------------------------------------------------------*/
- SicsInterp *InitInterp(void)
- {
- SicsInterp *pInter = NULL;
- int i;
-
- pInter = (SicsInterp *)malloc(sizeof(SicsInterp));
- if(!pInter)
- {
- SICSLogWrite("Error allocating memory for Interpreter",eInternal);
- return NULL;
- }
- memset(pInter,0,sizeof(SicsInterp));
- pInter->pCList = NULL;
- pInter->AList.pFirst = NULL; /* M.Z. */
- pInter->pTcl = (void *)MacroInit(pInter);
- if(!pInter->pTcl)
- {
- free(pInter);
- return NULL;
- }
+SicsInterp *InitInterp(void)
+{
+ SicsInterp *pInter = NULL;
+ int i;
- pInter->iDeleting = 0;
- return pInter;
+ pInter = (SicsInterp *) malloc(sizeof(SicsInterp));
+ if (!pInter) {
+ SICSLogWrite("Error allocating memory for Interpreter", eInternal);
+ return NULL;
+ }
+ memset(pInter, 0, sizeof(SicsInterp));
+ pInter->pCList = NULL;
+ pInter->AList.pFirst = NULL; /* M.Z. */
+ pInter->pTcl = (void *) MacroInit(pInter);
+ if (!pInter->pTcl) {
+ free(pInter);
+ return NULL;
}
-/*------------------------------------------------------------------------*/
- int AddCommandWithFlag(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
- KillFunc pKFunc, void *pData, int startupOnly)
- {
- CommandList *pNew = NULL;
- CommandList *p, *tail;
- char pBueffel[512];
- assert(pName);
- assert(pFunc);
- assert(pInterp);
-
- strcpy(pBueffel,pName);
- strtolower(pBueffel);
- RemoveAlias(&pInterp->AList,pBueffel); /* M.Z. */
- if(FindCommand(pInterp,pBueffel) != NULL)
- {
- return 0;
+ pInter->iDeleting = 0;
+ return pInter;
+}
+
+/*------------------------------------------------------------------------*/
+int AddCommandWithFlag(SicsInterp * pInterp, char *pName, ObjectFunc pFunc,
+ KillFunc pKFunc, void *pData, int startupOnly)
+{
+ CommandList *pNew = NULL;
+ CommandList *p, *tail;
+ char pBueffel[512];
+
+ assert(pName);
+ assert(pFunc);
+ assert(pInterp);
+
+ strlcpy(pBueffel, pName,511);
+ strtolower(pBueffel);
+ RemoveAlias(&pInterp->AList, pBueffel); /* M.Z. */
+ if (FindCommand(pInterp, pBueffel) != NULL) {
+ return 0;
+ }
+
+ /* new memory */
+ pNew = (CommandList *) malloc(sizeof(CommandList));
+ if (!pNew) {
+ snprintf(pBueffel,sizeof(pBueffel)-1, "Out of memory creating command - %s -", pName);
+ SICSLogWrite(pBueffel, eInternal);
+ return 0;
+ }
+ memset(pNew, 0, sizeof(CommandList));
+
+ /* if no data given, initialise with Dummy struct */
+ if (!pData) {
+ pData = (void *) CreateDummy(pBueffel);
+ if (!pKFunc) {
+ pKFunc = KillDummy;
}
-
- /* new memory */
- pNew = (CommandList *)malloc(sizeof(CommandList));
- if(!pNew)
- {
- sprintf(pBueffel,
- "Out of memory creating command - %s -", pName);
- SICSLogWrite(pBueffel,eInternal);
- return 0;
- }
- memset(pNew,0,sizeof(CommandList));
-
- /* if no data given, initialise with Dummy struct */
- if(!pData)
- {
- pData = (void *)CreateDummy(pBueffel);
- if(!pKFunc)
- {
- pKFunc = KillDummy;
- }
- }
-
- /* initialise datastructures */
- pNew->pName = strdup(pBueffel);
- pNew->OFunc = pFunc;
- pNew->KFunc = pKFunc;
- pNew->pData = pData;
- pNew->pNext = NULL;
- pNew->startupOnly = startupOnly;
- pNew->stat = StatisticsNew(pBueffel);
-
- /* find end of list */
- tail = NULL;
- p = pInterp->pCList;
- while(p != NULL)
- {
- tail = p;
- p = p->pNext;
- }
- if (tail==NULL) { /* first entry */
- pInterp->pCList = pNew;
- } else { /* insert at tail */
- tail->pNext = pNew;
- }
- pNew->pPrevious = tail;
-
- return 1;
}
-/*------------------------------------------------------------------------*/
- int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
- KillFunc pKFunc, void *pData)
- {
- return AddCommandWithFlag(pInterp, pName, pFunc, pKFunc, pData, 0);
- }
-/*------------------------------------------------------------------------*/
- int AddIniCmd(char *pName, ObjectFunc pFunc)
- {
- return AddCommandWithFlag(pServ->pSics, pName, pFunc, NULL, NULL, 1);
- }
-/*------------------------------------------------------------------------*/
- int AddCmd(char *pName, ObjectFunc pFunc)
- {
- return AddCommandWithFlag(pServ->pSics, pName, pFunc, NULL, NULL, 0);
- }
-/*------------------------------------------------------------------------*/
- int RemoveCommand(SicsInterp *pInterp, char *pName)
- {
- CommandList *pVictim = NULL;
- char pBueffel[256];
- assert(pInterp);
- assert(pName);
-
- strcpy(pBueffel,pName);
- strtolower(pBueffel);
-
- if(pInterp->iDeleting)
- {
- return 0;
- }
-
- /* find our victim */
- pVictim = FindCommand(pInterp, pBueffel);
- if(!pVictim)
- return 0;
-
- /* found, remove it */
- /* kall KillFunction first */
- if(pVictim->KFunc)
- {
- pVictim->KFunc(pVictim->pData);
- }
-
- /* delete and unlink data */
- if(pVictim->pName)
- {
- free(pVictim->pName);
- }
- if(pVictim->pPrevious)
- {
- pVictim->pPrevious->pNext = pVictim->pNext;
- }
- if(pVictim->pNext)
- {
- pVictim->pNext->pPrevious = pVictim->pPrevious;
- }
- /* adjust headpointer if necessary */
- if(pVictim == pInterp->pCList)
- {
- pInterp->pCList = pVictim->pNext;
- }
- if (pVictim->stat) {
- StatisticsKill(pVictim->stat);
- }
- free(pVictim);
- return 1;
- }
+ /* initialise datastructures */
+ pNew->pName = strdup(pBueffel);
+ pNew->OFunc = pFunc;
+ pNew->KFunc = pKFunc;
+ pNew->pData = pData;
+ pNew->pNext = NULL;
+ pNew->startupOnly = startupOnly;
+ pNew->stat = StatisticsNew(pBueffel);
+ /* find end of list */
+ tail = NULL;
+ p = pInterp->pCList;
+ while (p != NULL) {
+ tail = p;
+ p = p->pNext;
+ }
+ if (tail == NULL) { /* first entry */
+ pInterp->pCList = pNew;
+ } else { /* insert at tail */
+ tail->pNext = pNew;
+ }
+ pNew->pPrevious = tail;
+
+ return 1;
+}
+
+/*------------------------------------------------------------------------*/
+int AddCommand(SicsInterp * pInterp, char *pName, ObjectFunc pFunc,
+ KillFunc pKFunc, void *pData)
+{
+ return AddCommandWithFlag(pInterp, pName, pFunc, pKFunc, pData, 0);
+}
+
+/*------------------------------------------------------------------------*/
+int AddIniCmd(char *pName, ObjectFunc pFunc)
+{
+ return AddCommandWithFlag(pServ->pSics, pName, pFunc, NULL, NULL, 1);
+}
+
+/*------------------------------------------------------------------------*/
+int AddCmd(char *pName, ObjectFunc pFunc)
+{
+ return AddCommandWithFlag(pServ->pSics, pName, pFunc, NULL, NULL, 0);
+}
+
+/*------------------------------------------------------------------------*/
+int RemoveCommand(SicsInterp * pInterp, char *pName)
+{
+ CommandList *pVictim = NULL;
+ char pBueffel[256];
+
+ assert(pInterp);
+ assert(pName);
+
+ strlcpy(pBueffel, pName,255);
+ strtolower(pBueffel);
+
+ if (pInterp->iDeleting) {
+ return 0;
+ }
+
+ /* find our victim */
+ pVictim = FindCommand(pInterp, pBueffel);
+ if (!pVictim)
+ return 0;
+
+ /* found, remove it */
+ /* kall KillFunction first */
+ if (pVictim->KFunc) {
+ void *data = pVictim->pData;
+ pVictim->pData = NULL; /* make data unreachable by FindCommandData before killing */
+ pVictim->KFunc(data);
+ }
+
+ /* delete and unlink data */
+ if (pVictim->pName) {
+ free(pVictim->pName);
+ }
+ if (pVictim->pPrevious) {
+ pVictim->pPrevious->pNext = pVictim->pNext;
+ }
+ if (pVictim->pNext) {
+ pVictim->pNext->pPrevious = pVictim->pPrevious;
+ }
+ /* adjust headpointer if necessary */
+ if (pVictim == pInterp->pCList) {
+ pInterp->pCList = pVictim->pNext;
+ }
+ if (pVictim->stat) {
+ StatisticsKill(pVictim->stat);
+ }
+ free(pVictim);
+ return 1;
+}
#define MAXLEN 256
#define MAXCOM 50
-extern char *stptok(char *s, char *tok, unsigned int toklen, char *brk);
+extern char *stptok(char *s, char *tok, unsigned int toklen, char *brk);
extern char *SkipSpace(char *pPtr);
/*-----------------------------------------------------------------------*/
- int InterpExecute(SicsInterp *self,SConnection *pCon, char *pText)
- {
- int iCount = 0;
- int iRet;
- int i, argc;
- char pBueffel[1024];
- CommandList *pCommand = NULL;
- char pBrk[] = {" \r\n\0"};
- char *pPtr;
- char **argv = NULL;
- commandContext comCon;
- Statistics *old;
-
-
- assert(self);
- assert(pCon);
+static char tclescape[] = "tcl:";
- /* write info to Log */
- if(pCon->pSock)
- {
- sprintf(pBueffel,"Executing -> %s <- from socket %d",pText,
- pCon->pSock->sockid);
- SICSLogWrite(pBueffel,eCommand);
- }
- else
- {
- sprintf(pBueffel, "Executing -> %s <- from dummy socket\n", pText);
- SICSLogWrite(pBueffel,eCommand);
- }
+static int TclExecFunc(SConnection *pCon, SicsInterp *pInter, void *data,
+ char *command)
+{
+ int status;
+ char *realcommand;
- /* convert to argc, argv */
- argc = 0;
- argv = NULL;
- Text2Arg(pText,&argc,&argv);
-
- /* the first one must be the target object. If not given an empty
- command string was given which will be silently ignored */
- if(argc < 1)
- {
- iRet = 1;
- goto deleteArgv;
- }
+ if(!SCMatchRights(pCon,usMugger)){
+ return 0;
+ }
- if(argv[0] == NULL)
- {
- SCWrite(pCon,"ERROR: failed to parse command",eError);
- iRet = -1;
- goto deleteArgv;
- }
-
- /* find it */
- pCommand = FindCommand(self,argv[0]);
- if(!pCommand)
- {
- sprintf(pBueffel,"ERROR: Object -> %s <- NOT found",
- argv[0]);
- SCWrite(pCon,pBueffel,eError);
- iRet = -1;
- goto deleteArgv;
- }
+ realcommand = command + strlen(tclescape);
+ MacroPush(pCon);
+ status = Tcl_Eval(InterpGetTcl(pInter), realcommand);
+ MacroPop();
+ if(status == TCL_OK){
+ SCWrite(pCon,(char *)Tcl_GetStringResult(InterpGetTcl(pInter)), eValue );
+ return 1;
+ } else {
+ SCWrite(pCon,(char *)Tcl_GetStringResult(InterpGetTcl(pInter)), eValue );
+ return 0;
-
- /* invoke the command */
- self->eOut = eStatus;
- Tcl_ResetResult((Tcl_Interp *)self->pTcl);
- MacroPush(pCon);
- pCon->conStatus = 0;
- old = StatisticsBegin(pCommand->stat);
- iRet = pCommand->OFunc(pCon, self, pCommand->pData, argc, argv);
- StatisticsEnd(old);
- /* If a task is registered with the dev exec then conStatus is HWBusy*/
- if (pCon->conStatus != HWBusy) {
- comCon = SCGetContext(pCon);
- if (0 != strcmp("contextdo",comCon.deviceID))
- SCWrite(pCon,"",eFinish);
- }
- MacroPop();
+ }
+ return 0;
+}
+/*-----------------------------------------------------------------------*/
+int InterpExecute(SicsInterp * self, SConnection * pCon, char *pText)
+{
+ int iCount = 0;
+ int iRet;
+ int i, argc;
+ char pBueffel[1024];
+ CommandList *pCommand = NULL;
+ char pBrk[] = { " \r\n\0" };
+ char *pPtr;
+ char **argv = NULL;
+ commandContext comCon;
+ Statistics *old;
- deleteArgv:
- if (argv) {
- /* delete argv */
- for(i = 0; i < argc; i++)
- {
- if(argv[i] != NULL)
- {
- free(argv[i]);
- }
- }
- free(argv);
- }
- return iRet;
+ assert(self);
+ assert(pCon);
+
+ /* write info to Log */
+ if (pCon->sockHandle >= 0) {
+ snprintf(pBueffel,1023, "Executing -> %s <- from socket %d", pText,
+ pCon->sockHandle);
+ SICSLogWrite(pBueffel, eCommand);
+ } else {
+ snprintf(pBueffel,1023, "Executing -> %s <- from dummy socket\n", pText);
+ SICSLogWrite(pBueffel, eCommand);
}
+
+ if(strstr(pText,tclescape) == pText){
+ return TclExecFunc(pCon,self,NULL,pText);
+ }
+
+ /* convert to argc, argv */
+ /* use Tcl_SplitList instead of Text2Arg, is needed for complicated Tcl syntax. M.Z. 8.2011 */
+ iRet = Tcl_SplitList(self->pTcl, pText, &argc, (const char ***)&argv);
+ if (iRet != TCL_OK) {
+ SCWrite(pCon, "ERROR: illegal tcl syntax", eError);
+ return -1;
+ }
+
+ /* the first one must be the target object. If not given an empty
+ command string was given which will be silently ignored */
+ if (argc < 1) {
+ iRet = 1;
+ goto deleteArgv;
+ }
+
+ if (argv[0] == NULL) {
+ SCWrite(pCon, "ERROR: failed to parse command", eError);
+ iRet = -1;
+ goto deleteArgv;
+ }
+
+ /* find it */
+ pCommand = FindCommand(self, argv[0]);
+ if (!pCommand) {
+ snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Object -> %s <- NOT found", argv[0]);
+ SCWrite(pCon, pBueffel, eError);
+ iRet = -1;
+ goto deleteArgv;
+ }
+
+
+ /* invoke the command */
+ self->eOut = eValue;
+ Tcl_ResetResult((Tcl_Interp *) self->pTcl);
+ MacroPush(pCon);
+ pCon->conStatus = 0;
+ old = StatisticsBegin(pCommand->stat);
+ iRet = pCommand->OFunc(pCon, self, pCommand->pData, argc, argv);
+ StatisticsEnd(old);
+ /* If a task is registered with the dev exec then conStatus is HWBusy */
+ if (pCon->conStatus != HWBusy) {
+ /*comCon = SCGetContext(pCon); */
+ if (0 != strcmp("contextdo", pCon->deviceID))
+ SCWrite(pCon, "", eFinish);
+ }
+ MacroPop();
+
+ /*
+ * log in history if succesfull
+ */
+ if(iRet == 1){
+ WriteCommandHistory(pText);
+ }
+
+
+deleteArgv:
+ Tcl_Free((char *)argv);
+ return iRet;
+}
+
/*------------------------------------------------------------------------*/
- CommandList *FindCommand(SicsInterp *self, char *pName)
- {
- CommandList *pCurrent = NULL;
- char pBueffel[256], *pCmd;
+CommandList *FindCommand(SicsInterp * self, char *pName)
+{
+ CommandList *pCurrent = NULL;
+ char pBuffer[1024], *pCmd, *pBueffel = NULL;
- assert(self);
-
- if(self->iDeleting)
- {
- return NULL;
- }
-
- strcpy(pBueffel,pName);
- strtolower(pBueffel);
+ assert(self);
- pCmd=TranslateAlias(&self->AList, pBueffel); /* M.Z. */
-
- pCurrent = self->pCList;
- while(pCurrent)
- {
- if(pCurrent->pName != NULL)
- {
- if(strcmp(pCurrent->pName, pCmd) == 0 ) /* M.Z. */
- {
- return pCurrent;
- }
- }
- pCurrent = pCurrent->pNext;
- }
+ if (self->iDeleting) {
return NULL;
- }
+ }
+
+ if(strlen(pName) > sizeof(pBuffer)){
+ pBueffel = malloc((strlen(pName)+1)*sizeof(char));
+ if(pBueffel == NULL){
+ return NULL;
+ }
+ memset(pBueffel,0,strlen(pName)+1);
+ } else {
+ pBueffel = pBuffer;
+ }
+
+ memset(pBueffel,0,1024);
+ strlcpy(pBueffel, pName,1023);
+ strtolower(pBueffel);
+
+ pCmd = TranslateAlias(&self->AList, pBueffel); /* M.Z. */
+
+ pCurrent = self->pCList;
+ while (pCurrent) {
+ if (pCurrent->pName != NULL) {
+ if (strcmp(pCurrent->pName, pCmd) == 0) { /* M.Z. */
+ if(pBueffel != pBuffer){
+ free(pBueffel);
+ }
+ return pCurrent;
+ }
+ }
+ pCurrent = pCurrent->pNext;
+ }
+ if(pBueffel != pBuffer){
+ free(pBueffel);
+ }
+ return NULL;
+}
+
/*------------------------------------------------------------------------*/
- int WriteSicsStatus(SicsInterp *self, char *file, int iMot)
- {
- CommandList *pCurrent = NULL;
- FILE *fd = NULL;
- Dummy *pDum = NULL;
- float fVal;
- pIDrivable pDriv = NULL;
- void *pTest = NULL;
- char tmpfile[PATH_MAX];
- int l;
-
- assert(self);
- assert(file);
-
- /* make sure that status file is always valid M.Z. Apr 2005 */
- /* create a temporary file first */
- l=strlen(file);
- if (l >= sizeof tmpfile - 2) {
- return 0;
- }
- strcpy(tmpfile, file);
- tmpfile[l]='.';
- tmpfile[l+1]='\0';
- remove(tmpfile); /* remove already existing file */
-
- fd = fopen(tmpfile,"w");
- if(!fd)
- {
- return 0;
- }
-
- /* cycle through the list */
- pCurrent = self->pCList;
- while(pCurrent)
- {
- pDum = (Dummy *)pCurrent->pData;
- if(pDum)
- {
- pDum->pDescriptor->SaveStatus(pCurrent->pData,pCurrent->pName,fd);
- if(iMot)
- {
- /*
- save values of motors but not of environment devices as they
- may not be present the next time round
- */
- pDriv = pDum->pDescriptor->GetInterface(pDum,DRIVEID);
- pTest = pDum->pDescriptor->GetInterface(pDum,ENVIRINTERFACE);
- if(pDriv && !pTest)
- {
- if(strcmp(pDum->pDescriptor->name,"Motor") == 0)
- {
- MotorGetSoftPosition((pMotor)pDum,pServ->dummyCon,&fVal);
- }
- else
- {
- fVal = pDriv->GetValue(pDum,pServ->dummyCon);
- }
- if(fVal > -990.)
- {
- fprintf(fd,"drive %s %f\n",pCurrent->pName, fVal);
- }
+int WriteSicsStatus(SicsInterp * self, char *file, int iMot)
+{
+ CommandList *pCurrent = NULL;
+ FILE *fd = NULL;
+ Dummy *pDum = NULL;
+ float fVal;
+ pIDrivable pDriv = NULL;
+ void *pTest = NULL;
+ char tmpfile[PATH_MAX];
+ int l;
+
+ assert(self);
+ assert(file);
+
+ /* make sure that status file is always valid M.Z. Apr 2005 */
+ /* create a temporary file first */
+ l = strlen(file);
+ if (l >= sizeof tmpfile - 2) {
+ return 0;
+ }
+ strcpy(tmpfile, file);
+ tmpfile[l] = '.';
+ tmpfile[l + 1] = '\0';
+ remove(tmpfile); /* remove already existing file */
+
+ fd = fopen(tmpfile, "w");
+ if (!fd) {
+ return 0;
+ }
+
+ /* cycle through the list */
+ pCurrent = self->pCList;
+ while (pCurrent) {
+ pDum = (Dummy *) pCurrent->pData;
+ if (pDum) {
+ pDum->pDescriptor->SaveStatus(pCurrent->pData, pCurrent->pName, fd);
+ if (iMot) {
+ /*
+ save values of motors but not of environment devices as they
+ may not be present the next time round
+ */
+ pDriv = pDum->pDescriptor->GetInterface(pDum, DRIVEID);
+ pTest = pDum->pDescriptor->GetInterface(pDum, ENVIRINTERFACE);
+ if (pDriv && !pTest) {
+ if (strcmp(pDum->pDescriptor->name, "Motor") == 0) {
+ MotorGetSoftPosition((pMotor) pDum, pServ->dummyCon, &fVal);
+ } else {
+ fVal = pDriv->GetValue(pDum, pServ->dummyCon);
+ }
+ if (fVal > -990.) {
+ fprintf(fd, "syncdrive %s %f\n", pCurrent->pName, fVal);
}
}
}
- pCurrent = pCurrent->pNext;
- }
- if(iMot)
- {
- fprintf(fd,"Success \n");
- }
- fclose(fd);
- /* rename temporary to final file (this is an atomic action) */
- if (0 > rename(tmpfile, file)) {
- return 0;
- }
- return 1;
- }
-/*------------------------------------------------------------------------*/
- void DeleteInterp(SicsInterp *self)
- {
- CommandList *pCurrent = NULL;
- CommandList *pTemp, *tail;
- Tcl_Interp *pTcl = NULL;
- int i;
-
- assert(self);
- self->iDeleting = 1;
-
- /* find end of list */
- tail = NULL;
- pCurrent = self->pCList;
- while(pCurrent != NULL)
- {
- tail = pCurrent;
- pCurrent = pCurrent->pNext;
- }
-
- /* delete Commandlist (reversed order) */
- if (tail) {
- pCurrent = tail;
- while(pCurrent)
- {
- /* the line below fixes problems with kill functions
- * traversing the command list
- */
- pCurrent->pNext = NULL;
- if(pCurrent->KFunc)
- {
- pCurrent->KFunc(pCurrent->pData);
- }
- if(pCurrent->pName)
- {
- /* printf("Deleting %s\n",pCurrent->pName); */
- free(pCurrent->pName);
- }
- if (pCurrent->stat) {
- StatisticsKill(pCurrent->stat);
- }
- pTemp = pCurrent->pPrevious;
- free(pCurrent);
- pCurrent = pTemp;
- }
- }
-
- FreeAliasList(&self->AList); /* M.Z. */
-
- /* clear Tcl_Interpreter. Must be AFTER deleting command list because
- some devices may have Tcl drivers which need to be accessed for
- proper closing of devices.
- */
- pTcl = (Tcl_Interp *)self->pTcl;
- if(pTcl)
- {
- /*
- uncommented: the current versions of Tcl (8.3,4) dump core with a
- memory problem deep in the Tcl library. This causes a core dump on
- each SICS restart and breaks the use of external tools.
- Tcl_DeleteInterp(pTcl);
-
- call KillSicsUnknown instead to clean up all memory properly. M.Z., Apr 05
- */
- KillSicsUnknown();
- }
-
- free(self);
- }
-/*------------------------------------------------------------------------*/
-static void printAll(SicsInterp *pSics, SConnection *pCon)
-{
- CommandList *pCurrent;
- char pBueffel[256];
- int iNum = 0;
-
- assert(pSics);
- assert(pCon);
-
- pCurrent = pSics->pCList;
- while(pCurrent)
- {
- if(iNum == 0)
- {
- strcpy(pBueffel,pCurrent->pName);
- iNum++;
- }
- else if(iNum < 4)
- {
- strcat(pBueffel," ");
- strcat(pBueffel,pCurrent->pName);
- iNum++;
- }
- else
- {
- strcat(pBueffel," ");
- strcat(pBueffel,pCurrent->pName);
- strcat(pBueffel,"\r\n");
- SCWrite(pCon,pBueffel,eStatus);
- iNum = 0;
- pBueffel[0]='\0';
- }
- pCurrent = pCurrent->pNext;
- }
-
- /* write final entries */
- if(strlen(pBueffel) > 2)
- {
- strcat(pBueffel,"\r\n");
- SCWrite(pCon,pBueffel,eStatus);
}
+ pCurrent = pCurrent->pNext;
+ }
+ if (iMot) {
+ fprintf(fd, "Success \n");
+ }
+ fclose(fd);
+ /* rename temporary to final file (this is an atomic action) */
+ if (0 > rename(tmpfile, file)) {
+ return 0;
+ }
+ return 1;
}
+
+/*------------------------------------------------------------------------*/
+void DeleteInterp(SicsInterp * self)
+{
+ CommandList *pCurrent = NULL;
+ CommandList *pTemp, *tail;
+ Tcl_Interp *pTcl = NULL;
+ int i;
+
+ assert(self);
+ self->iDeleting = 1;
+
+ /* find end of list */
+ tail = NULL;
+ pCurrent = self->pCList;
+ while (pCurrent != NULL) {
+ tail = pCurrent;
+ pCurrent = pCurrent->pNext;
+ }
+
+ /* delete Commandlist (reversed order) */
+ if (tail) {
+ pCurrent = tail;
+ while (pCurrent) {
+ pCurrent->pNext = NULL; /* inhibit access to killed commands by FindCommandData */
+ if (pCurrent->KFunc) {
+ void *data = pCurrent->pData;
+ pCurrent->pData = NULL; /* make data unreachable by FindCommandData before killing */
+ pCurrent->KFunc(data);
+ }
+ if (pCurrent->pName) {
+ /* printf("Deleting %s\n",pCurrent->pName); */
+ free(pCurrent->pName);
+ }
+ if (pCurrent->stat) {
+ StatisticsKill(pCurrent->stat);
+ }
+ pTemp = pCurrent->pPrevious;
+ free(pCurrent);
+ pCurrent = pTemp;
+ }
+ }
+
+ FreeAliasList(&self->AList); /* M.Z. */
+
+ /* clear Tcl_Interpreter. Must be AFTER deleting command list because
+ some devices may have Tcl drivers which need to be accessed for
+ proper closing of devices.
+ */
+ pTcl = (Tcl_Interp *) self->pTcl;
+ if (pTcl) {
+ /*
+ uncommented: the current versions of Tcl (8.3,4) dump core with a
+ memory problem deep in the Tcl library. This causes a core dump on
+ each SICS restart and breaks the use of external tools.
+ Tcl_DeleteInterp(pTcl);
+
+ call KillSicsUnknown instead to clean up all memory properly. M.Z., Apr 05
+ */
+ KillSicsUnknown();
+ }
+
+ free(self);
+}
+
+/*------------------------------------------------------------------------*/
+static void printAll(SicsInterp * pSics, SConnection * pCon)
+{
+ CommandList *pCurrent;
+ char pBueffel[256];
+ int iNum = 0;
+
+ assert(pSics);
+ assert(pCon);
+
+ pCurrent = pSics->pCList;
+ while (pCurrent) {
+ if (iNum == 0) {
+ strlcpy(pBueffel, pCurrent->pName,255);
+ iNum++;
+ } else if (iNum < 4) {
+ strlcat(pBueffel, " ",255);
+ strlcat(pBueffel, pCurrent->pName,255);
+ iNum++;
+ } else {
+ strlcat(pBueffel, " ",255);
+ strlcat(pBueffel, pCurrent->pName,255);
+ strcat(pBueffel, "\r\n");
+ SCWrite(pCon, pBueffel, eValue);
+ iNum = 0;
+ pBueffel[0] = '\0';
+ }
+ pCurrent = pCurrent->pNext;
+ }
+
+ /* write final entries */
+ if (strlen(pBueffel) > 2) {
+ strlcat(pBueffel, "\r\n",255);
+ SCWrite(pCon, pBueffel, eValue);
+ }
+}
+
/*------------------------------------------------------------------------*/
/* compareStringNode wraps strcmp for use in findNode(LLD module) calls */
int compareStringNode(const void *pStr1, const void *ppStr2)
{
- return strcmp((char *)pStr1,*(char **)ppStr2);
+ return strcmp((char *) pStr1, *(char **) ppStr2);
}
+
/*------------------------------------------------------------------------
printAllTypes prints the list of types of objects instantiated on the
CommandList.
iFiltered=0 gives all objects including interpreter command objects
iFiltered=1 gives types where object name is not the same as its type
-------------------------------------------------------------------------*/
-static void printAllTypes(SicsInterp *pSics, SConnection *pCon, int iFiltered)
+static void printAllTypes(SicsInterp * pSics, SConnection * pCon,
+ int iFiltered)
{
- CommandList *pCurrent = NULL;
- char pBueffel[256];
- char pName_lc[256];
- char pType_lc[256];
- char *pType;
- Dummy *pTest;
- int typeListID;
-
- assert(pSics);
- assert(pCon);
+ CommandList *pCurrent = NULL;
+ char pBueffel[256];
+ char pName_lc[256];
+ char pType_lc[256];
+ char *pType;
+ Dummy *pTest;
+ int typeListID;
- pBueffel[0] = '\0';
-
- typeListID = LLDstringCreate();
- if(-1==typeListID)
- {
- strcpy(pBueffel,"ERROR: Cannot generate list of object types\r\n");
- SCWrite(pCon,pBueffel,eStatus);
- return;
- }
-
- pCurrent = pSics->pCList;
- while(pCurrent)
- {
- if(NULL != pCurrent->pData)
- {
- pTest = (pDummy)pCurrent->pData;
- if(NULL != pTest->pDescriptor)
- {
- pType = pTest->pDescriptor->name;
- strcpy(pType_lc,pType);
- strtolower(pType_lc);
-
- LLDnodePtr2First(typeListID);
+ assert(pSics);
+ assert(pCon);
- /* int LLDnodeFind( int List, CompFunPtr Compare, void * DataPtr ); */
- /* */
- /* Find *DataPtr in the List using the *Compare function. */
- /* Returns the return value of *Compare. */
- /* 0 == equal == found. */
- /* non-zero == not found. Current node is set to found node. */
- /* Returns 2 for an empty list. */
- /* NB: First checked node is current node, then search to end of list*/
-
- if(0!=LLDnodeFind(typeListID,compareStringNode,(void *)pType))
- { /* empty list or 'typename' not found */
- strcpy(pName_lc, pCurrent->pName);
- strtolower(pName_lc);
- if((0==iFiltered)||((1==iFiltered)&&(0!=strcmp(pType_lc,pName_lc))))
- { /*ie Add if unfiltered or pass filter(name!=typename) */
- LLDstringAdd(typeListID,pType);
- }
- }
- }
- }
- pCurrent = pCurrent->pNext;
+ pBueffel[0] = '\0';
+
+ typeListID = LLDstringCreate();
+ if (-1 == typeListID) {
+ strcpy(pBueffel, "ERROR: Cannot generate list of object types\r\n");
+ SCWrite(pCon, pBueffel, eValue);
+ return;
+ }
+
+ pCurrent = pSics->pCList;
+ while (pCurrent) {
+ if (NULL != pCurrent->pData) {
+ pTest = (pDummy) pCurrent->pData;
+ if (NULL != pTest->pDescriptor) {
+ pType = pTest->pDescriptor->name;
+ strlcpy(pType_lc, pType,255);
+ strtolower(pType_lc);
+
+ LLDnodePtr2First(typeListID);
+
+ /* int LLDnodeFind( int List, CompFunPtr Compare, void * DataPtr ); */
+ /* */
+ /* Find *DataPtr in the List using the *Compare function. */
+ /* Returns the return value of *Compare. */
+ /* 0 == equal == found. */
+ /* non-zero == not found. Current node is set to found node. */
+ /* Returns 2 for an empty list. */
+ /* NB: First checked node is current node, then search to end of list */
+
+ if (0 != LLDnodeFind(typeListID, compareStringNode, (void *) pType)) { /* empty list or 'typename' not found */
+ strlcpy(pName_lc, pCurrent->pName,255);
+ strtolower(pName_lc);
+ if ((0 == iFiltered) || ((1 == iFiltered) && (0 != strcmp(pType_lc, pName_lc)))) { /*ie Add if unfiltered or pass filter(name!=typename) */
+ LLDstringAdd(typeListID, pType);
+ }
+ }
+ }
}
- printList(pCon,typeListID);
- freeList(typeListID);
+ pCurrent = pCurrent->pNext;
+ }
+ printList(pCon, typeListID);
+ freeList(typeListID);
}
+
/*-----------------------------------------------------------------------
printInterface prints only those objects which implement an interface
as specified bi the id given
-------------------------------------------------------------------------*/
-static void printInterface(SicsInterp *pSics, SConnection *pCon, int id)
+static void printInterface(SicsInterp * pSics, SConnection * pCon, int id)
{
- CommandList *pCurrent;
- char pBueffel[256];
- int iNum = 0;
- pObjectDescriptor pObj = NULL;
+ CommandList *pCurrent;
+ char pBueffel[256];
+ int iNum = 0;
+ pObjectDescriptor pObj = NULL;
- assert(pSics);
- assert(pCon);
+ assert(pSics);
+ assert(pCon);
- pBueffel[0] = '\0';
- pCurrent = pSics->pCList;
- while(pCurrent)
- {
- pObj = FindDescriptor(pCurrent->pData);
- if(pObj != NULL)
- {
- if(pObj->GetInterface(pObj,id) != NULL)
- {
- if(iNum == 0)
- {
- strcpy(pBueffel,pCurrent->pName);
- iNum++;
- }
- else if(iNum < 4)
- {
- strcat(pBueffel," ");
- strcat(pBueffel,pCurrent->pName);
- iNum++;
- }
- else
- {
- strcat(pBueffel," ");
- strcat(pBueffel,pCurrent->pName);
- strcat(pBueffel,"\r\n");
- SCWrite(pCon,pBueffel,eStatus);
- iNum = 0;
- pBueffel[0]='\0';
- }
- }
+ pBueffel[0] = '\0';
+ pCurrent = pSics->pCList;
+ while (pCurrent) {
+ pObj = FindDescriptor(pCurrent->pData);
+ if (pObj != NULL) {
+ if (pObj->GetInterface(pObj, id) != NULL) {
+ if (iNum == 0) {
+ strlcpy(pBueffel, pCurrent->pName,255);
+ iNum++;
+ } else if (iNum < 4) {
+ strlcat(pBueffel, " ",255);
+ strlcat(pBueffel, pCurrent->pName,255);
+ iNum++;
+ } else {
+ strlcat(pBueffel, " ",255);
+ strlcat(pBueffel, pCurrent->pName,255);
+ strlcat(pBueffel, "\r\n",255);
+ SCWrite(pCon, pBueffel, eValue);
+ iNum = 0;
+ pBueffel[0] = '\0';
+ }
}
- pCurrent = pCurrent->pNext;
}
-
- /* write final entries */
- strcat(pBueffel,"\r\n");
- SCWrite(pCon,pBueffel,eStatus);
+ pCurrent = pCurrent->pNext;
+ }
+
+ /* write final entries */
+ strcat(pBueffel, "\r\n");
+ SCWrite(pCon, pBueffel, eValue);
}
+
/*-----------------------------------------------------------------------
printMatch prints only those objects which match the wildcard string given
-------------------------------------------------------------------------*/
-extern int match(const char *mask, const char *name); /* from wwildcard.c */
+extern int match(const char *mask, const char *name); /* from wwildcard.c */
-static void printMatch(SicsInterp *pSics, SConnection *pCon, char *mask)
+static void printMatch(SicsInterp * pSics, SConnection * pCon, char *mask)
{
- CommandList *pCurrent;
- char pBueffel[256];
- int iNum = 0;
- pObjectDescriptor pObj = NULL;
+ CommandList *pCurrent;
+ char pBueffel[256];
+ int iNum = 0;
+ pObjectDescriptor pObj = NULL;
- assert(pSics);
- assert(pCon);
+ assert(pSics);
+ assert(pCon);
- pBueffel[0] = '\0';
- pCurrent = pSics->pCList;
- while(pCurrent)
- {
- pObj = FindDescriptor(pCurrent->pData);
- if(pObj != NULL)
- {
- if(!match(mask,pObj->name))
- {
- if(iNum == 0)
- {
- strcpy(pBueffel,pCurrent->pName);
- iNum++;
- }
- else if(iNum < 4)
- {
- strcat(pBueffel," ");
- strcat(pBueffel,pCurrent->pName);
- iNum++;
- }
- else
- {
- strcat(pBueffel," ");
- strcat(pBueffel,pCurrent->pName);
- strcat(pBueffel,"\r\n");
- SCWrite(pCon,pBueffel,eStatus);
- pBueffel[0]='\0';
- iNum = 0;
- }
- }
+ pBueffel[0] = '\0';
+ pCurrent = pSics->pCList;
+ while (pCurrent) {
+ pObj = FindDescriptor(pCurrent->pData);
+ if (pObj != NULL) {
+ if (!match(mask, pObj->name)) {
+ if (iNum == 0) {
+ strlcpy(pBueffel, pCurrent->pName,255);
+ iNum++;
+ } else if (iNum < 4) {
+ strlcat(pBueffel, " ",255);
+ strlcat(pBueffel, pCurrent->pName,255);
+ iNum++;
+ } else {
+ strlcat(pBueffel, " ",255);
+ strlcat(pBueffel, pCurrent->pName,255);
+ strlcat(pBueffel, "\r\n",255);
+ SCWrite(pCon, pBueffel, eValue);
+ pBueffel[0] = '\0';
+ iNum = 0;
+ }
}
- pCurrent = pCurrent->pNext;
}
-
- /* write final entries */
- strcat(pBueffel,"\r\n");
- SCWrite(pCon,pBueffel,eStatus);
+ pCurrent = pCurrent->pNext;
+ }
+
+ /* write final entries */
+ strlcat(pBueffel, "\r\n",255);
+ SCWrite(pCon, pBueffel, eValue);
}
+
/*-----------------------------------------------------------------------
printType prints only those objects whose descriptor match the type given
-------------------------------------------------------------------------*/
-static void printType(SicsInterp *pSics, SConnection *pCon, char *typeName)
+static void printType(SicsInterp * pSics, SConnection * pCon,
+ char *typeName)
{
- CommandList *pCurrent;
- Tcl_DString txt;
- char pBueffel[256];
- int iNum = 0;
+ CommandList *pCurrent;
+ Tcl_DString txt;
+ char pBueffel[256];
+ int iNum = 0;
- assert(pSics);
- assert(pCon);
+ assert(pSics);
+ assert(pCon);
- Tcl_DStringInit(&txt);
- pBueffel[0] = '\0';
- pCurrent = pSics->pCList;
- while(pCurrent)
- {
- if(pCurrent->pData != NULL)
- {
- if(iHasType(pCurrent->pData,typeName))
- {
- if(iNum == 0)
- {
- strcpy(pBueffel,pCurrent->pName);
- iNum++;
- }
- else if(iNum < 4)
- {
- strcat(pBueffel," ");
- strcat(pBueffel,pCurrent->pName);
- iNum++;
- }
- else
- {
- strcat(pBueffel," ");
- strcat(pBueffel,pCurrent->pName);
- strcat(pBueffel,"\r\n");
- Tcl_DStringAppend(&txt,pBueffel,-1);
- pBueffel[0]='\0';
- iNum = 0;
- }
- }
+ Tcl_DStringInit(&txt);
+ pBueffel[0] = '\0';
+ pCurrent = pSics->pCList;
+ while (pCurrent) {
+ if (pCurrent->pData != NULL) {
+ if (iHasType(pCurrent->pData, typeName)) {
+ if (iNum == 0) {
+ strlcpy(pBueffel, pCurrent->pName,255);
+ iNum++;
+ } else if (iNum < 4) {
+ strlcat(pBueffel, " ",255);
+ strlcat(pBueffel, pCurrent->pName,255);
+ iNum++;
+ } else {
+ strlcat(pBueffel, " ",255);
+ strlcat(pBueffel, pCurrent->pName,255);
+ strlcat(pBueffel, "\r\n",255);
+ Tcl_DStringAppend(&txt, pBueffel, -1);
+ pBueffel[0] = '\0';
+ iNum = 0;
+ }
}
- pCurrent = pCurrent->pNext;
}
-
- /* write final entries */
- strcat(pBueffel,"\r\n");
- SCWrite(pCon,Tcl_DStringValue(&txt),eStatus);
- Tcl_DStringFree(&txt);
+ pCurrent = pCurrent->pNext;
+ }
+
+ /* write final entries */
+ strlcat(pBueffel, "\r\n",255);
+ SCWrite(pCon, Tcl_DStringValue(&txt), eValue);
+ Tcl_DStringFree(&txt);
}
+
/*--------------------------------------------------------------------------*/
- int ListObjects(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- char pType[256];
- int i;
-
- if(argc < 2)
- {
- printAll(pSics,pCon);
- return 1;
- }
-
- strtolower(argv[1]);
- /*
- stand alone subcommands
- */
- if(strstr(argv[1],"var") != NULL)
- {
- printType(pSics,pCon,"SicsVariable");
- return 1;
- }
- if(strstr(argv[1],"mot") != NULL)
- {
- printType(pSics,pCon,"Motor");
- return 1;
- }
- /* Start Mod by Paul Hathaway May 2004 */
- if(0 == strcmp(argv[1],"types"))
- {
- printAllTypes(pSics,pCon,1);
- return 1;
- }
- /* End Mod by Paul Hathaway May 2004*/
-
-
- /*
- subcommand with three args
- */
- if(argc < 3)
- {
- SCWrite(pCon,"ERROR: missing parameter to command or bad subcommand",
- eError);
- return 0;
- }
-
- /*
- interface
- */
- if(strcmp(argv[1],"inter") == 0)
- {
- strtolower(argv[2]);
- if(strstr(argv[2],"driv") != NULL)
- {
- printInterface(pSics,pCon,DRIVEID);
- return 1;
- }
- if(strstr(argv[2],"coun") != NULL)
- {
- printInterface(pSics,pCon,COUNTID);
- return 1;
- }
- if(strstr(argv[2],"env") != NULL)
- {
- printInterface(pSics,pCon,ENVIRINTERFACE);
- return 1;
- }
- SCWrite(pCon,"ERROR: interface description not recognized",eError);
- return 0;
- }
- /*
- match
- */
- if(strcmp(argv[1],"match") == 0)
- {
- printMatch(pSics,pCon,argv[2]);
- return 1;
- }
-
- /* Start Mod by Paul Hathaway May 2004 */
- /*
- * type-based dir
- */
- if(0 == strcmp(argv[1],"type"))
- {
- if(0==strcmp(argv[2],"*"))
- {
- printAllTypes(pSics,pCon,0);
- return 1;
- }
- strcpy(pType,argv[2]);
- /* Cater for multi-word types eg 'Environment Monitor' */
- if(argc > 3)
- {
- for(i=3;ipTcl;
- Tcl_SetResult(pTcl,buffer,TCL_VOLATILE);
+
+ strtolower(argv[1]);
+ /*
+ stand alone subcommands
+ */
+ if (strstr(argv[1], "var") != NULL) {
+ printType(pSics, pCon, "SicsVariable");
return 1;
}
-/*---------------------------------------------------------------------------*/
- Tcl_Interp *InterpGetTcl(SicsInterp *pSics)
- {
- Tcl_Interp *pTcl = NULL;
-
- pTcl = (Tcl_Interp *)pSics->pTcl;
- return pTcl;
+ if (strstr(argv[1], "mot") != NULL) {
+ printType(pSics, pCon, "Motor");
+ return 1;
}
-/*---------------------------------------------------------------------------*/
- void strtolower(char *pText)
- {
- assert(pText);
-
- while(*pText != '\0')
- {
- *pText = tolower(*pText);
- pText++;
- }
+ /* Start Mod by Paul Hathaway May 2004 */
+ if (0 == strcmp(argv[1], "types")) {
+ printAllTypes(pSics, pCon, 1);
+ return 1;
}
-/*---------------------------------------------------------------------------*/
- void argtolower(int argc, char *argv[])
- {
- int i;
-
- for(i = 0; i < argc; i++)
- {
- strtolower(argv[i]);
- }
- }
-
-/*------------------------------------------------------------------------*/
- char *FindAlias(SicsInterp *self, void *pData)
- {
- CommandList *pCurrent = NULL;
+ /* End Mod by Paul Hathaway May 2004 */
- assert(self);
-
- if(self->iDeleting)
- {
- return NULL;
+
+ /*
+ subcommand with three args
+ */
+ if (argc < 3) {
+ SCWrite(pCon, "ERROR: missing parameter to command or bad subcommand",
+ eError);
+ return 0;
+ }
+
+ /*
+ interface
+ */
+ if (strcmp(argv[1], "inter") == 0) {
+ strtolower(argv[2]);
+ if (strstr(argv[2], "driv") != NULL) {
+ printInterface(pSics, pCon, DRIVEID);
+ return 1;
}
-
- pCurrent = self->pCList;
- while(pCurrent)
- {
- if(pCurrent->pData == pData)
- {
- return pCurrent->pName;
+ if (strstr(argv[2], "coun") != NULL) {
+ printInterface(pSics, pCon, COUNTID);
+ return 1;
+ }
+ if (strstr(argv[2], "env") != NULL) {
+ printInterface(pSics, pCon, ENVIRINTERFACE);
+ return 1;
+ }
+ SCWrite(pCon, "ERROR: interface description not recognized", eError);
+ return 0;
+ }
+ /*
+ match
+ */
+ if (strcmp(argv[1], "match") == 0) {
+ printMatch(pSics, pCon, argv[2]);
+ return 1;
+ }
+
+ /* Start Mod by Paul Hathaway May 2004 */
+ /*
+ * type-based dir
+ */
+ if (0 == strcmp(argv[1], "type")) {
+ if (0 == strcmp(argv[2], "*")) {
+ printAllTypes(pSics, pCon, 0);
+ return 1;
+ }
+ strlcpy(pType, argv[2],255);
+ /* Cater for multi-word types eg 'Environment Monitor' */
+ if (argc > 3) {
+ for (i = 3; i < argc; i++) {
+ strlcat(pType, " ",255);
+ strlcat(pType, argv[i],255);
}
- pCurrent = pCurrent->pNext;
}
- return NULL;
- }
-/*---------------------------------------------------------------------------*/
- void *FindCommandData(SicsInterp *pSics, char *name, char *cclass)
- {
- CommandList *pCom;
- pDummy pDum = NULL;
-
- pCom = FindCommand(pSics,name);
- if(!pCom)
- {
- return NULL;
- }
- if(!pCom->pData)
- return NULL;
-
- if (cclass == NULL)
- {
- return pCom->pData;
- }
-
- pDum = (pDummy)pCom->pData;
- if(strcmp(pDum->pDescriptor->name,cclass) == 0)
- {
- return pCom->pData;
- }
- return NULL;
+ printType(pSics, pCon, pType);
+ return 1;
}
+ /* End Mod by Paul Hathaway May 2004 */
+
+ return 1;
+}
+
/*---------------------------------------------------------------------------*/
- pObjectDescriptor FindCommandDescriptor(SicsInterp *pSics, char *name)
- {
- CommandList *pCom;
-
- pCom = FindCommand(pSics,name);
- if(pCom == NULL || pCom->pData == NULL)
- {
- return NULL;
- }
-
- return ((pDummy)pCom->pData)->pDescriptor;
+int InterpWrite(SicsInterp * pSics, char *buffer)
+{
+ Tcl_Interp *pTcl = NULL;
+
+ assert(pSics);
+ pTcl = (Tcl_Interp *) pSics->pTcl;
+ if(Tcl_GetStringResult(pTcl) != buffer){
+ Tcl_SetResult(pTcl, buffer, TCL_VOLATILE);
}
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+Tcl_Interp *InterpGetTcl(SicsInterp * pSics)
+{
+ Tcl_Interp *pTcl = NULL;
+
+ pTcl = (Tcl_Interp *) pSics->pTcl;
+ return pTcl;
+}
+
+/*---------------------------------------------------------------------------*/
+void strtolower(char *pText)
+{
+ assert(pText);
+
+ while (*pText != '\0') {
+ *pText = tolower(*pText);
+ pText++;
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+void argtolower(int argc, char *argv[])
+{
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ strtolower(argv[i]);
+ }
+}
+
/*------------------------------------------------------------------------*/
-void *FindDrivable(SicsInterp *pSics, char *name){
+char *FindAlias(SicsInterp * self, void *pData)
+{
+ CommandList *pCurrent = NULL;
+
+ assert(self);
+
+ if (self->iDeleting) {
+ return NULL;
+ }
+
+ pCurrent = self->pCList;
+ while (pCurrent) {
+ if (pCurrent->pData == pData) {
+ return pCurrent->pName;
+ }
+ pCurrent = pCurrent->pNext;
+ }
+ return NULL;
+}
+
+/*---------------------------------------------------------------------------*/
+void *FindCommandData(SicsInterp * pSics, char *name, char *cclass)
+{
+ CommandList *pCom;
+ pDummy pDum = NULL;
+
+ pCom = FindCommand(pSics, name);
+ if (!pCom) {
+ return NULL;
+ }
+ if (!pCom->pData)
+ return NULL;
+
+ if (cclass == NULL) {
+ return pCom->pData;
+ }
+
+ pDum = (pDummy) pCom->pData;
+ if (strcmp(pDum->pDescriptor->name, cclass) == 0) {
+ return pCom->pData;
+ }
+ return NULL;
+}
+
+/*---------------------------------------------------------------------------*/
+pObjectDescriptor FindCommandDescriptor(SicsInterp * pSics, char *name)
+{
+ CommandList *pCom;
+
+ pCom = FindCommand(pSics, name);
+ if (pCom == NULL || pCom->pData == NULL) {
+ return NULL;
+ }
+
+ return ((pDummy) pCom->pData)->pDescriptor;
+}
+
+/*------------------------------------------------------------------------*/
+void *FindDrivable(SicsInterp * pSics, char *name)
+{
pIDrivable pDriv;
pDummy pDum = NULL;
CommandList *pCom = NULL;
- pCom = FindCommand(pSics,name);
- if(pCom != NULL){
- pDum = (pDummy)pCom->pData;
- if(pDum != NULL){
- return pDum->pDescriptor->GetInterface(pDum,DRIVEID);
+ pCom = FindCommand(pSics, name);
+ if (pCom != NULL) {
+ pDum = (pDummy) pCom->pData;
+ if (pDum != NULL) {
+ return pDum->pDescriptor->GetInterface(pDum, DRIVEID);
}
}
@@ -1029,121 +1013,110 @@ void *FindDrivable(SicsInterp *pSics, char *name){
* linked list module. May extend toallow different output formats
* (eg multi/single column) via switches
*/
-static void printList(SConnection *pCon, int listID)
+static void printList(SConnection * pCon, int listID)
{
- char pBueffel[MAXBUF];
- int retCode;
+ char pBueffel[MAXBUF];
+ int retCode;
- if(0!=LLDnodePtr2First(listID))
- {
- do
- {
- retCode = LLDstringData(listID,NULL);
- if ((MAXBUF-3) > retCode) {
- retCode = LLDstringData(listID,pBueffel);
- strcat(pBueffel,"\r\n");
- SCWrite(pCon,pBueffel,eStatus);
- }
- } while(0!=LLDnodePtr2Next(listID));
- }
+ if (0 != LLDnodePtr2First(listID)) {
+ do {
+ retCode = LLDstringData(listID, NULL);
+ if ((MAXBUF - 3) > retCode) {
+ retCode = LLDstringData(listID, pBueffel);
+ strcat(pBueffel, "\r\n");
+ SCWrite(pCon, pBueffel, eValue);
+ }
+ } while (0 != LLDnodePtr2Next(listID));
+ }
}
/*------------------------------------------------------------------------*/
static void freeList(int listID)
{
- do {
- LLDstringDelete(listID);
- } while(0!=LLDnodePtr2First(listID));
- LLDdelete(listID);
+ do {
+ LLDstringDelete(listID);
+ } while (0 != LLDnodePtr2First(listID));
+ LLDdelete(listID);
}
/*------------------------------------------------------------------------*/
- void RemoveStartupCommands(void)
- {
- CommandList *pCurrent, *pNext;
- pCurrent = pServ->pSics->pCList;
- while(pCurrent)
- {
- pNext = pCurrent->pNext;
- if (pCurrent->startupOnly) {
- RemoveCommand(pServ->pSics, pCurrent->pName);
- }
- pCurrent = pNext;
- }
- }
-/*---------------------------------------------------------------------*/
-char *FindAliases(SicsInterp *pSics, char *name)
+void RemoveStartupCommands(void)
{
- pDynString result = NULL;
- CommandList *pOri = NULL, *pCom = NULL;
- char *pTrans = NULL, *charResult = NULL;
- int first;
-
- pOri = FindCommand(pSics, name);
- if(pOri == NULL)
- {
- return NULL;
- }
- if(pOri->pData == NULL)
- {
- return NULL;
- }
-
- result = CreateDynString(64,64);
- if(result == NULL)
- {
- return NULL;
- }
-
- /* try first to locate Markus style aliases */
- pTrans = TranslateAlias(&pSics->AList,name);
- if(strcmp(pTrans,name) != 0)
- {
- DynStringCopy(result,pTrans);
- charResult = strdup(GetCharArray(result));
- DeleteDynString(result);
- return charResult;
- }
-
- /*
- * locate SicsAlias style aliases by comparing the original
- * data pointer with the data pointers of other commands
- */
- first = 1;
- pCom = pSics->pCList;
- while(pCom != NULL)
- {
- if(pCom != pOri && pCom->pData == pOri->pData)
- {
- if(first)
- {
- DynStringCopy(result,pCom->pName);
- first = 0;
- }
- else
- {
- DynStringConcat(result,",");
- DynStringConcat(result,pCom->pName);
- }
- }
- pCom = pCom->pNext;
- }
- charResult = strdup(GetCharArray(result));
- DeleteDynString(result);
- return charResult;
+ CommandList *pCurrent, *pNext;
+ pCurrent = pServ->pSics->pCList;
+ while (pCurrent) {
+ pNext = pCurrent->pNext;
+ if (pCurrent->startupOnly) {
+ RemoveCommand(pServ->pSics, pCurrent->pName);
+ }
+ pCurrent = pNext;
+ }
}
+
/*---------------------------------------------------------------------*/
-void ForEachCommand(int (*scanFunction)(char *name, pDummy object, void *userData)
- , void *userData)
+char *FindAliases(SicsInterp * pSics, char *name)
+{
+ pDynString result = NULL;
+ CommandList *pOri = NULL, *pCom = NULL;
+ char *pTrans = NULL, *charResult = NULL;
+ int first;
+
+ pOri = FindCommand(pSics, name);
+ if (pOri == NULL) {
+ return NULL;
+ }
+ if (pOri->pData == NULL) {
+ return NULL;
+ }
+
+ result = CreateDynString(64, 64);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ /* try first to locate Markus style aliases */
+ pTrans = TranslateAlias(&pSics->AList, name);
+ if (strcmp(pTrans, name) != 0) {
+ DynStringCopy(result, pTrans);
+ charResult = strdup(GetCharArray(result));
+ DeleteDynString(result);
+ return charResult;
+ }
+
+ /*
+ * locate SicsAlias style aliases by comparing the original
+ * data pointer with the data pointers of other commands
+ */
+ first = 1;
+ pCom = pSics->pCList;
+ while (pCom != NULL) {
+ if (pCom != pOri && pCom->pData == pOri->pData) {
+ if (first) {
+ DynStringCopy(result, pCom->pName);
+ first = 0;
+ } else {
+ DynStringConcat(result, ",");
+ DynStringConcat(result, pCom->pName);
+ }
+ }
+ pCom = pCom->pNext;
+ }
+ charResult = strdup(GetCharArray(result));
+ DeleteDynString(result);
+ return charResult;
+}
+
+/*---------------------------------------------------------------------*/
+void ForEachCommand(int (*scanFunction)
+ (char *name, pDummy object, void *userData)
+ , void *userData)
{
CommandList *pCurrent;
-
-
- for(pCurrent = pServ->pSics->pCList;
- pCurrent != NULL;
- pCurrent = pCurrent->pNext)
- {
- if(scanFunction(pCurrent->pName, pCurrent->pData, userData) == 0) {
+
+
+ for (pCurrent = pServ->pSics->pCList;
+ pCurrent != NULL; pCurrent = pCurrent->pNext) {
+ if (scanFunction(pCurrent->pName, pCurrent->pData, userData) == 0) {
return;
}
}
diff --git a/SCinter.h b/SCinter.h
index 1b24ce24..fd126154 100644
--- a/SCinter.h
+++ b/SCinter.h
@@ -9,149 +9,151 @@
---------------------------------------------------------------------------*/
#ifndef SICSINTERPRETER
#define SICSINTERPRETER
-#include "obdes.h"
-#include "Scommon.h"
+#include "obdes.h"
+#include "Scommon.h"
#include "statistics.h"
#include
/* M.Z. */
#include "definealias.i"
typedef struct __SConnection *pSConnection;
-typedef struct __SINTER *pSicsInterp;
+typedef struct __SINTER *pSicsInterp;
-typedef int (*ObjectFunc)(pSConnection pCon, pSicsInterp pInter, void
- *pData, int argc, char *argv[]);
+typedef int (*ObjectFunc) (pSConnection pCon, pSicsInterp pInter, void
+ *pData, int argc, char *argv[]);
-typedef void (*KillFunc)(void *pData);
+typedef int (*ObjectFuncSelfParse) (pSConnection pCon, pSicsInterp pInter, void
+ *pData, char *command);
+
+typedef void (*KillFunc) (void *pData);
typedef struct __Clist {
- char *pName;
- ObjectFunc OFunc;
- KillFunc KFunc;
- void *pData;
- struct __Clist *pNext;
- struct __Clist *pPrevious;
- int startupOnly;
- Statistics *stat;
- } CommandList;
+ char *pName;
+ ObjectFunc OFunc;
+ KillFunc KFunc;
+ void *pData;
+ struct __Clist *pNext;
+ struct __Clist *pPrevious;
+ int startupOnly;
+ Statistics *stat;
+} CommandList;
+
+typedef struct __SINTER {
+ CommandList *pCList;
+ OutCode eOut;
+ void *pTcl;
+ int iDeleting;
+ AliasList AList; /* M.Z. */
+} SicsInterp;
-typedef struct __SINTER
- {
- CommandList *pCList;
- OutCode eOut;
- void *pTcl;
- int iDeleting;
- AliasList AList; /* M.Z. */
- }SicsInterp;
-
/*-------------------------------------------------------------------------*/
- SicsInterp *InitInterp(void);
+SicsInterp *InitInterp(void);
/* makes a new interpreter. Returns him on success, else NULL
- */
-/*------------------------------------------------------------------------*/
- int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
- KillFunc pKFunc, void *pData);
+ */
+/*------------------------------------------------------------------------*/
+int AddCommand(SicsInterp * pInterp, char *pName, ObjectFunc pFunc,
+ KillFunc pKFunc, void *pData);
/* adds a new command, Returns True or False, depending on success
Parameters:
- pInterp : the interpreter to add the command to.
- pName : the commands name
- pFunc : the object function to call when this command is
- invoked. Definition of type: see above
- pKFunc : function to call in order to delete command data.
- type definition: above
- pData : pointer to the command's own datastructure. Will be
- passed as pData with each call to Ofunc.
- */
-/*-------------------------------------------------------------------------*/
- int RemoveCommand(SicsInterp *pInterp, char *pName);
+ pInterp : the interpreter to add the command to.
+ pName : the commands name
+ pFunc : the object function to call when this command is
+ invoked. Definition of type: see above
+ pKFunc : function to call in order to delete command data.
+ type definition: above
+ pData : pointer to the command's own datastructure. Will be
+ passed as pData with each call to Ofunc.
+ */
+/*-------------------------------------------------------------------------*/
+int RemoveCommand(SicsInterp * pInterp, char *pName);
/* kills the command name from the interpreter pInterp
- */
-/*-------------------------------------------------------------------------*/
- int AddCommandWithFlag(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
- KillFunc pKFunc, void *pData, int startupFlag);
- int AddIniCmd(char *pName, ObjectFunc pFunc); /* command will be deleted after startup */
- int AddCmd(char *pName, ObjectFunc pFunc); /* syntactic sugar for AddCommand without data */
- void RemoveStartupCommands(void); /* called after startup to delete startup commands */
-/*-------------------------------------------------------------------------*/
- int InterpExecute(SicsInterp *self,pSConnection pCon,char *pCommand);
-
+ */
+/*-------------------------------------------------------------------------*/
+int AddCommandWithFlag(SicsInterp * pInterp, char *pName, ObjectFunc pFunc,
+ KillFunc pKFunc, void *pData, int startupFlag);
+int AddIniCmd(char *pName, ObjectFunc pFunc); /* command will be deleted after startup */
+int AddCmd(char *pName, ObjectFunc pFunc); /* syntactic sugar for AddCommand without data */
+void RemoveStartupCommands(void); /* called after startup to delete startup commands */
+/*-------------------------------------------------------------------------*/
+int InterpExecute(SicsInterp * self, pSConnection pCon, char *pCommand);
+
/*
- executes a command in the interpreter self. Essentially converts
- pCommand in an argc, argv[] pair, sets various status things and
- invokes the object function. Takes care of status and error reporting
- afterwards.
-
- Parameters:
- self : interpreter to invoke command in.
- The connection pCon will be used for I/O and status reporting.
- The command to invoke is the string pCommand.
- Returns -1 if the command can not be found.
- If the command is found, 1 is returned on success, 0 on failure in
- the command.
-----------------------------------------------------------------------------*/
- CommandList *FindCommand(SicsInterp *pInterp, char *name);
+ executes a command in the interpreter self. Essentially converts
+ pCommand in an argc, argv[] pair, sets various status things and
+ invokes the object function. Takes care of status and error reporting
+ afterwards.
+
+ Parameters:
+ self : interpreter to invoke command in.
+ The connection pCon will be used for I/O and status reporting.
+ The command to invoke is the string pCommand.
+ Returns -1 if the command can not be found.
+ If the command is found, 1 is returned on success, 0 on failure in
+ the command.
+ ---------------------------------------------------------------------------- */
+CommandList *FindCommand(SicsInterp * pInterp, char *name);
/*
Searches the Interpreters pInterp command list for a command
with name. Returns ist datastructure if found, NULL else
- */
+ */
/*-------------------------------------------------------------------------*/
- int WriteSicsStatus(SicsInterp *pSics,char *file, int iMot);
+int WriteSicsStatus(SicsInterp * pSics, char *file, int iMot);
/*
- SICS needs a way to save the status of each object into a file.
- This is done by invoking for each object the object descriptor
- function SaveStatus. This function does just that.
-
- Parameters:
- pSics : the interpreter to use.
- file : the file to write the information to.
- iMot : flag if motor position shall be saved or not
- Returns: 1 on success, 0 on failure.
----------------------------------------------------------------------------*/
- int InterpWrite(SicsInterp *pSics, char *buffer);
+ SICS needs a way to save the status of each object into a file.
+ This is done by invoking for each object the object descriptor
+ function SaveStatus. This function does just that.
+
+ Parameters:
+ pSics : the interpreter to use.
+ file : the file to write the information to.
+ iMot : flag if motor position shall be saved or not
+ Returns: 1 on success, 0 on failure.
+ --------------------------------------------------------------------------- */
+int InterpWrite(SicsInterp * pSics, char *buffer);
/*
writes result to Tcl, used for Macro mechanism.
This is an internal function and should not be used.
-----------------------------------------------------------------------------*/
-
- void DeleteInterp(SicsInterp *self);
+ ---------------------------------------------------------------------------- */
+
+void DeleteInterp(SicsInterp * self);
/*
deletes the interpreter self aand clears all asoociated datastructures.
self will no longer be valid after this.
---------------------------------------------------------------------------- */
- void strtolower(char *pText);
+ --------------------------------------------------------------------------- */
+void strtolower(char *pText);
/*
- strtolower converts a string to lowercase
---------------------------------------------------------------------------- */
- void argtolower(int argc, char *argv[]);
+ strtolower converts a string to lowercase
+ --------------------------------------------------------------------------- */
+void argtolower(int argc, char *argv[]);
/*
- converts an argc, argv[] pair to lowercase
- */
+ converts an argc, argv[] pair to lowercase
+ */
/*--------------------------------------------------------------------------
FindAlias tries to find an alias to the datastructure given as second
parameter. Returns the command name on success, else NULL. Be warned, this
is very special
*/
-
- char *FindAlias(SicsInterp *pSics, void *pData);
+
+char *FindAlias(SicsInterp * pSics, void *pData);
/*----------------------------------------------------------------------
FindAliases locates alle aliases related to a gibe name. The result
is returned as a komma separated list.
*/
- char *FindAliases(SicsInterp *pSics, char *name);
+char *FindAliases(SicsInterp * pSics, char *name);
/*-------------------------------------------------------------------------
FindCommandData finds a command with the name given. It tests the name in the
ObjectDescriptor to be of name class. If all this succeeds a pointer
to the commands data structure is retuned. Else NULL.
Do not test the Object Descriptor name when comclass == NULL.
*/
- void *FindCommandData(SicsInterp *pSics, char *name, char *comclass);
+void *FindCommandData(SicsInterp * pSics, char *name, char *comclass);
/*-------------------------------------------------------------------------
FindCommandDescriptor finds the descriptor of a command with the name given.
*/
- pObjectDescriptor FindCommandDescriptor(SicsInterp *pSics, char *name);
+pObjectDescriptor FindCommandDescriptor(SicsInterp * pSics, char *name);
/*------------------------------------------------------------------------
FindDrivable tries to find Drivable object by the name given. Returns a
@@ -159,18 +161,19 @@ typedef struct __SINTER
case of failure. In order to save me fixing header files the pointer must
be cast to the drivable interface pointer.
*/
-void *FindDrivable(SicsInterp *pics, char *name);
+void *FindDrivable(SicsInterp * pics, char *name);
/*------------------------------------------------------------------------
Go through the command list and call scanFunction for every command
until the return value is 0.
*/
-void ForEachCommand(int (*scanFunction)(char *name, pDummy object, void *userData)
- , void *userData);
+void
+ForEachCommand(int (*scanFunction)
+ (char *name, pDummy object, void *userData)
+ , void *userData);
/*-----------------------------------------------------------------------
Get a copy of the Tcl interpreter
- ------------------------------------------------------------------------*/
-Tcl_Interp *InterpGetTcl(SicsInterp *pSics);
+ ------------------------------------------------------------------------*/
+Tcl_Interp *InterpGetTcl(SicsInterp * pSics);
#endif
-
diff --git a/SICSmain.c b/SICSmain.c
index e6df767b..f6187cf7 100644
--- a/SICSmain.c
+++ b/SICSmain.c
@@ -20,90 +20,73 @@
#include
#include
#include
-#include
#include "nserver.h"
#include "servlog.h"
/***************************** Necessary Globals ****************************/
- IPair *pSICSOptions = NULL;
- pServer pServ = NULL;
-
+IPair *pSICSOptions = NULL;
+pServer pServ = NULL;
+
/* ========================= Less dreadful file statics =================== */
#define DEFAULTINIFILE "servo.tcl"
-int usage(const char* name) {
- fprintf(stderr, "usage: %s [-d] [-nolog] \n", name);
- return 1;
-}
/*---------------------------------------------------------------------------
The Servers Main program. May take one argument: the name of an
initialisation file
*/
-
- int main(int argc, char *argv[])
- {
- int iRet;
- int debug = 0;
- char *file=NULL;
- int i, firstArg=1;
- if (argc < 2)
- return usage(argv[0]);
+int main(int argc, char *argv[])
+{
+ int iRet;
+ char *file = NULL;
+ int i;
- /* initialise, will die on you if problems */
- if (strcasecmp(argv[1], "-d") == 0) {
- debug = 1;
- firstArg=2;
- }
- for (i=firstArg; ipSics;
+ iRet = InitServer(file, &pServ);
+ if (!iRet) {
+ printf("Unrecoverable error on server startup, exiting.........\n");
+ exit(1);
}
+
+
+ RunServer(pServ);
+
+ StopServer(pServ);
+ pServ = NULL;
+ exit(0);
+}
+
/*--------------------------------------------------------------------------*/
- pExeList GetExecutor(void)
- {
- return pServ->pExecutor;
- }
+SicsInterp *GetInterpreter(void)
+{
+ return pServ->pSics;
+}
+
+/*--------------------------------------------------------------------------*/
+pExeList GetExecutor(void)
+{
+ return pServ->pExecutor;
+}
+
/*------------------------------------------------------------------------*/
- void StopExit(void)
- {
- if(pServ)
- {
- StopServer(pServ);
- }
- }
+void StopExit(void)
+{
+ if (pServ) {
+ StopServer(pServ);
+ }
+}
+
/*-------------------------------------------------------------------------*/
- pTaskMan GetTasker(void)
- {
- return pServ->pTasker;
- }
+pTaskMan GetTasker(void)
+{
+ return pServ->pTasker;
+}
diff --git a/Scommon.h b/Scommon.h
index bf7da342..4d356e7e 100644
--- a/Scommon.h
+++ b/Scommon.h
@@ -40,21 +40,23 @@
/* this enum defines the output types in SICS */
typedef enum {
- eInternal,
- eCommand,
- eHWError,
- eInError,
- eStatus,
- eValue,
- eStart,
- eFinish,
- eEvent,
- eWarning,
- eError,
- eHdbValue,
- eHdbEvent
- } OutCode;
-
+ eInternal, /* internal */
+ eCommand, /* reserved, not used */
+ eHWError, /* reserved, used only for SICSLog */
+ eInError, /* reserved, used as a mark in the handling of output codes */
+ eStatus, /* reserved, deprecated */
+ eValue, /* value reponse: copied into Tcl */
+ eStart, /* start message */
+ eFinish, /* finish message */
+ eEvent, /* some callback messages */
+ eWarning, /* warnings */
+ eError, /* error: copied into Tcl */
+ eHdbValue, /* hipadaba value chnage */
+ eHdbEvent, /* Hipadaba event */
+ eLog, /* log message: is always written to client */
+ eLogError /* error message to log: is always written to client */
+} OutCode;
+
#include "interrupt.h"
/* define some user rights codes */
@@ -82,6 +84,5 @@ typedef enum {
*/
#include "ifile.h"
extern IPair *pSICSOptions;
-
-#endif
+#endif
diff --git a/access.c b/access.c
index 110947e9..2b77d4b7 100644
--- a/access.c
+++ b/access.c
@@ -7,26 +7,31 @@
#include
#include
- static char *aCode[] = {
- "internal",
- "mugger",
- "user",
- "spy",
- NULL };
- static int iCodes = 4;
+static char *aCode[] = {
+ "internal",
+ "mugger",
+ "user",
+ "spy",
+ NULL
+};
+static int iCodes = 4;
/*--------------------------------------------------------------------------*/
-int decodeSICSPriv(char *privText){
- int code = 0;
-
- strtolower(privText);
- while(aCode[code] != NULL){
- if(strcmp(aCode[code], privText) == 0){
- return code;
- }
- code++;
- }
- if(code >= iCodes){
- return -1;
+int decodeSICSPriv(char *privText)
+{
+ int code = 0;
+
+ strtolower(privText);
+ if(strcmp(privText,"manager") == 0){
+ return 1;
+ }
+ while (aCode[code] != NULL) {
+ if (strcmp(aCode[code], privText) == 0) {
+ return code;
}
+ code++;
+ }
+ if (code >= iCodes) {
return -1;
+ }
+ return -1;
}
diff --git a/alias.c b/alias.c
index 45155e15..188312a4 100644
--- a/alias.c
+++ b/alias.c
@@ -45,72 +45,69 @@
/*
Usage: SicsAlias object newname
-*/
+*/
- int SicsAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- CommandList *pCom = NULL;
- char pBueffel[256];
- int iRet;
-
- if(!SCMatchRights(pCon,usMugger))
- {
- SCWrite(pCon,"ERROR: aliasing only allowed to Managers",
- eError);
- return 0;
- }
-
- if(argc < 3)
- {
- SCWrite(pCon,"ERROR: insufficient number of arguments to SicsAlias",
- eError);
- return 0;
- }
+int SicsAlias(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ CommandList *pCom = NULL;
+ char pBueffel[256];
+ int iRet;
+
+ if (!SCMatchRights(pCon, usMugger)) {
+ SCWrite(pCon, "ERROR: aliasing only allowed to Managers", eError);
+ return 0;
+ }
+
+ if (argc < 3) {
+ SCWrite(pCon, "ERROR: insufficient number of arguments to SicsAlias",
+ eError);
+ return 0;
+ }
+
+ argtolower(argc, argv);
+ /* first parameter should be an registered SICS object */
+ pCom = FindCommand(pSics, argv[1]);
+ if (!pCom) {
+ snprintf(pBueffel,255, "ERROR: cannot find %s, no alias created", argv[1]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+ /* alright: create the alias */
+ iRet = AddCommand(pSics, argv[2], pCom->OFunc, NULL, pCom->pData);
+ if (!iRet) {
+ snprintf(pBueffel,255, "ERROR: duplicate command %s not created", argv[2]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ return 1;
+}
- argtolower(argc,argv);
- /* first parameter should be an registered SICS object */
- pCom = FindCommand(pSics,argv[1]);
- if(!pCom)
- {
- sprintf(pBueffel,"ERROR: cannot find %s, no alias created",argv[1]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
- /* alright: create the alias */
- iRet = AddCommand(pSics,argv[2],pCom->OFunc,NULL,pCom->pData);
- if(!iRet)
- {
- sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- return 1;
- }
/*--------------------------------------------------------------------
Make Alias: a command which installs a general alias into SICS.
*/
- typedef struct {
- pObjectDescriptor pDes;
- char *pCommand;
- }Alias, *pAlias;
+typedef struct {
+ pObjectDescriptor pDes;
+ char *pCommand;
+} Alias, *pAlias;
/*----------------------------------------------------------------------*/
- static void FreeAlias(void *pData)
- {
- pAlias self = (pAlias)pData;
- if(!self)
- return;
+static void FreeAlias(void *pData)
+{
+ pAlias self = (pAlias) pData;
+ if (!self)
+ return;
- if(self->pDes)
- DeleteDescriptor(self->pDes);
+ if (self->pDes)
+ DeleteDescriptor(self->pDes);
- if(self->pCommand)
- free(self->pCommand);
+ if (self->pCommand)
+ free(self->pCommand);
+
+ free(self);
+}
- free(self);
- }
/*----------------------------------------------------------------------
In order to make alias most general alias tries to find the interfaces
defined by the object corresponding to the first word in the command.
@@ -118,116 +115,113 @@
will be called refers to the alias and not the proper thing: core dump!
Therefore disabled!
*/
- static void *AliasInterface(void *pData, int iID)
- {
- CommandList *pCom = NULL;
- pDummy pDum = NULL;
- char *pPtr = NULL;
- pAlias self = (pAlias)pData;
+static void *AliasInterface(void *pData, int iID)
+{
+ CommandList *pCom = NULL;
+ pDummy pDum = NULL;
+ char *pPtr = NULL;
+ pAlias self = (pAlias) pData;
- assert(self);
- pPtr = strtok(self->pCommand," \t\n");
- pCom = FindCommand(pServ->pSics,pPtr);
- if(!pCom)
- return NULL;
+ assert(self);
+ pPtr = strtok(self->pCommand, " \t\n");
+ pCom = FindCommand(pServ->pSics, pPtr);
+ if (!pCom)
+ return NULL;
- pDum = (pDummy)pCom->pData;
- if(!pDum)
- return NULL;
+ pDum = (pDummy) pCom->pData;
+ if (!pDum)
+ return NULL;
- return pDum->pDescriptor->GetInterface(pDum,iID);
- }
-/*-----------------------------------------------------------------------*/
- static int AliasAction(SConnection *pCon, SicsInterp *pSics,
- void *pData, int argc, char *argv[])
- {
- pAlias self = NULL;
- int status;
- char pLine[512];
- char *pPtr;
- Tcl_DString command;
-
- self = (pAlias)pData;
- assert(self);
-
- /*
- build command by appending the alias command and any possible
- arguments given.
- */
- Tcl_DStringInit(&command);
- Tcl_DStringAppend(&command, self->pCommand,-1);
- Tcl_DStringAppend(&command," ",-1);
- Arg2Text(argc-1,&argv[1],pLine,511);
- Tcl_DStringAppend(&command,pLine,-1);
-
- /* execute the command on the current connection */
- status = SCInvoke(pCon,pSics,Tcl_DStringValue(&command));
-
- /* finish */
- Tcl_DStringFree(&command);
- return status;
- }
-/*-----------------------------------------------------------------------*/
- int MakeAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- char pBueffel[512];
- int iRet;
- pAlias pNew = NULL;
-
- if(argc < 3)
- {
- SCWrite(pCon,"ERROR: insufficient number of arguments to alias",
- eError);
- return 0;
- }
-
- Arg2Text(argc-2,&argv[2],pBueffel,511);
-
- /* create data structure */
- pNew = (pAlias)malloc(sizeof(Alias));
- if(!pNew)
- {
- SCWrite(pCon,"ERROR: out of memory while creating alias",eError);
- return 0;
- }
- pNew->pDes = CreateDescriptor("Alias");
- pNew->pCommand = strdup(pBueffel);
- if( !pNew->pDes || !pNew->pCommand)
- {
- SCWrite(pCon,"ERROR: out of memory while creating alias",eError);
- return 0;
- }
-
- iRet = AddCommand(pSics,
- argv[1],
- AliasAction,
- FreeAlias,
- pNew);
- if(!iRet)
- {
- FreeAlias(pNew);
- SCWrite(pCon,"ERROR: duplicate object name NOT created",eError);
- return 0;
- }
- return 1;
- }
-/*-------------------------------------------------------------------------------*/
-int LocateAliasAction(SConnection *pCon, SicsInterp *pSics,
- void *pData, int argc, char *argv[]){
- char *aliases = NULL;
-
- if(argc < 2){
- SCWrite(pCon,"ERROR: missing argument aliasname for locating aliases",eError);
- return 0;
- }
-
- strtolower(argv[1]);
- aliases = FindAliases(pSics,argv[1]);
- if(aliases == NULL){
- SCWrite(pCon,"NONE", eValue);
- } else {
- SCPrintf(pCon,eValue,"%s = %s",argv[1], aliases);
- }
- return 1;
+ return pDum->pDescriptor->GetInterface(pDum, iID);
+}
+
+/*-----------------------------------------------------------------------*/
+static int AliasAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[])
+{
+ pAlias self = NULL;
+ int status;
+ char pLine[512];
+ char *pPtr;
+ Tcl_DString command;
+
+ self = (pAlias) pData;
+ assert(self);
+
+ /*
+ build command by appending the alias command and any possible
+ arguments given.
+ */
+ Tcl_DStringInit(&command);
+ Tcl_DStringAppend(&command, self->pCommand, -1);
+ Tcl_DStringAppend(&command, " ", -1);
+ Arg2Text(argc - 1, &argv[1], pLine, 511);
+ Tcl_DStringAppend(&command, pLine, -1);
+
+ /* execute the command on the current connection */
+ status = SCInvoke(pCon, pSics, Tcl_DStringValue(&command));
+
+ /* finish */
+ Tcl_DStringFree(&command);
+ return status;
+}
+
+/*-----------------------------------------------------------------------*/
+int MakeAlias(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ char pBueffel[512];
+ int iRet;
+ pAlias pNew = NULL;
+
+ if (argc < 3) {
+ SCWrite(pCon, "ERROR: insufficient number of arguments to alias",
+ eError);
+ return 0;
+ }
+
+ Arg2Text(argc - 2, &argv[2], pBueffel, 511);
+
+ /* create data structure */
+ pNew = (pAlias) malloc(sizeof(Alias));
+ if (!pNew) {
+ SCWrite(pCon, "ERROR: out of memory while creating alias", eError);
+ return 0;
+ }
+ pNew->pDes = CreateDescriptor("Alias");
+ pNew->pCommand = strdup(pBueffel);
+ if (!pNew->pDes || !pNew->pCommand) {
+ SCWrite(pCon, "ERROR: out of memory while creating alias", eError);
+ return 0;
+ }
+
+ iRet = AddCommand(pSics, argv[1], AliasAction, FreeAlias, pNew);
+ if (!iRet) {
+ FreeAlias(pNew);
+ SCWrite(pCon, "ERROR: duplicate object name NOT created", eError);
+ return 0;
+ }
+ return 1;
+}
+
+/*-------------------------------------------------------------------------------*/
+int LocateAliasAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[])
+{
+ char *aliases = NULL;
+
+ if (argc < 2) {
+ SCWrite(pCon, "ERROR: missing argument aliasname for locating aliases",
+ eError);
+ return 0;
+ }
+
+ strtolower(argv[1]);
+ aliases = FindAliases(pSics, argv[1]);
+ if (aliases == NULL) {
+ SCWrite(pCon, "NONE", eValue);
+ } else {
+ SCPrintf(pCon, eValue, "%s = %s", argv[1], aliases);
+ }
+ return 1;
}
diff --git a/alias.h b/alias.h
index 4a70827c..d9d4ac55 100644
--- a/alias.h
+++ b/alias.h
@@ -12,11 +12,10 @@
#ifndef SICSALIAS
#define SICSALIAS
- int SicsAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
- int MakeAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
- int LocateAliasAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int SicsAlias(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+int MakeAlias(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+int LocateAliasAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
#endif
-
diff --git a/anticollider.c b/anticollider.c
index 6c58dbee..5e144766 100644
--- a/anticollider.c
+++ b/anticollider.c
@@ -27,14 +27,16 @@ static pAntiCollider myCollider = NULL;
the replacement function for the motor's drivable interface SetValue
function. It enters the new target into the motor list.
---------------------------------------------------------------------*/
-static long ReplacementSetValue(void *pData, SConnection *pCon, float fTarget){
+static long ReplacementSetValue(void *pData, SConnection * pCon,
+ float fTarget)
+{
pMotReg pMot = NULL;
-
+
assert(myCollider != NULL);
- pMot = FindMotFromDataStructure(myCollider->motorList,pData);
- if(pMot != NULL){
- SetRegMotTarget(pMot,fTarget);
+ pMot = FindMotFromDataStructure(myCollider->motorList, pData);
+ if (pMot != NULL) {
+ SetRegMotTarget(pMot, fTarget);
myCollider->isDirty = 1;
} else {
return 0;
@@ -42,33 +44,35 @@ static long ReplacementSetValue(void *pData, SConnection *pCon, float fTarget){
return 1;
}
+
/*---------------------------------------------------------------------
The replacement CheckStatus function for controlled motors.
Start AntiCollider if not running and finish. Rest of work done by
AntiCollider.
-----------------------------------------------------------------------*/
-static int ReplacementCheckStatus(void *pData, SConnection *pCon){
+static int ReplacementCheckStatus(void *pData, SConnection * pCon)
+{
pMotReg pMot = NULL;
-
+
assert(myCollider != NULL);
- if(myCollider->isDirty == 1){
+ if (myCollider->isDirty == 1) {
myCollider->isDirty = 0;
StartDevice(pServ->pExecutor,
- "anticollider",
- myCollider->pDes,
- myCollider,
- pCon,
- 77.77);
+ "anticollider", myCollider->pDes, myCollider,
+ pCon,pCon->runLevel, 77.77);
return HWIdle;
} else {
return HWIdle;
}
}
+
/*------------------------------------------------------------------------
The collider SetValue function
-------------------------------------------------------------------------*/
-static long ColliderSetValue(void *pData, SConnection *pCon, float fTarget){
+static long ColliderSetValue(void *pData, SConnection * pCon,
+ float fTarget)
+{
pAntiCollider self = (pAntiCollider) pData;
int iRet;
pMotReg pMot = NULL;
@@ -78,79 +82,80 @@ static long ColliderSetValue(void *pData, SConnection *pCon, float fTarget){
Tcl_DString command;
/*
- build command list
- */
- if(self->colliderScript == NULL){
- SCWrite(pCon,"ERROR: no collider script defined",eError);
+ build command list
+ */
+ if (self->colliderScript == NULL) {
+ SCWrite(pCon, "ERROR: no collider script defined", eError);
return 0;
}
Tcl_DStringInit(&command);
- Tcl_DStringAppend(&command,self->colliderScript,-1);
+ Tcl_DStringAppend(&command, self->colliderScript, -1);
iRet = LLDnodePtr2First(self->motorList);
- while(iRet != 0){
- LLDnodeDataTo(self->motorList,&pMot);
- if(pMot != NULL){
- if(pMot->iActive){
- CreateTargetString(pMot,pBueffel);
- Tcl_DStringAppend(&command, pBueffel,-1);
- pMot->iActive = 0;
+ while (iRet != 0) {
+ LLDnodeDataTo(self->motorList, &pMot);
+ if (pMot != NULL) {
+ if (pMot->iActive) {
+ CreateTargetString(pMot, pBueffel);
+ Tcl_DStringAppend(&command, pBueffel, -1);
+ pMot->iActive = 0;
}
}
iRet = LLDnodePtr2Next(self->motorList);
}
-
- /*
- kill old collider sequence
- */
- LLDdelete(self->sequenceList);
- self->sequenceList = LLDcreate(sizeof(Sequence));
- self->level = -1; /* otherwise level 0 will not be started */
/*
- evaluate colliderScript
- */
- iRet = Tcl_Eval(pServ->pSics->pTcl,Tcl_DStringValue(&command));
- if(iRet != TCL_OK){
- SCWrite(pCon,"ERROR: Movement not possible or bad collider script",eError);
- SCWrite(pCon,Tcl_DStringValue(&command),eError);
+ kill old collider sequence
+ */
+ LLDdelete(self->sequenceList);
+ self->sequenceList = LLDcreate(sizeof(Sequence));
+ self->level = -1; /* otherwise level 0 will not be started */
+
+ /*
+ evaluate colliderScript
+ */
+ iRet = Tcl_Eval(pServ->pSics->pTcl, Tcl_DStringValue(&command));
+ if (iRet != TCL_OK) {
+ SCWrite(pCon, "ERROR: Movement not possible or bad collider script",
+ eError);
+ SCPrintf(pCon,eError, "%s returned %s", Tcl_DStringValue(&command), Tcl_GetStringResult(pServ->pSics->pTcl));
/*
- SCWrite(pCon,pServ->pSics->pTcl->result,eError);
- */
- SCSetInterrupt(pCon,eAbortOperation);
+ SCWrite(pCon,pServ->pSics->pTcl->result,eError);
+ */
+ SCSetInterrupt(pCon, eAbortOperation);
return 0;
}
/*
- we are set
- */
+ we are set
+ */
Tcl_DStringFree(&command);
return 1;
}
+
/*----------------------------------------------------------------------
The Collider CheckStatus function
-----------------------------------------------------------------------*/
-static int ColliderCheckStatus(void *pData, SConnection *pCon){
+static int ColliderCheckStatus(void *pData, SConnection * pCon)
+{
int count = 0;
pAntiCollider self = (pAntiCollider) pData;
assert(self);
- if(SCGetInterrupt(pCon) != eContinue){
+ if (SCGetInterrupt(pCon) != eContinue) {
return HWIdle;
}
- count = CheckAllMotors(self->motorList,pCon);
- if(count == 0){
+ count = CheckAllMotors(self->motorList, pCon);
+ if (count == 0) {
self->level++;
count = StartLevel(self->level,
- self->sequenceList,
- self->motorList,
- pCon);
- if(count == 0){
+ self->sequenceList, self->motorList, pCon);
+ if (count == 0) {
/*
- no more levels. All done
- */
+ no more levels. All done
+ */
return HWIdle;
} else {
return HWBusy;
@@ -159,27 +164,35 @@ static int ColliderCheckStatus(void *pData, SConnection *pCon){
return HWBusy;
}
}
+
/*----------------------------------------------------------------------
Most of these are dummies........
-----------------------------------------------------------------------*/
-static int ColliderHalt(void *pData){
+static int ColliderHalt(void *pData)
+{
pAntiCollider self = (pAntiCollider) pData;
StopAllMotors(self->motorList);
self->level = 999999999;
return 1;
}
+
/*---------------------------------------------------------------------*/
-static int ColliderLimits(void *self, float fVal, char *error,
- int iErren){
+static int ColliderLimits(void *self, float fVal, char *error, int iErren)
+{
return 1;
}
+
/*--------------------------------------------------------------------*/
-static float ColliderGetValue(void *self, SConnection *pCon){
+static float ColliderGetValue(void *self, SConnection * pCon)
+{
return 77.77;
}
+
/*--------------------------------------------------------------------*/
-int StartLevel(int level, int sequenceList, int motorList, SConnection *pCon){
+int StartLevel(int level, int sequenceList, int motorList,
+ SConnection * pCon)
+{
Sequence seq;
pMotReg pMot = NULL;
int iRet, status;
@@ -187,99 +200,109 @@ int StartLevel(int level, int sequenceList, int motorList, SConnection *pCon){
char pBueffel[132];
iRet = LLDnodePtr2First(sequenceList);
- while(iRet != 0){
- LLDnodeDataTo(sequenceList,&seq);
- if(seq.level == level){
- pMot = FindMotEntry(motorList,seq.pMotor);
- if(pMot){
- status = StartRegMot(pMot,pCon,seq.target);
+ while (iRet != 0) {
+ LLDnodeDataTo(sequenceList, &seq);
+ if (seq.level == level) {
+ pMot = FindMotEntry(motorList, seq.pMotor);
+ if (pMot) {
+ status = StartRegMot(pMot, pCon, seq.target);
/*
* I have to ignore the problem here: if I do not increment the count
* all the other levels will not be drive and the anticollider
* gets into a mess
*/
- count++;
+ count++;
} else {
- sprintf(pBueffel,"ERROR: motor %s, requested from anticollider script",
- seq.pMotor);
- SCWrite(pCon,pBueffel,eError);
- SCWrite(pCon,"ERROR: motor NOT found, fix script!",eError);
+ snprintf(pBueffel,131,
+ "ERROR: motor %s, requested from anticollider script",
+ seq.pMotor);
+ SCWrite(pCon, pBueffel, eError);
+ SCWrite(pCon, "ERROR: motor NOT found, fix script!", eError);
}
}
iRet = LLDnodePtr2Next(sequenceList);
}
return count;
}
+
/*--------------------------------------------------------------------*/
-static void ListSequence(int sequenceList, SConnection *pCon){
+static void ListSequence(int sequenceList, SConnection * pCon)
+{
Sequence seq;
int iRet;
char pBueffel[132];
- SCWrite(pCon,"level motor target",eValue);
+ SCWrite(pCon, "level motor target", eValue);
iRet = LLDnodePtr2First(sequenceList);
- while(iRet != 0){
- LLDnodeDataTo(sequenceList,&seq);
- sprintf(pBueffel,"%d %s %f",seq.level,seq.pMotor,seq.target);
- SCWrite(pCon,pBueffel,eValue);
+ while (iRet != 0) {
+ LLDnodeDataTo(sequenceList, &seq);
+ snprintf(pBueffel,131, "%d %s %f", seq.level, seq.pMotor, seq.target);
+ SCWrite(pCon, pBueffel, eValue);
iRet = LLDnodePtr2Next(sequenceList);
}
}
+
/*-------------------------------------------------------------------------*/
-static void *ColliderGetInterface(void *pData, int iID) {
+static void *ColliderGetInterface(void *pData, int iID)
+{
pAntiCollider self = NULL;
-
- self = (pAntiCollider)pData;
+
+ self = (pAntiCollider) pData;
assert(self);
- if(iID == DRIVEID){
- return self->pDriv;
+ if (iID == DRIVEID) {
+ return self->pDriv;
}
- return NULL;
-}
+ return NULL;
+}
+
/*----------------------------------------------------------------------*/
-void KillCollider(void *pData){
- pAntiCollider self = (pAntiCollider)pData;
-
- if(self == NULL){
+void KillCollider(void *pData)
+{
+ pAntiCollider self = (pAntiCollider) pData;
+
+ if (self == NULL) {
return;
}
- if(self->pDes != NULL){
+ if (self->pDes != NULL) {
DeleteDescriptor(self->pDes);
}
- if(self->pDriv != NULL){
+ if (self->pDriv != NULL) {
free(self->pDriv);
}
- if(self->colliderScript != NULL){
+ if (self->colliderScript != NULL) {
free(self->colliderScript);
}
- if(self->motorList > 0){
+ if (self->motorList > 0) {
KillMotList(self->motorList);
}
- if(self->sequenceList > 0){
+ if (self->sequenceList > 0) {
LLDdelete(self->sequenceList);
}
free(self);
myCollider = NULL;
}
-/*-----------------------------------------------------------------------*/
-int AntiColliderFactory(SConnection *pCon, SicsInterp *pSics,
- void *pData,
- int argc, char *argv[]){
- myCollider = (pAntiCollider)malloc(sizeof(AntiCollider));
- if(myCollider == NULL){
- SCWrite(pCon,"ERROR: out of memory when generating AntiCollider",eError);
+/*-----------------------------------------------------------------------*/
+int AntiColliderFactory(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[])
+{
+
+ myCollider = (pAntiCollider) malloc(sizeof(AntiCollider));
+ if (myCollider == NULL) {
+ SCWrite(pCon, "ERROR: out of memory when generating AntiCollider",
+ eError);
return 0;
}
- memset(myCollider,0,sizeof(AntiCollider));
+ memset(myCollider, 0, sizeof(AntiCollider));
myCollider->pDes = CreateDescriptor("AntiCollider");
myCollider->pDriv = CreateDrivableInterface();
- if(!myCollider->pDes || !myCollider->pDriv){
+ if (!myCollider->pDes || !myCollider->pDriv) {
KillCollider(myCollider);
- SCWrite(pCon,"ERROR: out of memory when generating AntiCollider",eError);
+ SCWrite(pCon, "ERROR: out of memory when generating AntiCollider",
+ eError);
return 0;
}
@@ -293,91 +316,90 @@ int AntiColliderFactory(SConnection *pCon, SicsInterp *pSics,
myCollider->motorList = LLDcreate(sizeof(void *));
myCollider->sequenceList = LLDcreate(sizeof(Sequence));
- AddCommand(pSics,"anticollision",AntiColliderAction,
- KillCollider,
- myCollider);
+ AddCommand(pSics, "anticollision", AntiColliderAction,
+ KillCollider, myCollider);
return 1;
}
+
/*------------------------------------------------------------------------*/
-int AntiColliderAction(SConnection *pCon, SicsInterp *pSics,
- void *pData,
- int argc, char *argv[]){
- pAntiCollider self = (pAntiCollider)pData;
+int AntiColliderAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[])
+{
+ pAntiCollider self = (pAntiCollider) pData;
Sequence seq;
char pBueffel[256];
pMotReg pMot = NULL;
-
+
assert(self != NULL);
- if(argc > 1){
- if(strcmp(argv[1],"clear") == 0){
- if(!SCMatchRights(pCon,usUser)){
- return 0;
+ if (argc > 1) {
+ if (strcmp(argv[1], "clear") == 0) {
+ if (!SCMatchRights(pCon, usUser)) {
+ return 0;
}
LLDdelete(self->sequenceList);
self->sequenceList = LLDcreate(sizeof(Sequence));
SCSendOK(pCon);
return 1;
- } else if(strcmp(argv[1],"list") == 0){
- ListSequence(self->sequenceList,pCon);
+ } else if (strcmp(argv[1], "list") == 0) {
+ ListSequence(self->sequenceList, pCon);
return 1;
}
}
- if(argc < 3){
- SCWrite(pCon,"ERROR : insufficient number of arguments to anticollision",
- eError);
+ if (argc < 3) {
+ SCWrite(pCon,
+ "ERROR : insufficient number of arguments to anticollision",
+ eError);
return 0;
}
strtolower(argv[1]);
- if(strcmp(argv[1],"script") == 0){
- if(!SCMatchRights(pCon,usMugger)){
+ if (strcmp(argv[1], "script") == 0) {
+ if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
- if(self->colliderScript != NULL){
+ if (self->colliderScript != NULL) {
free(self->colliderScript);
}
self->colliderScript = strdup(argv[2]);
SCSendOK(pCon);
return 1;
- } else if(strcmp(argv[1],"register") == 0){
- if(!SCMatchRights(pCon,usMugger)){
+ } else if (strcmp(argv[1], "register") == 0) {
+ if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
- if(FindDrivable(pSics,argv[2]) == NULL){
- sprintf(pBueffel,"ERROR: %s is NOT drivable, cannot register",argv[2]);
- SCWrite(pCon,pBueffel,eError);
+ if (FindDrivable(pSics, argv[2]) == NULL) {
+ snprintf(pBueffel,255, "ERROR: %s is NOT drivable, cannot register",
+ argv[2]);
+ SCWrite(pCon, pBueffel, eError);
return 0;
}
- pMot = RegisterMotor(argv[2],pSics,
- ReplacementSetValue,
- ReplacementCheckStatus);
- if(pMot){
- LLDnodeAppendFrom(self->motorList,&pMot);
+ pMot = RegisterMotor(argv[2], pSics,
+ ReplacementSetValue, ReplacementCheckStatus);
+ if (pMot) {
+ LLDnodeAppendFrom(self->motorList, &pMot);
SCSendOK(pCon);
return 1;
} else {
- SCWrite(pCon,"ERROR: out of memory registering motor",eError);
+ SCWrite(pCon, "ERROR: out of memory registering motor", eError);
return 0;
}
- } else if(strcmp(argv[1],"add") == 0){
- if(argc < 5){
+ } else if (strcmp(argv[1], "add") == 0) {
+ if (argc < 5) {
SCWrite(pCon,
- "ERROR: InsUfficient number of arguments to anticollicion add",
- eError);
+ "ERROR: Insufficient number of arguments to anticollicion add",
+ eError);
return 0;
}
seq.level = atoi(argv[2]);
- strncpy(seq.pMotor,argv[3],79);
+ strlcpy(seq.pMotor, argv[3], 79);
seq.target = atof(argv[4]);
- LLDnodeAppendFrom(self->sequenceList,&seq);
+ LLDnodeAppendFrom(self->sequenceList, &seq);
SCSendOK(pCon);
return 1;
- }
- SCWrite(pCon,"ERROR: anticollider command not understood",eError);
+ }
+ SCWrite(pCon, "ERROR: anticollider command not understood", eError);
return 0;
}
-
-
diff --git a/anticollider.h b/anticollider.h
index f526789c..76c8cb22 100644
--- a/anticollider.h
+++ b/anticollider.h
@@ -11,15 +11,10 @@
#define ANTICOLLIDER
- int AntiColliderFactory(SConnection *pCon, SicsInterp *pSics,
- void *pData,
- int argc, char *argv[]);
- int AntiColliderAction(SConnection *pCon, SicsInterp *pSics,
- void *pData,
- int argc, char *argv[]);
+int AntiColliderFactory(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[]);
+int AntiColliderAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[]);
#endif
-
-
-
diff --git a/arrayutil.c b/arrayutil.c
new file mode 100644
index 00000000..9d9c458a
--- /dev/null
+++ b/arrayutil.c
@@ -0,0 +1,46 @@
+/*
+ * arrayutil.c
+ *
+ * copyright: see file COPYRIGHT
+ *
+ * some utilities for dealing with arrays
+ *
+ * Created on: Mar 16, 2011
+ * Author: koennecke
+ */
+
+long sumWindow(int *data, int xstart, int xend, int xlength,
+ int ystart, int yend, int ylength)
+{
+ int i,j;
+ long result = 0;
+ int *row;
+
+ if(xstart < 0 || xstart > xlength){
+ return -2;
+ }
+ if(xend < 0 || xend > xlength){
+ return -2;
+ }
+ if(xend < xstart){
+ return -2;
+ }
+ if(ystart < 0 || ystart > ylength){
+ return -2;
+ }
+ if(yend < 0 || yend > ylength){
+ return -2;
+ }
+ if(yend < ystart){
+ return -2;
+ }
+
+
+ for(j = ystart; j < yend; j++){
+ row = data + j*xlength;
+ for(i = xstart; i < xend; i++){
+ result += row[i];
+ }
+ }
+ return result;
+}
diff --git a/arrayutil.h b/arrayutil.h
new file mode 100644
index 00000000..c2e23f38
--- /dev/null
+++ b/arrayutil.h
@@ -0,0 +1,31 @@
+/*
+ * arrayutil.h
+ *
+ * copyright: GPL
+ *
+ * Start of some array processing utilities. This may go if
+ * a more generalized array handling gets implemented into
+ * SICS.
+ *
+ * Created on: Mar 16, 2011
+ * Author: koennecke
+ */
+
+#ifndef ARRAYUTIL_H_
+#define ARRAYUTIL_H_
+
+/**
+ * sum data in a window
+ * @param data The data pointer
+ * @param xstart
+ * @param xend
+ * @param xlength length of x dimension
+ * @param ystart
+ * @param yend
+ * @param ylength size of y dimension
+ * @return a sum or -2 if the limits fail to make sense
+ */
+long sumWindow(int *data, int xstart, int xend, int xlength,
+ int ystart, int yend, int ylength);
+
+#endif /* ARRAYUTIL_H_ */
diff --git a/ascon.c b/ascon.c
index 0b27bb0e..d5d5f96a 100644
--- a/ascon.c
+++ b/ascon.c
@@ -12,18 +12,21 @@
#include "sics.h"
#include "splitter.h"
#include "ascon.i"
+#include "uselect.h"
+
+static double lastClose = 0; /* time of last close operation */
+static AsconProtocol *protocols = NULL;
/*
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
*/
-static int CreateSocketAdress(
- struct sockaddr_in *sockaddrPtr, /* Socket address */
- char *host, /* Host. NULL implies INADDR_ANY */
- int port) /* Port number */
-{
- struct hostent *hostent; /* Host database entry */
- struct in_addr addr; /* For 64/32 bit madness */
+static int CreateSocketAdress(struct sockaddr_in *sockaddrPtr, /* Socket address */
+ char *host, /* Host. NULL implies INADDR_ANY */
+ int port)
+{ /* Port number */
+ struct hostent *hostent; /* Host database entry */
+ struct in_addr addr; /* For 64/32 bit madness */
(void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
sockaddrPtr->sin_family = AF_INET;
@@ -34,11 +37,11 @@ static int CreateSocketAdress(
hostent = gethostbyname(host);
if (hostent != NULL) {
memcpy((char *) &addr,
- (char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
+ (char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
} else {
addr.s_addr = inet_addr(host);
- if (addr.s_addr == (unsigned long)-1) {
- return 0; /* error */
+ if (addr.s_addr == (unsigned long) -1) {
+ return 0; /* error */
}
}
}
@@ -50,39 +53,50 @@ static int CreateSocketAdress(
return 1;
}
-double DoubleTime(void) {
- struct timeval now;
- /* the resolution of this function is usec, if the machine supports this
- and the mantissa of a double is 51 bits or more (31 for sec and 20 for micro)
- */
- gettimeofday(&now, NULL);
- return now.tv_sec + now.tv_usec / 1e6;
-}
-
-void AsconError(Ascon *a, char *msg, int errorno) {
+void AsconError(Ascon *a, char *msg, int errorno)
+{
static char *stateText[]={
- "state 0", "kill", "state 2", "notConnected",
- "connect", "start connect", "connect finished", "connect failed",
- "write", "start write", "write finished", "write failed",
- "read", "start read", "read finished", "read failed",
- "state 16", "state 17", "state 18", "idle"
+ "not connected",
+ "connect start",
+ "connecting",
+ "connect done",
+ "write start",
+ "writing",
+ "write done",
+ "read start",
+ "reading",
+ "read done",
+ "idle",
+ "failed",
+ "timeout"
};
char *state;
+ char num[8];
- if (a->state < 0 || a->state > 19) {
+ if (a->state < 0 || a->state >= AsconMaxState) {
state = "bad state";
} else {
state = stateText[a->state];
}
- if (errorno != 0) {
- a->errList = ErrPutMsg(a->errList, "ASCERR: %s %s (during %s on %s)", msg, strerror(errorno), state, a->hostport);
+ DynStringCopy(a->errmsg, "ASCERR: ");
+ if (errorno == 0) {
+ DynStringConcat(a->errmsg, msg);
+ DynStringConcat(a->errmsg, " (");
+ DynStringConcat(a->errmsg, state);
+ DynStringConcat(a->errmsg, " state)");
} else {
- a->errList = ErrPutMsg(a->errList, "ASCERR: %s (during %s on %s)", msg, state, a->hostport);
+ DynStringConcat(a->errmsg, strerror(errorno));
+ DynStringConcat(a->errmsg, " (");
+ DynStringConcat(a->errmsg, state);
+ DynStringConcat(a->errmsg, " state, ");
+ DynStringConcat(a->errmsg, msg);
+ DynStringConcat(a->errmsg, ")");
}
- a->state |= AsconFailed;
+ a->state = AsconFailed;
}
-static void AsconConnect(Ascon *a) {
+static void AsconConnect(Ascon * a)
+{
/* input state: AsconConnectStart
output state: AsconFailed or AsconConnecting */
int ret;
@@ -91,16 +105,35 @@ static void AsconConnect(Ascon *a) {
int port;
int oldopts;
+ /* wait 0.5 sec before connecting again after a close
+ 2 reasons for that:
+ - it seems that connecting immediately to a closed port fails.
+ We will avoid some "Connection refused" error messages.
+ - a bug in the lantronix terminal: if a channel is closed and reopened
+ within short time the connect may be succesful, but a message will be
+ sent on the channel!
+ In principle we need only to wait when connecting to the same address
+ and port, but bookkeeping would be too complicated.
+ */
+ if (DoubleTime() < lastClose + 0.5) return;
+
if (a->fd < 0) {
- a->fd = socket(AF_INET,SOCK_STREAM,0);
+ a->fd = socket(AF_INET, SOCK_STREAM, 0);
if (a->fd < 0) {
- AsconError(a, "socket failed:", errno);
+ AsconError(a, "ASC1", errno);
return;
}
}
+ if (a->hostport == NULL) {
+ AsconError(a, "no host:port given", 0);
+ return;
+ }
colon = strchr(a->hostport, ':');
- if (colon == NULL) return;
- port = atoi(colon+1);
+ if (colon == NULL) {
+ AsconError(a, "expected 'host:port' or 'unconnected'", 0);
+ return;
+ }
+ port = atoi(colon + 1);
if (port <= 0) {
AsconError(a, "bad port number", 0);
return;
@@ -112,60 +145,45 @@ static void AsconConnect(Ascon *a) {
AsconError(a, "bad host specification", 0);
return;
}
- /* should we insert the workaround for lantronix server ? see network.c */
oldopts = fcntl(a->fd, F_GETFL, 0);
fcntl(a->fd, F_SETFL, oldopts | O_NONBLOCK);
- ret = connect(a->fd, (struct sockaddr *)&adr, sizeof(struct sockaddr_in));
+ ret =
+ connect(a->fd, (struct sockaddr *) &adr, sizeof(struct sockaddr_in));
if (ret < 0) {
- switch(errno) {
- case EINPROGRESS:
- case EALREADY:
- case EISCONN:
- a->state = AsconConnecting;
- break;
- default:
- AsconError(a, "connect failed:", errno);
- return;
- }
+ switch (errno) {
+ case EINPROGRESS:
+ case EALREADY:
+ case EISCONN:
+ a->state = AsconConnecting;
+ break;
+ default:
+ AsconError(a, "ASC2", errno);
+ return;
+ }
}
a->state = AsconConnecting;
return;
}
-int AsconStdInit(Ascon *a, SConnection *con,
- int argc, char *argv[]) {
- a->fd = -1;
- a->state = AsconConnectStart;
- a->reconnectInterval = 10;
- a->hostport = strdup(argv[1]);
- if(argc > 2){
- a->sendTerminator = strdup(argv[2]);
- } else {
- a->sendTerminator = strdup("\n");
- }
- if(argc > 3){
- a->timeout = atof(argv[3]);
- } else {
- a->timeout = 2.0; /* sec */
- }
- return 1;
-}
-int AsconReadGarbage(int fd) {
+int AsconReadGarbage(int fd)
+{
fd_set rmask;
- struct timeval tmo = {0,0};
+ struct timeval tmo = { 0, 0 };
int l, ret, result;
char garbage[100];
-
+
FD_ZERO(&rmask);
result = 0;
do {
FD_SET(fd, &rmask);
- ret = select(fd + 1, &rmask, NULL, NULL, &tmo);
+ ret = uselect(fd + 1, &rmask, NULL, NULL, &tmo);
if (ret > 0) {
- l = recv(fd, garbage, sizeof garbage, 0);
+ l = recv(fd, garbage, sizeof garbage - 1, 0);
if (l > 0) {
/* swallow */
+ garbage[l] = '\0';
+ /* printf("(((%s)))\n", garbage); */
result += l;
} else if (l == 0) {
errno = ECONNRESET;
@@ -178,7 +196,8 @@ int AsconReadGarbage(int fd) {
return result;
}
-void PrintChar(char chr) {
+void PrintChar(char chr)
+{
if (chr <= 32 || chr >= 127) {
printf("%2.2x ", chr);
} else {
@@ -186,49 +205,63 @@ void PrintChar(char chr) {
}
}
-int AsconConnectSuccess(int fd) {
+int AsconConnectSuccess(int fd)
+{
fd_set wmask, rmask;
- struct timeval tmo = {0,0};
+ struct timeval tmo = { 0, 0 };
int oldopts;
int ret;
-
+
oldopts = fcntl(fd, F_GETFL, 0);
assert(oldopts | O_NONBLOCK); /* fd must be in non-blocking mode */
-
+
FD_ZERO(&wmask);
FD_ZERO(&rmask);
FD_SET(fd, &wmask);
FD_SET(fd, &rmask);
- ret = select(fd + 1, &rmask, &wmask, NULL, &tmo);
+ ret = uselect(fd + 1, &rmask, &wmask, NULL, &tmo);
if (ret > 0) {
- assert(FD_ISSET(fd, &wmask));
- if (FD_ISSET(fd, &rmask)) { /* there may already be data for read */
- if (recv(fd, NULL, 0, 0) < 0) { /* zero length, check only return value */
+ /**
+ * MK:
+ * This assertion triggered for some reason: as writing is only done later
+ * I moved the test for ISSET(wmask) down there
+ * assert(FD_ISSET(fd, &wmask));
+ * MZ:
+ * I remember having found this logic on the www. Anyway, your way must be o.k. too
+ */
+
+ if (FD_ISSET(fd, &rmask)) { /* there may already be data for read */
+ if (recv(fd, NULL, 0, 0) < 0) { /* zero length, check only return value */
ret = ASCON_RECV_ERROR; /* first recv failed */
}
} else {
- if (send(fd, NULL, 0, 0) < 0) { /* zero length, check only return value */
- ret = ASCON_SEND_ERROR; /* first send failed */
+ if (FD_ISSET(fd,&wmask)) {
+ if (send(fd, NULL, 0, 0) < 0) { /* zero length, check only return value */
+ ret = ASCON_SEND_ERROR; /* first send failed */
+ }
}
}
}
- fcntl(fd, F_SETFL, oldopts & ~ O_NONBLOCK); /* reset to blocking mode */
+ fcntl(fd, F_SETFL, oldopts & ~O_NONBLOCK); /* reset to blocking mode */
return ret;
}
-int AsconReadChar(int fd, char *chr) {
+int AsconReadChar(int fd, char *chr)
+{
fd_set rmask;
- struct timeval tmo = {0,0};
+ struct timeval tmo = { 0, 0 };
int ret;
-
+
FD_ZERO(&rmask);
FD_SET(fd, &rmask);
- ret = select(fd + 1, &rmask, NULL, NULL, &tmo);
- if (ret <= 0) return ret;
+ ret = uselect(fd + 1, &rmask, NULL, NULL, &tmo);
+ if (ret <= 0)
+ return ret;
ret = recv(fd, chr, 1, 0);
/* PrintChar(*chr); */
fflush(stdout);
- if (ret > 0) return 1;
+ if (ret > 0)
+ return 1;
if (ret == 0) {
errno = ECONNRESET;
return ASCON_DISCONNECTED;
@@ -236,26 +269,30 @@ int AsconReadChar(int fd, char *chr) {
return ASCON_RECV_ERROR;
}
-int AsconWriteChars(int fd, char *data, int length) {
+int AsconWriteChars(int fd, char *data, int length)
+{
fd_set wmask;
- struct timeval tmo = {0,0};
+ struct timeval tmo = { 0, 0 };
int ret;
-
- if (length <= 0) return 0;
+
+ if (length <= 0)
+ return 0;
/*
- { int i;
- for (i=0; i 0) return ret;
+ if (ret > 0)
+ return ret;
if (ret == 0) {
errno = ECONNRESET;
return ASCON_DISCONNECTED;
@@ -265,14 +302,15 @@ int AsconWriteChars(int fd, char *data, int length) {
static double lastCall = 0;
-int AsconStdHandler(Ascon *a) {
+int AsconBaseHandler(Ascon * a)
+{
int ret;
int l;
char chr;
double now = DoubleTime();
-
- if (now > lastCall + 0.5) { /* AsconStdHandler was not called since a long time (0.5 sec) */
- if (lastCall != 0) { /* extend timeout time (for debugging purposes) */
+
+ if (now > lastCall + 0.5) { /* AsconBaseHandler was not called since a long time (0.5 sec) */
+ if (lastCall != 0) { /* extend timeout time (for debugging purposes) */
a->start += now - lastCall - 0.5;
}
}
@@ -286,29 +324,25 @@ int AsconStdHandler(Ascon *a) {
if (ret == 0) {
/* in progress */
} else if (ret > 0) {
- a->state = AsconConnectDone; /* success */
+ DynStringClear(a->errmsg);
+ a->state = AsconConnectDone; /* success */
} else if (ret < 0) {
- AsconError(a, "AsconConnectSuccess failed:", errno);
+ AsconError(a, "ASC3", errno);
}
break;
case AsconWriteStart:
- DynStringConcat(a->wrBuffer, a->sendTerminator);
+ if (a->sendTerminator) {
+ DynStringConcat(a->wrBuffer, a->sendTerminator);
+ }
a->wrPos = 0;
a->state = AsconWriting;
- if(strstr(GetCharArray(a->wrBuffer),"@@NOSEND@@") != NULL){
- a->state = AsconWriteDone;
- }
break;
case AsconWriting:
AsconReadGarbage(a->fd);
l = GetDynStringLength(a->wrBuffer) - a->wrPos;
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
if (ret < 0) {
- AsconError(a, "send failed:", errno);
- /*
- * Ooops: which state shall we go to after a write fail?
- * This seems to retry.
- */
+ AsconError(a, "ASC4", errno); /* sets state to AsconFailed */
} else {
a->wrPos += ret;
if (a->wrPos >= GetDynStringLength(a->wrBuffer)) {
@@ -323,149 +357,392 @@ int AsconStdHandler(Ascon *a) {
break;
case AsconReading:
ret = AsconReadChar(a->fd, &chr);
- while (ret > 0) {
- a->start = DoubleTime();
-
- if (chr == '\n') {
- if (a->readState) {
- /* swallow LF after CR */
- DynStringClear(a->rdBuffer);
- a->readState = 0;
- } else {
- DynStringConcatChar(a->rdBuffer, '\0');
- a->state = AsconReadDone;
- break;
- }
- } else if (chr == '\r') {
- a->readState = 1;
- DynStringConcatChar(a->rdBuffer, '\0');
- a->state = AsconReadDone;
- break;
- } else {
- if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
- AsconError(a, "DynStringConcatChar failed:", ENOMEM);
- break;
- }
- a->readState = 0;
+ if (ret <= 0) {
+ if (ret < 0) {
+ AsconError(a, "ASC5", errno);
+ return 0;
}
- ret = AsconReadChar(a->fd, &chr);
- }
- if (ret < 0) {
- AsconError(a, "AsconReadChar failed:", errno);
- return 1;
- }
- if (a->state == AsconReadDone) {
- DynStringConcatChar(a->rdBuffer, '\0');
- } else {
if (a->timeout > 0) {
if (DoubleTime() - a->start > a->timeout) {
- AsconError(a, "read timeout", 0);
+ AsconError(a, "no response", 0);
a->state = AsconTimeout;
}
}
+ return 0;
+ }
+ a->lastChar = chr;
+ a->start = DoubleTime();
+ if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
+ AsconError(a, "ASC6", errno);
+ return 0;
}
break;
default:
- return 1;
+ break;
}
return 1;
}
-/* define type AsconProtocolList and functions AsconProtocolAdd etc. */
-#define MC_NAME(T) AsconProtocol##T
-#include "mclist.c"
-
-static AsconProtocolList protocols={0};
-
void AsconInsertProtocol(AsconProtocol *protocol) {
- AsconProtocolAdd(&protocols, protocol);
+ protocol->next = protocols;
+ protocols = protocol;
}
-AsconHandler AsconSetHandler(Ascon *a, SConnection *con,
- int argc, char *argv[]) {
+AsconHandler AsconSetHandler(Ascon *a, SConnection *con,
+ int argc, char *argv[])
+{
AsconProtocol *p;
-
- if (argc < 1) return NULL;
+
+ if (argc < 1)
+ return NULL;
if (strcasecmp(argv[0], "std") == 0) {
- if (argc < 2) return NULL;
- AsconStdInit(a, con, argc, argv);
- return AsconStdHandler;
+ if (argc < 2)
+ return NULL;
+ if (AsconStdInit(a, con, argc, argv)) {
+ return AsconStdHandler;
+ } else {
+ return NULL;
+ }
}
- for (p = protocols.head; p!= NULL; p=p->next) {
+ for (p = protocols; p!= NULL; p=p->next) {
if (strcasecmp(p->name, argv[0]) == 0) {
- if(p->init(a, con, argc, argv)){
- return p->handler;
+ if (p->init(a, con, argc, argv)) {
+ return p->handler;
} else {
- return NULL;
+ return NULL;
}
}
}
return NULL;
}
+/* --- standard handler ---- */
+
+int AsconStdHandler(Ascon * a)
+{
+ int result;
+ char chr;
+ int ret, l;
+ char *cmd, *opt, *buf;
+
+ switch (a->state) {
+ case AsconWriteStart:
+ cmd = GetCharArray(a->wrBuffer);
+ a->lineCount = 1;
+ if (a->separator != NULL) { /* multiline mode enabled */
+ l = strlen(cmd);
+ if (l> 0 && cmd[l-1] == '}') {
+ opt = strrchr(cmd, '{');
+ if (opt != NULL) {
+ if (sscanf(opt, "{%d}", &a->lineCount) == 1) {
+ /* remove option */
+ for (l = strlen(opt); l > 0; l--) {
+ DynStringBackspace(a->wrBuffer);
+ }
+ }
+ }
+ }
+ } else if (strstr(GetCharArray(a->wrBuffer), "@@NOSEND@@") != NULL) {
+ a->state = AsconWriteDone;
+ return 1;
+ }
+ if(a->lineCount == 0){
+ a->noResponse = 1;
+ } else {
+ a->noResponse = 0;
+ }
+ break; /* go to the base handler */
+ case AsconReading:
+ if (a->lineCount == 0) {
+ /* no response expected */
+ a->state = AsconReadDone;
+ return 1;
+ }
+ result = AsconBaseHandler(a);
+ if (result == 0)
+ return 0;
+ chr = a->lastChar;
+ if (chr == '\0') { /* skip NUL characters */
+ DynStringBackspace(a->rdBuffer); /* remove NUL */
+ return 1;
+ }
+ if (a->replyTerminator != NULL) {
+ if (strchr(a->replyTerminator, chr) != NULL) {
+ if (a->compositeTerminator) {
+ /* one character was o.k., but all have to match */
+ l = strlen(a->replyTerminator);
+ buf = GetCharArray(a->rdBuffer) + GetDynStringLength(a->rdBuffer) - l;
+ if (strncmp(buf, a->replyTerminator, l) == 0) {
+ a->state = AsconReadDone;
+ }
+ } else {
+ a->state = AsconReadDone;
+ if (chr == '\n' || chr == '\r') {
+ DynStringBackspace(a->rdBuffer); /* remove LF or CR */
+ }
+ }
+ }
+ } else {
+ if (chr == '\n') { /* LF */
+ DynStringBackspace(a->rdBuffer); /* remove LF */
+ if (a->readState) { /* last char was CR */
+ /* LF after CR is not a terminator */
+ a->readState = 0;
+ } else {
+ a->state = AsconReadDone;
+ }
+ } else if (chr == '\r') { /* CR */
+ DynStringBackspace(a->rdBuffer); /* remove CR */
+ a->readState = 1; /* set 'last char was CR' */
+ a->state = AsconReadDone;
+ }
+ }
+ if (a->state == AsconReadDone && a->lineCount > 1) {
+ if (a->separator != NULL) {
+ DynStringConcat(a->rdBuffer, a->separator);
+ }
+ a->lineCount--;
+ a->state = AsconReading;
+ }
+ return 1; /* base handler was already called */
+ default:
+ break;
+ }
+ return AsconBaseHandler(a);
+}
+
+/**
+ * Treat hex strings as terminators right. Note that this
+ * is limited to single character terminators.
+ * M.Z. changed strstr to strncmp (more precise)
+ *
+ * M.Z. add new option (composite terminator):
+ * convert 'term' to term
+ */
+void AsconCheckTerminators(Ascon *a)
+{
+ int c, i, l;
+
+ if (a->sendTerminator != NULL && strncmp(a->sendTerminator,"0x",2) == 0) {
+ sscanf(a->sendTerminator,"%x",&c);
+ a->sendTerminator[0] = (char)c;
+ a->sendTerminator[1] = '\0';
+ }
+ if (a->replyTerminator != NULL && strncmp(a->replyTerminator,"0x",2) == 0) {
+ sscanf(a->replyTerminator,"%x",&c);
+ a->replyTerminator[0] = (char)c;
+ a->replyTerminator[1] = '\0';
+ }
+ a->compositeTerminator = 0;
+ if (a->replyTerminator != NULL && a->replyTerminator[0] == '\'') {
+ l = strlen(a->replyTerminator);
+ if (l > 2 && a->replyTerminator[l-1] == '\'') {
+ for (i = 0; i < l - 2; i++) {
+ a->replyTerminator[i] = a->replyTerminator[i+1];
+ }
+ a->replyTerminator[l-2] = '\0';
+ a->compositeTerminator = 1;
+ }
+ }
+}
+
+int AsconInterpreteArgs(int argc, char *argv[],
+ int parc, char *parn[], char *pars[])
+{
+ /* interprete arguments in the form "name=value" or
+ with a fixed order. The result is 1 in case
+ of success or 0 in case of an error. */
+
+ int ia, ip, l;
+
+ for (ip = 0; ip < parc; ip++) {
+ pars[ip] = NULL;
+ }
+ if (argc == 0) return 1;
+ if (strchr(argv[0], '=') == NULL) {
+ for (ia = 0; ia < argc; ia++) {
+ if (ia >= ip) {
+ return 0;
+ }
+ if (strchr(argv[ia], '=') != NULL) {
+ return 0;
+ }
+ pars[ia] = argv[ia];
+ }
+ return 1;
+ }
+ for (ia = 0; ia < argc; ia++) {
+ for (ip = 0; ip < parc; ip++) {
+ l = strlen(parn[ip]);
+ if (strncasecmp(argv[ia], parn[ip], l) == 0 && argv[ia][l] == '=') {
+ pars[ip] = argv[ia] + l + 1;
+ break;
+ }
+ }
+ if (ip >= parc) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[])
+{
+ enum nPars {NA=4};
+ char *pars[NA];
+ static char *parn[NA]={
+ "sendterminator",
+ "timeout",
+ "replyterminator",
+ "lineseparator"
+ };
+ char *msg;
+
+ assert(argc>1);
+ a->hostport = strdup(argv[1]);
+
+ if (!AsconInterpreteArgs(argc-2, argv+2, NA, parn, pars)) {
+ return 0;
+ }
+
+ if (pars[0]) {
+ a->sendTerminator = strdup(pars[0]);
+ } else {
+ a->sendTerminator = strdup("\n");
+ }
+ if (pars[1] && pars[1][0] != '\0') {
+ a->timeout = atof(pars[1]);
+ } else {
+ a->timeout = 2.0; /* sec */
+ }
+ if (pars[2] && pars[2][0] != '\0') {
+ a->replyTerminator = strdup(pars[2]);
+ } else {
+ a->replyTerminator = NULL;
+ }
+ if (pars[3] && pars[3][0] != '\0') {
+ a->separator = strdup(pars[3]);
+ } else {
+ a->separator = NULL;
+ }
+ AsconCheckTerminators(a);
+ return 1;
+}
+
/* --- implementation of higher level interface ---- */
-char *ConcatArgs(int argc, char *argv[]) {
+char *ConcatArgs(int argc, char *argv[])
+{
return Arg2Tcl(argc, argv, NULL, -1);
}
-Ascon *AsconMake(SConnection *con, int argc, char *argv[]) {
+Ascon *AsconMake(SConnection * con, int argc, char *argv[])
+{
Ascon *a;
char *args;
-
+
a = calloc(1, sizeof(*a));
if (a == NULL) {
SCWrite(con, "ERROR: no memory", eError);
return NULL;
}
+ a->fd = -1;
+ a->state = AsconConnectStart;
+ a->timeout = 2.0; /* 2 sec default */
+ a->reconnectInterval = 10; /* 10 sec default */
+ a->replyTerminator = NULL;
+ a->sendTerminator = NULL;
+ a->hostport = NULL;
+ a->responseValid = 0;
+ a->readState = 0;
+ a->lineCount = 1;
+ a->killPrivate = NULL;
+ a->private = NULL;
+
a->handler = AsconSetHandler(a, con, argc, argv);
if (a->handler == NULL) {
args = ConcatArgs(argc, argv);
- if (!args) return NULL;
+ if (!args)
+ return NULL;
SCPrintf(con, eError, "ERROR: illegal protocol: %s", args);
free(args);
return NULL;
}
a->rdBuffer = CreateDynString(60, 63);
a->wrBuffer = CreateDynString(60, 63);
- a->errList = NULL;
- a->responseValid = 0;
- a->reconnectInterval = 10;
- a->lastReconnect = 0;
+ a->errmsg = CreateDynString(60, 63);
+
return a;
}
-void AsconKill(Ascon *a) {
+void AsconKill(Ascon * a)
+{
if (a->fd > 0) {
close(a->fd);
+ lastClose = DoubleTime();
}
DeleteDynString(a->rdBuffer);
DeleteDynString(a->wrBuffer);
+ DeleteDynString(a->errmsg);
if (a->hostport) {
free(a->hostport);
}
- if(a->sendTerminator){
- free(a->sendTerminator);
+ if (a->sendTerminator) {
+ free(a->sendTerminator);
}
- if(a->private != NULL && a->killPrivate != NULL){
- a->killPrivate(a->private);
+ if (a->replyTerminator) {
+ free(a->replyTerminator);
+ }
+ if (a->separator) {
+ free(a->separator);
+ }
+ if (a->private != NULL && a->killPrivate != NULL) {
+ a->killPrivate(a->private);
}
free(a);
}
-AsconStatus AsconTask(Ascon *a) {
+void AsconDisconnect(Ascon * a)
+{
+ if (a->fd > 0) {
+ close(a->fd);
+ lastClose = DoubleTime();
+ }
+ a->fd = -1;
+ a->state = AsconNotConnected;
+}
+
+void AsconReconnect(Ascon * a, char * hostport)
+{
+ if (a->fd > 0) {
+ close(a->fd);
+ lastClose = DoubleTime();
+ }
+ if (hostport != NULL && hostport[0] != '\0') {
+ if (a->hostport) {
+ free(a->hostport);
+ }
+ a->hostport = strdup(hostport);
+ }
+ a->fd = -1;
+ a->state = AsconConnectStart;
+}
+
+AsconStatus AsconTask(Ascon * a)
+{
+ int result;
double now;
- while (a->handler(a)) {
+ while (1) {
+ result = a->handler(a);
switch (a->state) {
- case AsconReading:
- case AsconWriting:
- return AsconPending;
case AsconNotConnected:
return AsconOffline;
- break;
+ case AsconConnecting:
+ return AsconUnconnected;
case AsconConnectDone:
a->state = AsconIdle;
+ DynStringClear(a->errmsg); /* connection o.k. */
return AsconReady;
case AsconWriteDone:
if (a->noResponse) {
@@ -474,45 +751,46 @@ AsconStatus AsconTask(Ascon *a) {
}
a->state = AsconReadStart;
break;
+ case AsconReading:
+ if (result != 0) {
+ break; /* char received: try again, probably more characters pending */
+ }
+ return AsconPending;
case AsconReadDone:
a->state = AsconIdle;
a->responseValid = 1;
+ DynStringClear(a->errmsg);
return AsconReady;
- case AsconConnecting:
- return AsconUnconnected;
- default:
- switch (a->state % 4) {
- case AsconOnTheWay:
- case AsconStart:
- return AsconPending;
- case AsconFailed:
- /* ffr FIX reconnect if a device is restarted
- if (a->state == AsconTimeout) {
-we usually get to AsconFailed when a->state == AsconWriting */
- now = DoubleTime();
- if (now > a->lastReconnect + a->reconnectInterval) {
- a->lastReconnect = now;
- close(a->fd);
- a->fd = -1;
- a->state = AsconConnectStart;
- }
- /* ffr FIX reconnect
- }
- */
- return AsconFailure;
- case AsconFinished:
- if (a->state < AsconConnectFailed) {
- return AsconUnconnected;
- }
- return AsconReady;
+ case AsconIdle:
+ return AsconReady;
+ case AsconTimeout:
+ a->state = AsconIdle;
+ return AsconFailure;
+ case AsconFailed:
+ now = DoubleTime();
+ if (a->fd > 0) {
+ close(a->fd);
+ lastClose = now;
+ a->fd = -1;
}
+ if (now > a->lastReconnect + a->reconnectInterval) {
+ a->lastReconnect = now;
+ a->state = AsconConnectStart;
+ }
+ return AsconFailure;
+ default:
+ return AsconPending;
}
}
- return AsconIdle;
}
-int AsconWrite(Ascon *a, char *command, int noResponse) {
- if (a->state <= AsconConnectFailed || a->state % 4 < AsconFinished) return 0;
+int AsconWrite(Ascon * a, char *command, int noResponse)
+{
+ if (a->state != AsconIdle) {
+ /* this might happen if a script is sending after an error */
+ return 0;
+ }
+
DynStringCopy(a->wrBuffer, command);
a->noResponse = noResponse;
a->state = AsconWriteStart;
@@ -521,14 +799,15 @@ int AsconWrite(Ascon *a, char *command, int noResponse) {
return 1;
}
-char *AsconRead(Ascon *a) {
+char *AsconRead(Ascon * a)
+{
if (a->noResponse) {
- a->noResponse=0;
- return NULL;
+ a->noResponse = 0;
+ return "";
}
- if (a->state % 4 == AsconFailed) {
+ if (a->state != AsconIdle) {
a->state = AsconIdle;
- return NULL;
+ return "programming error in devser.c/ascon.c";
}
if (a->responseValid) {
a->responseValid = 0;
@@ -537,6 +816,27 @@ char *AsconRead(Ascon *a) {
return NULL;
}
-ErrMsg *AsconGetErrList(Ascon *a) {
- return a->errList;
+char *AsconGetError(Ascon *a)
+{
+ return GetCharArray(a->errmsg);
+}
+
+int AsconLastState(Ascon *a)
+{
+ return (int)a->state;
+}
+
+char *AsconHostport(Ascon *a)
+{
+ if (a==NULL) {
+ return NULL;
+ }
+ return a->hostport;
+}
+
+double AsconGetSetTimeout(Ascon *a, double timeout, int setmode) {
+ if (setmode) {
+ a->timeout = timeout;
+ }
+ return a->timeout;
}
diff --git a/ascon.h b/ascon.h
index fe6f4d32..1065e23e 100644
--- a/ascon.h
+++ b/ascon.h
@@ -2,13 +2,12 @@
#define ASCON_H
#include "sics.h"
-#include "errormsg.h"
/** \file
* \brief Asynchronous connection handling for devices controlled over tcp-ip
* connections. Interface for higher level modules.
*/
-
+
/** \brief the asynchronous connection
*/
typedef struct Ascon Ascon;
@@ -20,7 +19,7 @@ typedef enum {
AsconUnconnected,
AsconPending,
AsconReady,
- AsconFailure
+ AsconFailure /* codes after this indicate also failure */
} AsconStatus;
/** \brief make a new asynchronous connection
@@ -30,18 +29,28 @@ typedef enum {
* are protocol specific, but argv[1] is usually host::port
* \return the created connection or NULL on failure
*/
-Ascon *AsconMake(SConnection *con, int argc, char *argv[]);
+Ascon *AsconMake(SConnection * con, int argc, char *argv[]);
/** \brief kill function
* \param a the connection to be killed
*/
-void AsconKill(Ascon *a);
+void AsconKill(Ascon * a);
+/** \brief disconnect and disable
+ * \param a the connection to disconnect
+ */
+void AsconDisconnect(Ascon * a);
+
+/** \brief Reconnect function
+ * \param a the connection to reconnect
+ * \param hostport : to reconnect to (empty for reconnecting to the same port)
+ */
+void AsconReconnect(Ascon * a, char *hostport);
/** \brief the task handler. To be called repeatedly.
* \param a the connection
* \return the state of the connection
- */
-AsconStatus AsconTask(Ascon *a);
+ */
+AsconStatus AsconTask(Ascon * a);
/** \brief write to the connection. allowed only when the state is AsconReady
* \param a the connection
@@ -49,22 +58,24 @@ AsconStatus AsconTask(Ascon *a);
* \param noResponse 0 normally, 1 if no reponse is expected
* \return 1 on success, 0 when not ready
*/
-int AsconWrite(Ascon *a, char *command, int noResponse);
+int AsconWrite(Ascon * a, char *command, int noResponse);
/** \brief read from the connection. allowed only when a response is available
* \param a the connection
* \return the response when a response is ready
* NULL when the command has not completed and the response is not yet finished
* "" when the command has completed, but no response was expected.
- * The result is only valid until the next call to other AsconXxx functions
- * and has to be duplicated if needed later.
+ * The result is only valid until the next call to any AsconXxx function
+ * with the same connection and has to be duplicated if needed later.
*/
-char *AsconRead(Ascon *a);
+char *AsconRead(Ascon * a);
-/** \brief get the connections error list
- * \return the error list
+/** \brief get the last error message
+ * \return the error message
+ * The result is only valid until the next call to any AsconXxx function
+ * with the same connection and has to be duplicated if needed later.
*/
-ErrMsg *AsconGetErrList(Ascon *a);
+char *AsconGetError(Ascon *a);
/** \brief a helper function
* \param argc the number of args
@@ -74,9 +85,36 @@ ErrMsg *AsconGetErrList(Ascon *a);
*/
char *ConcatArgs(int argc, char *argv[]);
-/** \brief function for dealing with times with musec resolution
- * \return absolute time as double value
+/** \brief emit an error message. The state switches to AsconFailed.
+ * \param a the connection
+ * \param msg, a message to be emitted
+ * \param errorno, for user messages, this should be 0. After
+ * detection of a system error, eerno may be placed as argument
+ * for adding strerror(errno) to the message.
*/
-double DoubleTime(void);
+void AsconError(Ascon *a, char *msg, int errorno);
+
+/**
+ * \brief return the last ascon state. Only used for statistics
+ * \param a The Ascon to query
+ * \return the AsconState as an integer.
+ */
+int AsconLastState(Ascon *a);
+
+/**
+ * \brief return host:port
+ * \param a The Ascon to query
+ * \return the host and port
+ */
+char *AsconHostport(Ascon *a);
+
+/**
+ * \brief set or get timeout
+ * \param a the Ascon
+ * \param timeout the timeout to set
+ * \param setmode 0: get, 1: set
+ * \return the timeout value
+ */
+double AsconGetSetTimeout(Ascon *a, double timeout, int setmode);
#endif
diff --git a/ascon.i b/ascon.i
index 25f01eaa..2c510287 100644
--- a/ascon.i
+++ b/ascon.i
@@ -12,7 +12,7 @@
* For the implementation of a custom protocol, you have to implement
* the handler function and the init function, declare the protocol
* of type AsconProtocol and call AsconInsertProtocol on startup.
- * The handler and init functions are normally be a wrapper around AsconStdHandler
+ * The handler and init functions are normally a wrapper around AsconStdHandler
* and AsconStdInit
*
* The functions with fd as the first argument are utility functions with
@@ -22,28 +22,23 @@
*/
/**
- * A sub-state of the connection. Only states with sub-state AsconStart may
- * be set by the caller, and only when the sub-state is not AsconOnTheWay
- */
-typedef enum { AsconOnTheWay=0, AsconStart=1, AsconFinished=2, AsconFailed=3 } AsconMode;
-
-/**
- * The state of the connection. The sub-state is state % 4.
+ * The state of the connection.
*/
typedef enum {
- AsconNotConnected=0+AsconFinished,
- AsconConnecting=4+AsconOnTheWay,
- AsconConnectStart=AsconConnecting+AsconStart,
- AsconConnectDone=AsconConnecting+AsconFinished,
- AsconConnectFailed=AsconConnecting+AsconFailed,
- AsconWriting=8+AsconOnTheWay,
- AsconWriteStart=AsconWriting+AsconStart,
- AsconWriteDone=AsconWriting+AsconFinished,
- AsconReading=12+AsconOnTheWay,
- AsconReadStart=AsconReading+AsconStart,
- AsconReadDone=AsconReading+AsconFinished,
- AsconIdle=16+AsconFinished,
- AsconTimeout=20 + AsconFailed
+ AsconNotConnected, /**< unconnected, not to be connected automatically */
+ AsconConnectStart, /**< after initialisation or after AsconFailed */
+ AsconConnecting, /**< after AsconConnectStart or AsconConnecting */
+ AsconConnectDone, /**< after AsconConnecting */
+ AsconWriteStart, /**< set by the AsconWrite function */
+ AsconWriting, /**< after AsconWriteStart or AsconWriting */
+ AsconWriteDone, /**< after AsconWriting */
+ AsconReadStart, /**< after AsconWriteDone */
+ AsconReading, /**< after AsconReadStart or AsconReading */
+ AsconReadDone, /**< after AsconReading */
+ AsconIdle, /**< after AsconWriteDone, AsconReadDone, AsconTimeout, AsconIdle */
+ AsconFailed, /**< after any state */
+ AsconTimeout, /**< after AsconReading */
+ AsconMaxState /**< number of states */
} AsconState;
/** \brief the task handler function prototype
@@ -53,27 +48,35 @@ typedef enum {
typedef int (* AsconHandler)(Ascon *connection);
/** Ascon struct
- * all members are public, allowing access by handler wrappers
+ * all fields are public, allowing access by handler wrappers
+ * the fields marked with (std) are used by the standard handler
+ * they may get other meanings in a custom handler
*/
struct Ascon {
- AsconState state; /**< the current state */
- int fd; /**< socket */
- int readState; /**< default implementation: 'was cr' */
- pDynString rdBuffer;/**< read buffer */
- pDynString wrBuffer;/**< write buffer */
- int wrPos; /**< write buffer position */
- double timeout; /**< read timeout (sec) */
- char *sendTerminator; /**< terminator for sending messages */
- char *hostport; /**< host:port to connect */
- ErrMsg *errList; /**< error message list */
- double start; /**< unix time when read was started */
- void *private; /**< private data of protocol */
- void (*killPrivate)(void *); /** < kill function for private */
- int noResponse; /**< no response expected */
- int responseValid; /**< a valid response is ready */
- AsconHandler handler; /**< handler function */
- double reconnectInterval; /**< reconnect interval */
- double lastReconnect; /**< last connect try */
+ AsconState state; /**< the current state */
+ int fd; /**< socket */
+ int conState; /**< 1: connection refused, 0: else */
+ int readState; /**< (std) last char was CR */
+ pDynString rdBuffer; /**< read buffer */
+ pDynString wrBuffer; /**< write buffer */
+ int wrPos; /**< write buffer position */
+ double timeout; /**< read timeout (sec) */
+ char *sendTerminator; /**< terminator for sending messages */
+ char *replyTerminator; /**< (std) terminator list for reply. NULL is the special case CR, LF or CR/LF */
+ char *hostport; /**< host:port to connect */
+ pDynString errmsg; /**< error message */
+ double start; /**< unix time when read was started */
+ int noResponse; /**< no response expected */
+ int responseValid; /**< a valid response is ready */
+ AsconHandler handler; /**< handler function */
+ double reconnectInterval; /**< reconnect interval */
+ double lastReconnect; /**< last reconnect try */
+ char lastChar; /**< last char read */
+ char *separator; /**< (std) separator for multiline responses */
+ int lineCount; /**< number of lines expected (counting down) */
+ int compositeTerminator; /**< the terminator contains several chars */
+ void *private; /**< private data of protocol */
+ void (*killPrivate)(void *); /**< kill function for private */
};
#define ASCON_SELECT_ERROR -1
@@ -81,20 +84,48 @@ struct Ascon {
#define ASCON_SEND_ERROR -3
#define ASCON_DISCONNECTED -4
+/** \brief the basic handler routine.
+ * \param a the connection
+ * \return when the state before the call was not AsconReading, the return
+ * value should be 1
+ * when the state was AsconReading, a 1 indicates that a character was read
+ * and the character is stored in the lastChar field. A 0 indicates
+ * that no character was read. And this 0 has to be given, otherwise AsconTask
+ * goes into an endless loop till timeout is hit!
+ *
+ *
+ * In most cases a custom handler may be a wrapper around AsconBaseHandler
+ * or around AsconStdHandler
+ */
+int AsconBaseHandler(Ascon *a);
+
/** \brief the standard handler routine.
* \param a the connection
- * \return 0 when task has finished (connection to be closed), 1 when active
+ * \return see AsconBaseHandler
*
- * In most cases a custom handler may be a wrapper around AsconStdHandler
+ * features: see description of AsconStdInit
*/
int AsconStdHandler(Ascon *a);
/** \brief initialize a standard connection
* \param a the connection
* \param con A connection to print errors too.
- * \param hostport the tcp/ip address (syntax: host:port)
+ * \param argc number of arguments
+ * \param argv arguments (":" [sendTerminator] [timeout] [replyTerminators] [separator])
+ * sendTerminator is a character or string sent at the end of a command
+ * timeout is in seconds
+ * replyTerminators is a string, meant as a list of terminator characters
+ * if no replyTerminator is given, or if it is empty, CR, LF or CR/LF all are detected
+ * as terminators. If the terminator is CR, LF or CR/LF, it is removed from the result,
+ * all other terminators are kept in the result.
+ * is the first and the last character are single quotes (') is is treated as a composite
+ * terminator and not as a list of single character terminators
+ * separator is used for multiline responses. If this parameter
+ * is given (and not empty) a command may be followed by a line count in curly brackets,
+ * indicating that a multiline response is expected. All the lines of the response are
+ * then returned, separated with "separator"
*
- * In most cases a custom init function may be a wrapper around AsconStdInit
+ * In many cases a custom init function may be a wrapper around AsconStdInit
*/
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[]);
@@ -149,8 +180,18 @@ int AsconWriteChars(int fd, char *data, int length);
* \param a The asynchronous I/O structure to store the
* error with
* \param msg The error message
- * \param errorno The error number
+ * \param errorno The error number or 0 for a custom error
*/
void AsconError(Ascon *a, char *msg, int errorno);
+int AsconInterpreteArgs(int argc, char *argv[],
+ int parc, char *parn[], char *pars[]);
+
+
+/**
+ * Treat hex strings as terminators right. Note that this
+ * is limited to single character terminators.
+ */
+void AsconCheckTerminators(Ascon *a);
+
#endif
diff --git a/asyncprotocol.c b/asyncprotocol.c
index 5576126a..49a0118c 100644
--- a/asyncprotocol.c
+++ b/asyncprotocol.c
@@ -2,7 +2,8 @@
#include
#include
-int defaultSendCommand(pAsyncProtocol p, pAsyncTxn txn) {
+int defaultSendCommand(pAsyncProtocol p, pAsyncTxn txn)
+{
int i, iRet;
int state;
const char *term = "\r\n";
@@ -10,10 +11,9 @@ int defaultSendCommand(pAsyncProtocol p, pAsyncTxn txn) {
term = p->sendTerminator;
state = 0;
for (i = 0; i < txn->out_len; ++i) {
- if (txn->out_buf[i] == 0x00) { /* end of transmission */
+ if (txn->out_buf[i] == 0x00) { /* end of transmission */
break;
- }
- else if (txn->out_buf[i] == term[state]) {
+ } else if (txn->out_buf[i] == term[state]) {
++state;
continue;
}
@@ -24,29 +24,23 @@ int defaultSendCommand(pAsyncProtocol p, pAsyncTxn txn) {
if (iRet <= 0)
return iRet;
if (term[state] != 0)
- iRet = AsyncUnitWrite(txn->unit, (void *)term, strlen(term));
+ iRet = AsyncUnitWrite(txn->unit, (void *) term, strlen(term));
return iRet;
}
-int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch) {
+int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch)
+{
const char *term = "\r\n";
- if (txn->txn_state == 0) {
- int i;
- for (i = 0; i < 10; ++i)
- if (p->replyTerminator[i] && ch == p->replyTerminator[i][0]) {
- txn->txn_state = i << 16;
- break;
- }
- }
- term = p->replyTerminator[txn->txn_state >> 16];
- if (ch == term[txn->txn_state & 0xffff])
+ if (p->replyTerminator)
+ term = p->replyTerminator;
+ if (ch == term[txn->txn_state])
++txn->txn_state;
else
txn->txn_state = 0;
if (txn->inp_idx < txn->inp_len)
txn->inp_buf[txn->inp_idx++] = ch;
- if (term[txn->txn_state & 0xffff] == 0) {
+ if (term[txn->txn_state] == 0) {
if (txn->inp_idx < txn->inp_len)
txn->inp_buf[txn->inp_idx] = '\0';
return AQU_POP_CMD;
@@ -54,12 +48,15 @@ int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch) {
return 1;
}
-int defaultHandleEvent(pAsyncProtocol p, pAsyncTxn txn, int event) {
+int defaultHandleEvent(pAsyncProtocol p, pAsyncTxn txn, int event)
+{
/* TODO: what could or should we do to handle the event */
return AQU_POP_CMD;
}
-int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_len, int rsp_len) {
+int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char *cmd,
+ int cmd_len, int rsp_len)
+{
int i;
int state;
const char *term = "\r\n";
@@ -67,7 +64,10 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_
term = p->sendTerminator;
state = 0;
for (i = 0; i < cmd_len; ++i) {
- if (cmd[i] == term[state]) {
+ if (cmd[i] == 0x00) { /* end of transmission */
+ cmd_len = i;
+ break;
+ } else if (cmd[i] == term[state]) {
++state;
continue;
}
@@ -77,17 +77,18 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_
/* outgoing command is correctly terminated */
txn->out_buf = malloc(cmd_len + 1);
if (txn->out_buf == NULL) {
- SICSLogWrite("Out of memory in AsyncProtocol::defaultPrepareTxn", eError);
+ SICSLogWrite("Out of memory in AsyncProtocol::defaultPrepareTxn",
+ eError);
return 0;
}
memcpy(txn->out_buf, cmd, cmd_len + 1);
- }
- else {
+ } else {
/* outgoing command is NOT correctly terminated */
int tlen = strlen(term);
txn->out_buf = malloc(cmd_len + tlen + 1);
if (txn->out_buf == NULL) {
- SICSLogWrite("Out of memory in AsyncProtocol::defaultPrepareTxn", eError);
+ SICSLogWrite("Out of memory in AsyncProtocol::defaultPrepareTxn",
+ eError);
return 0;
}
memcpy(txn->out_buf, cmd, cmd_len);
@@ -96,9 +97,17 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_
}
txn->out_len = cmd_len;
txn->out_idx = 0;
- if(txn->inp_buf != NULL){
+ if (txn->inp_buf != NULL) {
free(txn->inp_buf);
}
+ txn->inp_buf = malloc(rsp_len);
+ if (txn->inp_buf == NULL) {
+ SICSLogWrite("Out of memory in AsyncProtocol::defaultPrepareTxn",
+ eError);
+ free(txn->out_buf);
+ txn->out_buf = NULL;
+ return 0;
+ }
txn->inp_len = rsp_len;
txn->inp_idx = 0;
txn->txn_state = 0;
@@ -106,29 +115,25 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_
return 1;
}
-static const char* hex = "0123456789ABCDEF";
+static const char *hex = "0123456789ABCDEF";
/*--------------------------------------------------------------------*/
static void encodeTerminator(char *result, char *terminator)
{
if (terminator)
while (*terminator) {
- if (*terminator <= 32 || *terminator >= 127) {
- *result++ = '0';
- *result++ = 'x';
- *result++ = hex[(*terminator >> 4) &0xF];
- *result++ = hex[(*terminator) &0xF];
- ++terminator;
- }
- else {
- *result++ = *terminator++;
- }
+ *result++ = '0';
+ *result++ = 'x';
+ *result++ = hex[(*terminator >> 4) & 0xF];
+ *result++ = hex[(*terminator) & 0xF];
+ ++terminator;
}
*result = '\0';
return;
}
-static int fromHex(const char* code) {
+static int fromHex(const char *code)
+{
int icode = -1;
int result = -1;
if (code[0] == '0' && (code[1] == 'x' || code[1] == 'X')) {
@@ -155,78 +160,77 @@ static int fromHex(const char* code) {
}
return -1;
}
+
/*--------------------------------------------------------------------*/
static char *decodeTerminator(char *code)
{
int count = 0, icode;
char *pResult;
- char* pCh;
- char* pQt = NULL; /* pointer to quote character if found */
+ char *pCh;
+ char *pQt = NULL; /* pointer to quote character if found */
if (code == NULL)
return NULL;
count = strlen(code);
pResult = (char *) malloc(count + 1);
if (!pResult) {
- SICSLogWrite("Out of memory in AsyncProtocol::decodeTerminator", eError);
+ SICSLogWrite("Out of memory in AsyncProtocol::decodeTerminator",
+ eError);
return NULL;
}
memset(pResult, 0, count + 1);
pCh = pResult;
- if (*code == '\'' || *code == '"') /* check for leading quote */
+ if (*code == '\'' || *code == '"') /* check for leading quote */
pQt = code++;
while (*code) {
- if (pQt && *code == *pQt) /* check for trailing quote */
+ if (pQt && *code == *pQt) /* check for trailing quote */
break;
- if (code[0] == '\\' && code[1] == 'r') { /* CR */
+ if (code[0] == '\\' && code[1] == 'r') { /* CR */
*pCh++ = '\r';
code += 2;
- }
- else if (code[0] == '\\' && code[1] == 'n') { /* LF */
+ } else if (code[0] == '\\' && code[1] == 'n') { /* LF */
*pCh++ = '\n';
code += 2;
- }
- else if ((icode = fromHex(code)) >= 0) { /* Hex: 0xFF */
+ } else if ((icode = fromHex(code)) >= 0) { /* Hex: 0xFF */
*pCh++ = icode;
code += 4;
- }
- else /* literal */
+ } else /* literal */
*pCh++ = *code++;
}
*pCh = '\0';
return pResult;
}
-int AsyncProtocolNoAction(SConnection *pCon, SicsInterp *pSics,
- void *pData, int argc, char *argv[])
+int AsyncProtocolNoAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[])
{
char line[132];
+ pAsyncProtocol self = (pAsyncProtocol) pData;
snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]);
SCWrite(pCon, line, eError);
return 0;
}
-int AsyncProtocolAction(SConnection *pCon, SicsInterp *pSics,
+int AsyncProtocolAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
+ char line[132];
pAsyncProtocol self = (pAsyncProtocol) pData;
if (argc > 1) {
/* handle genecic parameters like terminators */
if (strcasecmp(argv[1], "sendterminator") == 0) {
if (argc > 2) {
- char* pPtr = decodeTerminator(argv[2]);
+ char *pPtr = decodeTerminator(argv[2]);
if (pPtr) {
if (self->sendTerminator)
free(self->sendTerminator);
self->sendTerminator = pPtr;
}
SCSendOK(pCon);
- }
- else
- {
+ } else {
char term[132];
char line[1024];
encodeTerminator(term, self->sendTerminator);
@@ -234,47 +238,27 @@ int AsyncProtocolAction(SConnection *pCon, SicsInterp *pSics,
SCWrite(pCon, line, eValue);
}
return 1;
- }
- else if (strcasecmp(argv[1], "replyterminator") == 0) {
+ } else if (strcasecmp(argv[1], "replyterminator") == 0) {
if (argc > 2) {
- int i;
- for (i = 0; i < 10; ++i)
- if (self->replyTerminator[i]) {
- free(self->replyTerminator[i]);
- self->replyTerminator[i] = NULL;
- }
- for (i = 0; i < 10 && i < argc - 2; ++i) {
- char* pPtr = decodeTerminator(argv[i + 2]);
- if (pPtr) {
- self->replyTerminator[i] = pPtr;
- }
+ char *pPtr = decodeTerminator(argv[2]);
+ if (pPtr) {
+ if (self->replyTerminator)
+ free(self->replyTerminator);
+ self->replyTerminator = pPtr;
}
SCSendOK(pCon);
- }
- else
- {
- int i;
+ } else {
char term[132];
char line[1024];
- term[0] = '\0';
- sprintf(line, "%s.replyTerminator =", argv[0]);
- for (i = 0; i < 10; ++i) {
- if (self->replyTerminator[i] == NULL)
- break;
- term[0] = ' ';
- term[1] = '"';
- encodeTerminator(&term[2], self->replyTerminator[i]);
- strcat(term, "\"");
- strcat(line, term);
- }
+ encodeTerminator(term, self->replyTerminator);
+ sprintf(line, "%s.replyTerminator = \"%s\"", argv[0], term);
SCWrite(pCon, line, eValue);
}
return 1;
}
- }
- else if (strcasecmp(argv[1], "list") == 0) {
+ } else if (strcasecmp(argv[1], "list") == 0) {
int ac = 2;
- char* av[3] = { argv[0], 0, 0 };
+ char *av[3] = { argv[0], 0, 0 };
av[1] = "sendterminator";
AsyncProtocolAction(pCon, pSics, pData, ac, av);
av[1] = "replyterminator";
@@ -282,37 +266,41 @@ int AsyncProtocolAction(SConnection *pCon, SicsInterp *pSics,
return 1;
}
/* handle any other actions here */
- return AsyncProtocolNoAction(pCon, pSics, pData, argc,argv);
+ return AsyncProtocolNoAction(pCon, pSics, pData, argc, argv);
}
-void defaultKillPrivate(pAsyncProtocol p) {
+void defaultKillPrivate(pAsyncProtocol p)
+{
if (p->privateData) {
/* TODO: should we do anything? */
free(p->privateData);
}
}
-void AsyncProtocolKill(void *pData) {
+void AsyncProtocolKill(void *pData)
+{
pAsyncProtocol self = (pAsyncProtocol) pData;
- int i;
- if(self->pDes)
+ if (self->pDes)
DeleteDescriptor(self->pDes);
- if(self->sendTerminator != NULL)
+ if (self->sendTerminator != NULL)
free(self->sendTerminator);
- for (i = 0; i < 10; ++i)
- if(self->replyTerminator[i] != NULL)
- free(self->replyTerminator[i]);
+ if (self->replyTerminator != NULL)
+ free(self->replyTerminator);
if (self->killPrivate)
self->killPrivate(self);
}
-pAsyncProtocol AsyncProtocolCreate(SicsInterp *pSics, const char* protocolName,
- ObjectFunc pFunc, KillFunc pKFunc) {
+pAsyncProtocol AsyncProtocolCreate(SicsInterp * pSics,
+ const char *protocolName,
+ ObjectFunc pFunc, KillFunc pKFunc)
+{
int iRet;
pAsyncProtocol self = NULL;
/* try to find an existing queue with this name */
- self = (pAsyncProtocol) FindCommandData(pServ->pSics, (char *)protocolName, "AsyncProtocol");
+ self =
+ (pAsyncProtocol) FindCommandData(pServ->pSics, (char *) protocolName,
+ "AsyncProtocol");
if (self != NULL) {
return self;
}
@@ -328,8 +316,8 @@ pAsyncProtocol AsyncProtocolCreate(SicsInterp *pSics, const char* protocolName,
pFunc = AsyncProtocolNoAction;
if (pKFunc == NULL)
pKFunc = AsyncProtocolKill;
- iRet = AddCommand(pSics, (char *)protocolName, pFunc, pKFunc, self);
- if (!iRet ) {
+ iRet = AddCommand(pSics, (char *) protocolName, pFunc, pKFunc, self);
+ if (!iRet) {
SICSLogWrite("AddCommand failed in AsyncProtocolCreate", eError);
AsyncProtocolKill(self);
return NULL;
@@ -340,18 +328,21 @@ pAsyncProtocol AsyncProtocolCreate(SicsInterp *pSics, const char* protocolName,
self->prepareTxn = defaultPrepareTxn;
self->killPrivate = defaultKillPrivate;
self->sendTerminator = strdup("\r\n");
- self->replyTerminator[0] = strdup("\r\n");
+ self->replyTerminator = strdup("\r\n");
return self;
}
-int AsyncProtocolFactory(SConnection *pCon, SicsInterp *pSics,
- void *pData, int argc, char *argv[]) {
+int AsyncProtocolFactory(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[])
+{
if (argc < 2) {
- SCWrite(pCon,"ERROR: insufficient arguments to AsyncProtocolFactory", eError);
+ SCWrite(pCon, "ERROR: insufficient arguments to AsyncProtocolFactory",
+ eError);
return 0;
}
pAsyncProtocol pNew = AsyncProtocolCreate(pSics, argv[1],
- AsyncProtocolAction, AsyncProtocolKill);
+ AsyncProtocolAction,
+ AsyncProtocolKill);
/* handle any extra arguments here */
pNew->privateData = NULL;
return 1;
diff --git a/asyncprotocol.h b/asyncprotocol.h
index ebbb07f7..3c943666 100644
--- a/asyncprotocol.h
+++ b/asyncprotocol.h
@@ -4,40 +4,41 @@
typedef struct __AsyncUnit AsyncUnit, *pAsyncUnit;
typedef struct __async_txn AsyncTxn, *pAsyncTxn;
-typedef int (*AsyncTxnHandler)(pAsyncTxn pTxn);
+typedef int (*AsyncTxnHandler) (pAsyncTxn pTxn);
typedef struct __async_protocol AsyncProtocol, *pAsyncProtocol;
-pAsyncProtocol AsyncProtocolCreate(SicsInterp *pSics, const char* protocolName,
- ObjectFunc pFunc, KillFunc pKFunc);
+pAsyncProtocol AsyncProtocolCreate(SicsInterp * pSics,
+ const char *protocolName,
+ ObjectFunc pFunc, KillFunc pKFunc);
-int AsyncProtocolAction(SConnection *pCon, SicsInterp *pSics,
+int AsyncProtocolAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]);
-int AsyncProtocolFactory(SConnection *pCon, SicsInterp *pSics,
- void *pData, int argc, char *argv[]);
+int AsyncProtocolFactory(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[]);
typedef enum {
- ATX_NULL=0,
- ATX_TIMEOUT=-1,
- ATX_ACTIVE=1,
- ATX_COMPLETE=2,
- ATX_DISCO=3
+ ATX_NULL = 0,
+ ATX_TIMEOUT = -1,
+ ATX_ACTIVE = 1,
+ ATX_COMPLETE = 2,
+ ATX_DISCO = 3
} ATX_STATUS;
struct __async_txn {
- pAsyncUnit unit; /**< unit that transaction is associated with */
- int txn_state; /**< protocol handler transaction parse state */
- ATX_STATUS txn_status; /**< status of the transaction OK, Error, ... */
- int txn_timeout; /**< transaction timeout in milliseconds */
- char* out_buf; /**< output buffer for sendCommand */
- int out_len; /**< length of data to be sent */
- int out_idx; /**< index of next character to transmit */
- char* inp_buf; /**< input buffer for transaction response */
- int inp_len; /**< length of input buffer */
- int inp_idx; /**< index of next character (number already received) */
+ pAsyncUnit unit; /**< unit that transaction is associated with */
+ int txn_state; /**< protocol handler transaction parse state */
+ ATX_STATUS txn_status; /**< status of the transaction OK, Error, ... */
+ int txn_timeout; /**< transaction timeout in milliseconds */
+ char *out_buf; /**< output buffer for sendCommand */
+ int out_len; /**< length of data to be sent */
+ int out_idx; /**< index of next character to transmit */
+ char *inp_buf; /**< input buffer for transaction response */
+ int inp_len; /**< length of input buffer */
+ int inp_idx; /**< index of next character (number already received) */
AsyncTxnHandler handleResponse; /**< Txn response handler of command sender */
- void* cntx; /**< opaque context used by command sender */
+ void *cntx; /**< opaque context used by command sender */
/* The cntx field may be used by protocol handler from sendCommand
* as long as it is restored when response is complete
*/
@@ -48,15 +49,16 @@ struct __async_txn {
*/
struct __async_protocol {
pObjectDescriptor pDes;
- char* protocolName;
+ char *protocolName;
char *sendTerminator;
- char *replyTerminator[10];
- void* privateData;
- int (* sendCommand)(pAsyncProtocol p, pAsyncTxn txn);
- int (* handleInput)(pAsyncProtocol p, pAsyncTxn txn, int ch);
- int (* handleEvent)(pAsyncProtocol p, pAsyncTxn txn, int event);
- int (* prepareTxn)(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_len, int rsp_len);
- void (* killPrivate)(pAsyncProtocol p);
+ char *replyTerminator;
+ void *privateData;
+ int (*sendCommand) (pAsyncProtocol p, pAsyncTxn txn);
+ int (*handleInput) (pAsyncProtocol p, pAsyncTxn txn, int ch);
+ int (*handleEvent) (pAsyncProtocol p, pAsyncTxn txn, int event);
+ int (*prepareTxn) (pAsyncProtocol p, pAsyncTxn txn, const char *cmd,
+ int cmd_len, int rsp_len);
+ void (*killPrivate) (pAsyncProtocol p);
};
-#endif /* ASYNCPROTOCOL */
+#endif /* ASYNCPROTOCOL */
diff --git a/asyncqueue.c b/asyncqueue.c
index 9faa9ed1..6b75a9f8 100644
--- a/asyncqueue.c
+++ b/asyncqueue.c
@@ -8,178 +8,105 @@
* single command channel.
*
* Douglas Clowes, February 2007
- *
+ *
*/
#include
#include
#include
#include
-#include
-#include
#include
#include
#include "network.h"
#include "asyncqueue.h"
#include "nwatch.h"
-#include
typedef struct __async_command AQ_Cmd, *pAQ_Cmd;
struct __async_command {
- pAQ_Cmd next;
- pAsyncTxn tran;
- pAsyncUnit unit;
- int timeout;
- int retries;
- int active;
+ pAQ_Cmd next;
+ pAsyncTxn tran;
+ pAsyncUnit unit;
+ int timeout;
+ int retries;
+ int active;
};
struct __AsyncUnit {
- pAsyncUnit next;
+ pAsyncUnit next;
pAsyncQueue queue;
- AQU_Notify notify_func;
- void* notify_cntx;
+ AQU_Notify notify_func;
+ void *notify_cntx;
};
-typedef enum {eAsyncIdle, eAsyncWaiting, eAsyncConnecting, eAsyncConnected} AsyncState;
-
struct __AsyncQueue {
pObjectDescriptor pDes;
- char* queue_name;
- char* pHost;
- int iPort;
- int iDelay; /* intercommand delay in milliseconds */
- int timeout;
- int retries;
- int retryTimer; /* mSec delay before next retry */
- bool translate; /* translate binary output with escaped chars */
- struct timeval tvLastCmd; /* time of completion of last command */
- int unit_count; /* number of units connected */
- pAsyncUnit units; /* head of unit chain */
- pAQ_Cmd command_head; /* first/next command in queue */
- pAQ_Cmd command_tail; /* last command in queue */
- pNWContext nw_ctx; /* NetWait context handle */
- pNWTimer nw_tmr; /* NetWait timer handle */
- mkChannel* pSock; /* socket address */
- AsyncState state; /* Queue Connection State */
- pAsyncProtocol protocol;
- void* context; /**< opaque caller queue context */
+ char *queue_name;
+ char *pHost;
+ int iPort;
+ int iDelay; /* intercommand delay in milliseconds */
+ int timeout;
+ int retries;
+ struct timeval tvLastCmd; /* time of completion of last command */
+ int unit_count; /* number of units connected */
+ pAsyncUnit units; /* head of unit chain */
+ pAQ_Cmd command_head; /* first/next command in queue */
+ pAQ_Cmd command_tail; /* last command in queue */
+ pNWContext nw_ctx; /* NetWait context handle */
+ pNWTimer nw_tmr; /* NetWait timer handle */
+ mkChannel *pSock; /* socket address */
+ pAsyncProtocol protocol;
};
static pAsyncQueue queue_array[FD_SETSIZE];
static int queue_index = 0;
-static const char* state_name(AsyncState the_state) {
- switch (the_state) {
- case eAsyncIdle:
- return "eAsyncIdle";
- case eAsyncWaiting:
- return "eAsyncWaiting";
- case eAsyncConnecting:
- return "eAsyncConnecting";
- case eAsyncConnected:
- return "eAsyncConnected";
- }
- return "";
-}
-
/* ---------------------------- Local ------------------------------------
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
*/
-static int
-CreateSocketAdress(
- struct sockaddr_in *sockaddrPtr, /* Socket address */
- char *host, /* Host. NULL implies INADDR_ANY */
- int port) /* Port number */
-{
- struct hostent *hostent; /* Host database entry */
- struct in_addr addr; /* For 64/32 bit madness */
+static int CreateSocketAdress(struct sockaddr_in *sockaddrPtr, /* Socket address */
+ char *host, /* Host. NULL implies INADDR_ANY */
+ int port)
+{ /* Port number */
+ struct hostent *hostent; /* Host database entry */
+ struct in_addr addr; /* For 64/32 bit madness */
- (void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
- sockaddrPtr->sin_family = AF_INET;
- sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
- if (host == NULL) {
- addr.s_addr = INADDR_ANY;
+ (void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
+ sockaddrPtr->sin_family = AF_INET;
+ sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
+ if (host == NULL) {
+ addr.s_addr = INADDR_ANY;
+ } else {
+ hostent = gethostbyname(host);
+ if (hostent != NULL) {
+ memcpy((char *) &addr,
+ (char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
} else {
- hostent = gethostbyname(host);
- if (hostent != NULL) {
- memcpy((char *) &addr,
- (char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
- } else {
- addr.s_addr = inet_addr(host);
- if (addr.s_addr == (unsigned long)-1) {
- return 0; /* error */
- }
- }
+ addr.s_addr = inet_addr(host);
+ if (addr.s_addr == (unsigned long) -1) {
+ return 0; /* error */
+ }
}
- /*
- * There is a rumor that this assignment may require care on
- * some 64 bit machines.
- */
+ }
+ /*
+ * There is a rumor that this assignment may require care on
+ * some 64 bit machines.
+ */
- sockaddrPtr->sin_addr.s_addr = addr.s_addr;
- return 1;
+ sockaddrPtr->sin_addr.s_addr = addr.s_addr;
+ return 1;
}
static void AQ_Notify(pAsyncQueue self, int event)
{
pAsyncUnit unit;
- if (self->state != eAsyncConnected)
- SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name, __func__);
for (unit = self->units; unit; unit = unit->next)
if (unit->notify_func != NULL)
unit->notify_func(unit->notify_cntx, event);
}
-static int TimedReconnect(void* cntx, int mode)
-{
- int iRet;
- char line[132];
- pAsyncQueue self = (pAsyncQueue) cntx;
-
- if (self->state != eAsyncConnected)
- SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name, __func__);
- iRet = NETReconnect(self->pSock);
- /*
- * iRet can take the following values:
- * -1: The request failed
- * 0: The request is still in progress
- * +1: The request succeeded
- */
- if (iRet < 0) {
- snprintf(line, 132, "Failed reconnect on AsyncQueue '%s'", self->queue_name);
- SICSLogWrite(line, eStatus);
- NetWatchSetMode(self->nw_ctx, 0);
- /* implement an exponential backoff within limits */
- self->retryTimer = 2 * self->retryTimer;
- if (self->retryTimer < 250)
- self->retryTimer = 250;
- if (self->retryTimer > 30000)
- self->retryTimer = 30000;
- NetWatchRegisterTimer(&self->nw_tmr, self->retryTimer, TimedReconnect, self);
- SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncWaiting\n", self->queue_name, __func__, state_name(self->state));
- self->state = eAsyncWaiting;
- }
- else if (iRet == 0) {
- snprintf(line, 132, "Inprogress reconnect on AsyncQueue '%s'", self->queue_name);
- NetWatchSetMode(self->nw_ctx, nwatch_write);
- SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnecting\n", self->queue_name, __func__, state_name(self->state));
- self->state = eAsyncConnecting;
- }
- else {
- snprintf(line, 132, "Reconnect on AsyncQueue '%s'", self->queue_name);
- SICSLogWrite(line, eStatus);
- AQ_Notify(self, AQU_RECONNECT);
- NetWatchSetMode(self->nw_ctx, nwatch_read);
- SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnected\n", self->queue_name, __func__, state_name(self->state));
- self->state = eAsyncConnected;
- }
- return 1;
-}
-
static int AQ_Reconnect(pAsyncQueue self)
{
int iRet;
@@ -187,61 +114,28 @@ static int AQ_Reconnect(pAsyncQueue self)
int flag = 1;
char line[132];
- if (self->state != eAsyncConnected)
- SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name, __func__);
- /*
- * Remove any old timer
- */
- if (self->nw_tmr)
- NetWatchRemoveTimer(self->nw_tmr);
-
iRet = NETReconnect(self->pSock);
- /*
- * iRet can take the following values:
- * -1: The request failed
- * 0: The request is still in progress
- * +1: The request succeeded
- */
if (iRet <= 0) {
snprintf(line, 132, "Disconnect on AsyncQueue '%s'", self->queue_name);
SICSLogWrite(line, eStatus);
AQ_Notify(self, AQU_DISCONNECT);
- if (iRet < 0) {
- /* TODO Timer for retry */
- NetWatchSetMode(self->nw_ctx, 0);
- self->retryTimer = 125; /* initial delay */
- NetWatchRegisterTimer(&self->nw_tmr, self->retryTimer, TimedReconnect, self);
- SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncWaiting\n", self->queue_name, __func__, state_name(self->state));
- self->state = eAsyncWaiting;
- }
- else {
- NetWatchSetMode(self->nw_ctx, nwatch_write);
- SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnecting\n", self->queue_name, __func__, state_name(self->state));
- self->state = eAsyncConnecting;
- /* TODO await reconnect result */
- }
return iRet;
}
- SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnected\n", self->queue_name, __func__, state_name(self->state));
- self->state = eAsyncConnected;
snprintf(line, 132, "Reconnect on AsyncQueue '%s'", self->queue_name);
SICSLogWrite(line, eStatus);
AQ_Notify(self, AQU_RECONNECT);
return 1;
}
+static int CommandTimeout(void *cntx, int mode);
+static int DelayedStart(void *cntx, int mode);
static int PopCommand(pAsyncQueue self);
-static int CommandTimeout(void* cntx, int mode);
-static int DelayedStart(void* cntx, int mode);
static int StartCommand(pAsyncQueue self)
{
pAQ_Cmd myCmd = self->command_head;
- mkChannel* sock = self->pSock;
- int iRet = 0;
+ mkChannel *sock = self->pSock;
- if (self->state != eAsyncConnected)
- SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name, __func__);
if (myCmd == NULL)
return OKOK;
@@ -270,8 +164,7 @@ static int StartCommand(pAsyncQueue self)
int delay = when.tv_sec - now.tv_sec;
delay *= 1000;
delay += (when.tv_usec - now.tv_usec + (1000 - 1)) / 1000;
- NetWatchRegisterTimer(&self->nw_tmr, delay,
- DelayedStart, self);
+ NetWatchRegisterTimer(&self->nw_tmr, delay, DelayedStart, self);
return OKOK;
}
}
@@ -279,44 +172,33 @@ static int StartCommand(pAsyncQueue self)
/*
* Discard any input before sending command
*/
- if (NETAvailable(sock, 0)) {
- while (NETAvailable(sock, 0)) {
- /* TODO: handle unsolicited input */
- char reply[128];
- iRet = NETRead(sock, reply, 128, 0);
- if (iRet < 0) { /* EOF */
- iRet = AQ_Reconnect(self);
- if (iRet == 0)
- return 0;
- }
- else if (iRet > 0) {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- SICSLogTimePrintf(eError, &tv, "ERROR: %d unsolicited chars in AsyncQueue %s", iRet, self->queue_name);
- SICSLogWriteHexTime(reply, iRet, eError, &tv);
+ while (NETAvailable(sock, 0)) {
+ /* TODO: handle unsolicited input */
+ char reply[1];
+ int iRet;
+ iRet = NETRead(sock, reply, 1, 0);
+ if (iRet < 0) { /* EOF */
+ iRet = AQ_Reconnect(self);
+ if (iRet <= 0) {
+ myCmd->tran->txn_state = ATX_DISCO;
+ if (myCmd->tran->handleResponse) {
+ myCmd->tran->handleResponse(myCmd->tran);
+ }
+ PopCommand(self);
+ return 0;
}
}
}
-
- myCmd->tran->txn_status = ATX_ACTIVE;
- iRet = self->protocol->sendCommand(self->protocol, myCmd->tran);
- /*
- * Handle case of no response expected
- */
- if (iRet > 0)
- if (myCmd->tran->txn_status == ATX_COMPLETE)
- return PopCommand(self);
/*
* Add a new command timeout timer
*/
if (myCmd->timeout > 0)
NetWatchRegisterTimer(&self->nw_tmr, myCmd->timeout,
- CommandTimeout, self);
+ CommandTimeout, self);
else
- NetWatchRegisterTimer(&self->nw_tmr, 30000,
- CommandTimeout, self);
+ NetWatchRegisterTimer(&self->nw_tmr, 30000, CommandTimeout, self);
myCmd->active = 1;
- return iRet;
+ return self->protocol->sendCommand(self->protocol, myCmd->tran);
}
static int QueCommandHead(pAsyncQueue self, pAQ_Cmd cmd)
@@ -333,8 +215,7 @@ static int QueCommandHead(pAsyncQueue self, pAQ_Cmd cmd)
if (self->command_head->active) {
cmd->next = self->command_head->next;
self->command_head->next = cmd;
- }
- else {
+ } else {
cmd->next = self->command_head;
self->command_head = cmd;
}
@@ -358,7 +239,6 @@ static int QueCommand(pAsyncQueue self, pAQ_Cmd cmd)
self->command_tail = cmd;
return 1;
}
-
static int PopCommand(pAsyncQueue self)
{
pAQ_Cmd myCmd = self->command_head;
@@ -366,9 +246,6 @@ static int PopCommand(pAsyncQueue self)
NetWatchRemoveTimer(self->nw_tmr);
self->nw_tmr = 0;
gettimeofday(&self->tvLastCmd, NULL);
- /* Process any callback */
- if (myCmd->tran->handleResponse)
- myCmd->tran->handleResponse(myCmd->tran);
/*
* If this is not the last in queue, start transmission
*/
@@ -376,8 +253,7 @@ static int PopCommand(pAsyncQueue self)
pAQ_Cmd pNew = myCmd->next;
self->command_head = pNew;
StartCommand(self);
- }
- else
+ } else
self->command_head = self->command_tail = NULL;
free(myCmd->tran->out_buf);
free(myCmd->tran->inp_buf);
@@ -386,7 +262,7 @@ static int PopCommand(pAsyncQueue self)
return 1;
}
-static int CommandTimeout(void* cntx, int mode)
+static int CommandTimeout(void *cntx, int mode)
{
pAsyncQueue self = (pAsyncQueue) cntx;
pAQ_Cmd myCmd = self->command_head;
@@ -394,95 +270,79 @@ static int CommandTimeout(void* cntx, int mode)
if (myCmd->retries > 0) {
--myCmd->retries;
StartCommand(self);
- }
- else {
+ } else {
int iRet;
- iRet = self->protocol->handleEvent(self->protocol, myCmd->tran, AQU_TIMEOUT);
+ iRet =
+ self->protocol->handleEvent(self->protocol, myCmd->tran,
+ AQU_TIMEOUT);
if (iRet == AQU_POP_CMD) {
- PopCommand(self); /* remove command */
- }
- else if (iRet == AQU_RETRY_CMD)
- StartCommand(self); /* restart command */
+ if (myCmd->tran->handleResponse)
+ myCmd->tran->handleResponse(myCmd->tran);
+ PopCommand(self); /* remove command */
+ } else if (iRet == AQU_RETRY_CMD)
+ StartCommand(self); /* restart command */
else if (iRet == AQU_RECONNECT)
AQ_Reconnect(self);
}
return 1;
}
-static int DelayedStart(void* cntx, int mode)
+static int DelayedStart(void *cntx, int mode)
{
pAsyncQueue self = (pAsyncQueue) cntx;
- if (self->state != eAsyncConnected)
- SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name, __func__);
self->nw_tmr = 0;
StartCommand(self);
return 1;
}
-static int MyCallback(void* context, int mode)
+static int MyCallback(void *context, int mode)
{
pAsyncQueue self = (pAsyncQueue) context;
- if (self->state != eAsyncConnected)
- SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name, __func__);
if (mode & nwatch_read) {
int iRet;
- char reply[100];
+ char reply[1];
- iRet = NETRead(self->pSock, reply, 100, 0);
- if (iRet < 0) { /* EOF */
+ iRet = NETRead(self->pSock, reply, 1, 0);
+ /* printf(" iRet, char = %d, %d\n", iRet, (int)reply[0]); */
+ if (iRet < 0) { /* EOF */
iRet = AQ_Reconnect(self);
- if (iRet <= 0)
+ if (iRet <= 0) {
+ /* changed to call handleResponse with a bad status code: MK
+ */
+ pAQ_Cmd myCmd = self->command_head;
+ if (myCmd) {
+ myCmd->tran->txn_state = ATX_DISCO;
+ if (myCmd->tran->handleResponse) {
+ myCmd->tran->handleResponse(myCmd->tran);
+ }
+ PopCommand(self);
+ }
return iRet;
+ }
/* restart the command */
StartCommand(self);
return 1;
}
- if (iRet == 0) { /* TODO: timeout or error */
+ if (iRet == 0) { /* TODO: timeout or error */
return 0;
} else {
- int nchars = iRet;
- int i = 0;
pAQ_Cmd myCmd = self->command_head;
if (myCmd) {
- for (i = 0; i < nchars; ++i) {
- iRet = self->protocol->handleInput(self->protocol, myCmd->tran, reply[i]);
- if (iRet == 0 || iRet == AQU_POP_CMD) { /* end of command */
- PopCommand(self);
- break;
- }
- else if (iRet < 0) {
- SICSLogWrite("ERROR: Protocol error in AsyncQueue", eError);
- /* TODO: error */
- break;
- }
- }
- if (i < nchars - 1) {
- int excess = nchars - 1 - i;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- SICSLogTimePrintf(eError, &tv, "ERROR: %d excess chars in AsyncQueue %s", excess, self->queue_name);
- SICSLogWriteHexTime(&reply[i], excess, eError, &tv);
- /* TODO: handle unsolicited */
- }
- }
- else {
- int excess = nchars - 1 - i;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- SICSLogTimePrintf(eError, &tv, "ERROR: %d unsolicited chars in AsyncQueue %s", excess, self->queue_name);
- SICSLogWriteHexTime(&reply[i], excess, eError, &tv);
- /* TODO: handle unsolicited input */
+ iRet =
+ self->protocol->handleInput(self->protocol, myCmd->tran,
+ reply[0]);
+ if (iRet == 0 || iRet == AQU_POP_CMD) { /* end of command */
+ if (myCmd->tran->handleResponse)
+ myCmd->tran->handleResponse(myCmd->tran);
+ PopCommand(self);
+ } else if (iRet < 0) /* TODO: error */
+ ;
+ } else {
+ /* TODO: handle unsolicited input */
}
}
}
- if (mode & nwatch_write) {
- char line[132];
- SICSLogPrintf(eStatus, "Writeable socket callback on AsyncQueue %s", self->queue_name);
- NetWatchSetMode(self->nw_ctx, nwatch_read);
- SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnected\n", self->queue_name, __func__, state_name(self->state));
- self->state = eAsyncConnected;
- }
return 1;
}
@@ -525,9 +385,9 @@ int AsyncUnitEnqueueTxn(pAsyncUnit unit, pAsyncTxn pTxn)
}
pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
- const char* command, int cmd_len,
- AsyncTxnHandler callback, void* context,
- int rsp_len)
+ const char *command, int cmd_len,
+ AsyncTxnHandler callback, void *context,
+ int rsp_len)
{
pAsyncTxn myTxn = NULL;
@@ -535,23 +395,20 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
myTxn = (pAsyncTxn) malloc(sizeof(AsyncTxn));
if (myTxn == NULL) {
SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError);
- return NULL;
+ return 0;
}
memset(myTxn, 0, sizeof(AsyncTxn));
if (unit->queue->protocol->prepareTxn) {
int iRet;
- iRet = unit->queue->protocol->prepareTxn(unit->queue->protocol, myTxn, command, cmd_len, rsp_len);
- if (iRet == 0) {
- free(myTxn);
- return NULL;
- }
- }
- else {
- myTxn->out_buf = (char*) malloc(cmd_len + 5);
+ iRet =
+ unit->queue->protocol->prepareTxn(unit->queue->protocol, myTxn,
+ command, cmd_len, rsp_len);
+ } else {
+ myTxn->out_buf = (char *) malloc(cmd_len + 5);
if (myTxn->out_buf == NULL) {
SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError);
free(myTxn);
- return NULL;
+ return 0;
}
memcpy(myTxn->out_buf, command, cmd_len);
myTxn->out_len = cmd_len;
@@ -566,12 +423,15 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
if (rsp_len == 0)
myTxn->inp_buf = NULL;
else {
+ if (myTxn->inp_buf != NULL) {
+ free(myTxn->inp_buf);
+ }
myTxn->inp_buf = malloc(rsp_len + 1);
if (myTxn->inp_buf == NULL) {
SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError);
free(myTxn->out_buf);
free(myTxn);
- return NULL;
+ return 0;
}
memset(myTxn->inp_buf, 0, rsp_len + 1);
}
@@ -583,13 +443,12 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
}
int AsyncUnitSendTxn(pAsyncUnit unit,
- const char* command, int cmd_len,
- AsyncTxnHandler callback, void* context,
- int rsp_len)
+ const char *command, int cmd_len,
+ AsyncTxnHandler callback, void *context, int rsp_len)
{
pAsyncTxn myTxn = NULL;
myTxn = AsyncUnitPrepareTxn(unit, command, cmd_len,
- callback, context, rsp_len);
+ callback, context, rsp_len);
if (myTxn == NULL)
return -1;
return AsyncUnitEnqueueTxn(unit, myTxn);
@@ -597,66 +456,59 @@ int AsyncUnitSendTxn(pAsyncUnit unit,
typedef struct txn_s {
- char* transReply;
+ char *transReply;
int transWait;
- int respLen;
} TXN, *pTXN;
/**
* \brief TransCallback is the callback for the general command transaction.
*/
-static int TransCallback(pAsyncTxn pCmd) {
- char* resp = pCmd->inp_buf;
+static int TransCallback(pAsyncTxn pCmd)
+{
+ char *resp = pCmd->inp_buf;
int resp_len = pCmd->inp_idx;
pTXN self = (pTXN) pCmd->cntx;
- self->respLen = resp_len;
- if (resp_len > 0) {
+ if (pCmd->txn_status == ATX_TIMEOUT) {
memcpy(self->transReply, resp, resp_len);
self->transReply[resp_len] = '\0';
- }
- else
self->transReply[0] = '\0';
-
- if (pCmd->txn_status == ATX_TIMEOUT)
self->transWait = -1;
- else
+ } else {
+ memcpy(self->transReply, resp, resp_len);
+ self->transReply[resp_len] = '\0';
self->transWait = 0;
-
+ }
return 0;
}
int AsyncUnitTransact(pAsyncUnit unit,
- const char* command, int cmd_len,
- char* response, int *rsp_len)
+ const char *command, int cmd_len,
+ char *response, int rsp_len)
{
TXN txn;
assert(unit);
txn.transReply = response;
- txn.respLen = *rsp_len;
txn.transWait = 1;
- AsyncUnitSendTxn(unit,
- command, cmd_len,
- TransCallback, &txn, *rsp_len);
+ AsyncUnitSendTxn(unit, command, cmd_len, TransCallback, &txn, rsp_len);
while (txn.transWait == 1)
TaskYield(pServ->pTasker);
- *rsp_len = txn.respLen;
if (txn.transWait < 0)
return txn.transWait;
return 1;
}
-int AsyncUnitWrite(pAsyncUnit unit, void* buffer, int buflen)
+int AsyncUnitWrite(pAsyncUnit unit, void *buffer, int buflen)
{
int iRet;
- mkChannel* sock;
+ mkChannel *sock;
assert(unit);
assert(unit->queue);
if (buflen > 0) {
sock = AsyncUnitGetSocket(unit);
iRet = NETWrite(sock, buffer, buflen);
/* TODO handle errors */
- if (iRet < 0) { /* EOF */
+ if (iRet < 0) { /* EOF */
iRet = AQ_Reconnect(unit->queue);
if (iRet == 0)
return 0;
@@ -665,7 +517,7 @@ int AsyncUnitWrite(pAsyncUnit unit, void* buffer, int buflen)
return 1;
}
-void AsyncUnitSetNotify(pAsyncUnit unit, void* context, AQU_Notify notify)
+void AsyncUnitSetNotify(pAsyncUnit unit, void *context, AQU_Notify notify)
{
assert(unit);
unit->notify_func = notify;
@@ -718,7 +570,7 @@ void AsyncUnitSetProtocol(pAsyncUnit unit, pAsyncProtocol protocol)
unit->queue->protocol = protocol;
}
-mkChannel* AsyncUnitGetSocket(pAsyncUnit unit)
+mkChannel *AsyncUnitGetSocket(pAsyncUnit unit)
{
assert(unit);
assert(unit->queue);
@@ -735,8 +587,8 @@ int AsyncUnitReconnect(pAsyncUnit unit)
return iRet;
}
-int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
- void *pData, int argc, char *argv[])
+int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[])
{
char line[132];
pAsyncQueue self = (pAsyncQueue) pData;
@@ -746,75 +598,19 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
char cmd[10240];
char rsp[10240];
int idx = 0;
- int i, j, len;
+ int i, j;
cmd[0] = '\0';
- /* Managers only */
- if (!SCMatchRights(pCon, usMugger))
- return 0;
for (i = 2; i < argc; ++i) {
- if (idx >= 10240)
+ j = snprintf(&cmd[idx], 10240 - idx, "%s%s",
+ (i > 2) ? " " : "", argv[i]);
+ if (j < 0)
break;
- if (i > 2)
- cmd[idx++] = ' ';
- len = strlen(argv[i]);
- for (j = 0; j < len; ++j) {
- if (idx >= 10240)
- break;
- if (argv[i][j] == '\\') {
- ++j;
- if (argv[i][j] == '\\')
- cmd[idx++] = '\\';
- else if (argv[i][j] == 'r')
- cmd[idx++] = '\r';
- else if (argv[i][j] == 'n')
- cmd[idx++] = '\n';
- else if (isdigit(argv[i][j])) {
- char* nptr = &argv[i][j];
- char* endptr;
- long k = strtol(nptr, &endptr, 0);
- cmd[idx++] = k;
- j += (endptr - nptr);
- --j; /* prepare for loop increment */
- } else
- cmd[idx++] = argv[i][j];
- } else
- cmd[idx++] = argv[i][j];
- }
+ idx += j;
}
- cmd[idx] = '\0';
memset(&myUnit, 0, sizeof(AsyncUnit));
myUnit.queue = self;
- len = 10240;
- (void) AsyncUnitTransact(&myUnit, cmd, idx, rsp, &len);
- /* escape control characters in response */
- j = 0;
- for (i = 0; i < len; ++i) {
- if (j >= 10230)
- break;
- if (self->translate) {
- if (rsp[i] < 32 || rsp[i] >= 127) {
- if (rsp[i] == '\r') {
- cmd[j++] = '\r';
- }
- else if (rsp[i] == '\n') {
- cmd[j++] = '\n';
- }
- else {
- j += snprintf(&cmd[j], 6, "\\0x%02x", rsp[i]);
- }
- }
- else if (rsp[i] == '\\') {
- cmd[j++] = '\\';
- cmd[j++] = '\\';
- }
- else
- cmd[j++] = rsp[i];
- }
- else
- cmd[j++] = rsp[i];
- }
- cmd[j++] = '\0';
- SCWrite(pCon, cmd, eValue);
+ AsyncUnitTransact(&myUnit, cmd, idx, rsp, 10240);
+ SCWrite(pCon, rsp, eValue);
return 1;
}
if (strcasecmp(argv[1], "reconnect") == 0) {
@@ -830,9 +626,8 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
snprintf(line, 132, "Invalid argument: %s", argv[2]);
SCWrite(pCon, line, eError);
return 0;
- }
- else {
- if (delay < 0 || delay > 300000) {
+ } else {
+ if (delay < 0 || delay > 30000) {
snprintf(line, 132, "Value out of range: %d", delay);
SCWrite(pCon, line, eError);
return 0;
@@ -840,10 +635,9 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
self->iDelay = delay;
return OKOK;
}
- }
- else {
+ } else {
snprintf(line, 132, "%s.delay = %d", argv[0], self->iDelay);
- SCWrite(pCon, line, eStatus);
+ SCWrite(pCon, line, eValue);
return OKOK;
}
return OKOK;
@@ -857,8 +651,7 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
snprintf(line, 132, "Invalid argument: %s", argv[2]);
SCWrite(pCon, line, eError);
return 0;
- }
- else {
+ } else {
if (timeout < 0 || timeout > 30000) {
snprintf(line, 132, "Value out of range: %d", timeout);
SCWrite(pCon, line, eError);
@@ -867,10 +660,9 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
self->timeout = timeout;
return OKOK;
}
- }
- else {
+ } else {
snprintf(line, 132, "%s.timeout = %d", argv[0], self->timeout);
- SCWrite(pCon, line, eStatus);
+ SCWrite(pCon, line, eValue);
return OKOK;
}
return OKOK;
@@ -884,8 +676,7 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
snprintf(line, 132, "Invalid argument: %s", argv[2]);
SCWrite(pCon, line, eError);
return 0;
- }
- else {
+ } else {
if (retries < 0 || retries > 30000) {
snprintf(line, 132, "Value out of range: %d", retries);
SCWrite(pCon, line, eError);
@@ -894,41 +685,9 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
self->retries = retries;
return OKOK;
}
- }
- else {
+ } else {
snprintf(line, 132, "%s.retries = %d", argv[0], self->retries);
- SCWrite(pCon, line, eStatus);
- return OKOK;
- }
- return OKOK;
- }
- if (strcasecmp(argv[1], "translate") == 0) {
- if (argc > 2) {
- int value;
- int iRet;
- iRet = sscanf(argv[2], "%d", &value);
- if (iRet != 1) {
- snprintf(line, 132, "Invalid argument: %s", argv[2]);
- SCWrite(pCon, line, eError);
- return 0;
- }
- else {
- if (value == 0) {
- self->translate = false;
- return OKOK;
- }
- else if (value == 1) {
- self->translate = true;
- return OKOK;
- }
- snprintf(line, 132, "Invalid argument: %s", argv[2]);
- SCWrite(pCon, line, eError);
- return 0;
- }
- }
- else {
- snprintf(line, 132, "%s.translate = %d", argv[0], self->translate);
- SCWrite(pCon, line, eStatus);
+ SCWrite(pCon, line, eValue);
return OKOK;
}
return OKOK;
@@ -939,40 +698,43 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
return 0;
}
-static pAsyncQueue AQ_Create(const char* host, const char* port)
+static pAsyncQueue AQ_Create(const char *host, const char *port)
{
int i;
pAsyncQueue self = NULL;
- mkChannel* channel = NULL;
+ mkChannel *channel = NULL;
if (host == NULL)
return NULL;
/* try the AsyncQueue with this name */
- self = (pAsyncQueue) FindCommandData(pServ->pSics, (char*) host, "AsyncQueue");
+ self =
+ (pAsyncQueue) FindCommandData(pServ->pSics, (char *) host,
+ "AsyncQueue");
/* try host and port */
if (self == NULL && port) {
int port_no = atoi(port);
if (port_no == 0) {
- struct servent *sp=NULL;
+ struct servent *sp = NULL;
sp = getservbyname(port, NULL);
if (sp)
port_no = ntohs(sp->s_port);
}
if (port_no > 0) {
struct sockaddr_in sa;
- if (CreateSocketAdress(&sa, (char *)host, port_no)) {
+ if (CreateSocketAdress(&sa, (char *) host, port_no)) {
/* look for queue with same address */
for (i = 0; i < queue_index; ++i)
if (queue_array[i]->pSock->adresse.sin_port == sa.sin_port
- && queue_array[i]->pSock->adresse.sin_addr.s_addr == sa.sin_addr.s_addr) {
+ && queue_array[i]->pSock->adresse.sin_addr.s_addr ==
+ sa.sin_addr.s_addr) {
self = queue_array[i];
break;
}
}
if (self == NULL) {
- channel = NETConnectWithFlags((char *)host, port_no, 0);
+ channel = NETConnectWithFlags((char *) host, port_no, 0);
/* TODO handle asynchronous connection */
}
}
@@ -1006,14 +768,11 @@ static int AQ_Init(pAsyncQueue self)
/* Init the controller */
if (self->nw_ctx == NULL)
NetWatchRegisterCallback(&self->nw_ctx,
- self->pSock->sockid,
- MyCallback,
- self);
- NetWatchSetMode(self->nw_ctx, nwatch_write | nwatch_read);
+ self->pSock->sockid, MyCallback, self);
return 1;
}
-static void AQ_Kill(void* pData)
+static void AQ_Kill(void *pData)
{
int i;
pAsyncQueue self = (pAsyncQueue) pData;
@@ -1041,42 +800,48 @@ static void AQ_Kill(void* pData)
*
* MakeAsyncQueue queueName protocolName hostName portname
*/
-int AsyncQueueFactory(SConnection *pCon, SicsInterp *pSics,
- void *pData, int argc, char *argv[])
+int AsyncQueueFactory(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[])
{
pAsyncQueue pNew = NULL;
- mkChannel* channel = NULL;
+ mkChannel *channel = NULL;
pAsyncProtocol pPro = NULL;
int port_no;
int iRet = 0;
if (argc < 5) {
- SCWrite(pCon,"ERROR: insufficient arguments to AsyncQueueFactory", eError);
+ SCWrite(pCon, "ERROR: insufficient arguments to AsyncQueueFactory",
+ eError);
return 0;
}
/* try to find an existing queue with this name */
- pNew = (pAsyncQueue) FindCommandData(pServ->pSics, argv[1], "AsyncQueue");
+ pNew =
+ (pAsyncQueue) FindCommandData(pServ->pSics, argv[1], "AsyncQueue");
if (pNew != NULL) {
char line[132];
- snprintf(line, 132, "WARNING: AsyncQueue '%s' already exists", argv[1]);
+ snprintf(line, 132, "WARNING: AsyncQueue '%s' already exists",
+ argv[1]);
SCWrite(pCon, line, eError);
SCSendOK(pCon);
return 1;
}
/* try to find an existing protocol with this name */
- pPro = (pAsyncProtocol) FindCommandData(pServ->pSics, argv[2], "AsyncProtocol");
+ pPro =
+ (pAsyncProtocol) FindCommandData(pServ->pSics, argv[2],
+ "AsyncProtocol");
if (pPro == NULL) {
char line[132];
- snprintf(line, 132, "WARNING: AsyncQueue protocol '%s' not found", argv[2]);
+ snprintf(line, 132, "WARNING: AsyncQueue protocol '%s' not found",
+ argv[2]);
SCWrite(pCon, line, eError);
return 0;
}
port_no = atoi(argv[4]);
if (port_no == 0) {
- struct servent *sp=NULL;
+ struct servent *sp = NULL;
sp = getservbyname(argv[4], NULL);
if (sp)
port_no = ntohs(sp->s_port);
@@ -1088,17 +853,18 @@ int AsyncQueueFactory(SConnection *pCon, SicsInterp *pSics,
/* look for queue with same address */
for (i = 0; i < queue_index; ++i)
if (queue_array[i]->pSock->adresse.sin_port == sa.sin_port
- && queue_array[i]->pSock->adresse.sin_addr.s_addr == sa.sin_addr.s_addr) {
+ && queue_array[i]->pSock->adresse.sin_addr.s_addr ==
+ sa.sin_addr.s_addr) {
char line[132];
- snprintf(line, 132, "WARNING: AsyncQueue '%s' has same address as %s",
- argv[1],
- queue_array[i]->queue_name);
+ snprintf(line, 132,
+ "WARNING: AsyncQueue '%s' has same address as %s",
+ argv[1], queue_array[i]->queue_name);
SCWrite(pCon, line, eError);
}
- }
+ }
/* TODO: implement asynchronous connection */
channel = NETConnectWithFlags(argv[3], port_no, 0);
- }
+ }
if (channel == NULL) {
char line[132];
@@ -1123,13 +889,12 @@ int AsyncQueueFactory(SConnection *pCon, SicsInterp *pSics,
queue_array[queue_index++] = pNew;
AQ_Init(pNew);
-
+
/*
- create the command
- */
+ create the command
+ */
iRet = AddCommand(pSics, argv[1], AsyncQueueAction, AQ_Kill, pNew);
- if(!iRet)
- {
+ if (!iRet) {
char line[132];
snprintf(line, 123, "ERROR: add command %s failed", argv[1]);
SCWrite(pCon, line, eError);
@@ -1147,7 +912,8 @@ int AsyncQueueFactory(SConnection *pCon, SicsInterp *pSics,
* \param handle the handle to the AsyncQueue object
* \return 0 for FAILURE, 1 for SUCCESS
*/
-int AsyncUnitCreateHost(const char* host, const char* port, pAsyncUnit* handle)
+int AsyncUnitCreateHost(const char *host, const char *port,
+ pAsyncUnit * handle)
{
int status;
pAsyncQueue self = NULL;
@@ -1175,7 +941,8 @@ int AsyncUnitCreateHost(const char* host, const char* port, pAsyncUnit* handle)
return 1;
}
-int AsyncUnitCreate(const char* host, pAsyncUnit* handle) {
+int AsyncUnitCreate(const char *host, pAsyncUnit * handle)
+{
return AsyncUnitCreateHost(host, NULL, handle);
}
@@ -1184,7 +951,7 @@ int AsyncUnitDestroy(pAsyncUnit unit)
assert(unit);
assert(unit->queue);
pAsyncQueue self = unit->queue;
- pAsyncUnit* pNxt = &self->units;
+ pAsyncUnit *pNxt = &self->units;
while (*pNxt) {
if (*pNxt == unit) {
*pNxt = (*pNxt)->next;
@@ -1200,30 +967,15 @@ int AsyncUnitDestroy(pAsyncUnit unit)
return 1;
}
-pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue){
- pAsyncUnit result = NULL;
-
- result = malloc(sizeof(AsyncUnit));
- if(result == NULL){
- return NULL;
- }
- memset(result,0,sizeof(AsyncUnit));
- result->queue = queue;
- return result;
-}
+pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue)
+{
+ pAsyncUnit result = NULL;
-void* AsyncUnitSetQueueContext(pAsyncUnit unit, void* cntx) {
- void* hold;
- assert(unit);
- assert(unit->queue);
- hold = unit->queue->context;
- unit->queue->context = cntx;
- return hold;
+ result = malloc(sizeof(AsyncUnit));
+ if (result == NULL) {
+ return NULL;
+ }
+ memset(result, 0, sizeof(AsyncUnit));
+ result->queue = queue;
+ return result;
}
-
-void* AsyncUnitGetQueueContext(pAsyncUnit unit) {
- assert(unit);
- assert(unit->queue);
- return unit->queue->context;
-}
-
diff --git a/asyncqueue.h b/asyncqueue.h
index d91cdda2..2359d575 100644
--- a/asyncqueue.h
+++ b/asyncqueue.h
@@ -26,9 +26,9 @@ typedef struct __AsyncQueue AsyncQueue, *pAsyncQueue;
* \param unit pointer to the AsyncUnit created on positive return
* \return positive if successful
*/
-int AsyncUnitCreate(const char* queueName, pAsyncUnit* unit);
+int AsyncUnitCreate(const char *queueName, pAsyncUnit * unit);
/** \brief Get an AsyncUnit from a given AsyncQueue
- * \param queue The AsyncQueue for which this AsyncUnit is valid
+ * \param queue The AsyncQueue fro which this AsyncUnit is valid
* \return a new AsyncUnit or NULL on error
*/
pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue);
@@ -39,14 +39,9 @@ pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue);
* \param port number or service name on the target host
* \param unit pointer to the AsyncUnit created on positive return
* \return positive if successful
- *
- * If is null then points to an existing queue name.
- * If a queue exists for /, then that queue is used.
- * If neither of the above hold, a new queue is created.
*/
-int AsyncUnitCreateHost(const char* host,
- const char* port,
- pAsyncUnit* unit);
+int AsyncUnitCreateHost(const char *host,
+ const char *port, pAsyncUnit * unit);
/** \brief destroys an AsyncUnit
*
@@ -78,9 +73,9 @@ int AsyncUnitEnqueueTxn(pAsyncUnit unit, pAsyncTxn pTxn);
* \param resp_len maximum length to be allowed for response
*/
pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
- const char* command, int cmd_len,
- AsyncTxnHandler responseHandler, void* context,
- int rsp_len);
+ const char *command, int cmd_len,
+ AsyncTxnHandler responseHandler,
+ void *context, int rsp_len);
/** \brief prepare and queue a transaction
*
@@ -92,9 +87,9 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
* \param resp_len maximum length to be allowed for response
*/
int AsyncUnitSendTxn(pAsyncUnit unit,
- const char* command, int cmd_len,
- AsyncTxnHandler responseHandler, void* context,
- int rsp_len);
+ const char *command, int cmd_len,
+ AsyncTxnHandler responseHandler, void *context,
+ int rsp_len);
/** \brief send a transaction and wait for the response
*
@@ -103,12 +98,11 @@ int AsyncUnitSendTxn(pAsyncUnit unit,
* \param cmd_len length of data in command
* \param responseHandler function to handle the response
* \param context to be used by handler function
- * \param resp_len [in] maximum length to be allowed for response
- * [out] actual length returned
+ * \param resp_len maximum length to be allowed for response
*/
int AsyncUnitTransact(pAsyncUnit unit,
- const char* command, int cmd_len,
- char* response, int *rsp_len);
+ const char *command, int cmd_len,
+ char *response, int rsp_len);
/** \brief write to the AsyncQueue file descriptor
*
@@ -120,7 +114,7 @@ int AsyncUnitTransact(pAsyncUnit unit,
* \param data to be transmitted
* \param buflen lenght of data
*/
-int AsyncUnitWrite(pAsyncUnit unit, void* buffer, int buflen);
+int AsyncUnitWrite(pAsyncUnit unit, void *buffer, int buflen);
/** \brief registers a notification callback
*
@@ -130,8 +124,8 @@ int AsyncUnitWrite(pAsyncUnit unit, void* buffer, int buflen);
* \param context passed in callback
* \param notify function to be called
*/
-typedef void (*AQU_Notify)(void* context, int event);
-void AsyncUnitSetNotify(pAsyncUnit unit, void* context, AQU_Notify notify);
+typedef void (*AQU_Notify) (void *context, int event);
+void AsyncUnitSetNotify(pAsyncUnit unit, void *context, AQU_Notify notify);
/** \brief get the intertransaction delay in milliseconds
*/
@@ -170,7 +164,7 @@ void AsyncUnitSetProtocol(pAsyncUnit unit, pAsyncProtocol protocol);
* \param unit AsyncUnit
* \return channel or NULL
*/
-mkChannel* AsyncUnitGetSocket(pAsyncUnit unit);
+mkChannel *AsyncUnitGetSocket(pAsyncUnit unit);
/** \brief attempt to reconnect the socket of the associated AsyncQueue
*
@@ -180,20 +174,12 @@ int AsyncUnitReconnect(pAsyncUnit handle);
/** \brief create an AsyncQueue from the SICS command MakeAsyncQueue
*/
-int AsyncQueueFactory(SConnection *pCon, SicsInterp *pSics,
- void *pData, int argc, char *argv[]);
+int AsyncQueueFactory(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[]);
/** \brief SICS command handler for the AsyncQueue object
*/
-int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
- void *pData, int argc, char *argv[]);
+int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[]);
-/** \brief store queue level context
- */
-void* AsyncUnitSetQueueContext(pAsyncUnit handle, void* cntx);
-
-/** \brief retrieve queue level context
- */
-void* AsyncUnitGetQueueContext(pAsyncUnit handle);
-
-#endif /* SICSASYNCQUEUE */
+#endif /* SICSASYNCQUEUE */
diff --git a/asynnet.c b/asynnet.c
new file mode 100644
index 00000000..d59c854d
--- /dev/null
+++ b/asynnet.c
@@ -0,0 +1,628 @@
+/**
+ * Asynchronous networking for SICS and other programs. This module centrally manages
+ * a number of network connections for a client program. It is a layer between the
+ * program and the network which manages non blocking network I/O. To this purpose, the
+ * client program has to call ANETprocess at convenient intervalls. This module
+ * has a couple of features:
+ * - Connections are abstracted to handles which are guranteed to be unique
+ * rather then socket numbers. Socket numbers may be reused by the OS.
+ * - This module allows upper level code to figure out if a connection is still
+ * connected or not.
+ * - This module introduces a buffer layer between the socket and the application.
+ * Thus the upper layer does not have to worry much about I/O blocking. This
+ * is taken care of by this module both for reading and writing.
+ * - All I/O is non blocking.
+ * - This module can detect if a client is hanging and close the connection then.
+ * Hanging is detected by not being able to write to the client for some period
+ * of time.
+ *
+ * copyright: see file COPYRIGHT
+ *
+ * Mark Koennecke, January 2009
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "asynnet.h"
+#include "rwpuffer.h"
+
+/*--------------------------------------------------------------------------*/
+#define SERVERSOCKET 0
+#define DATASOCKET 1
+#define MAXCONNECTIONS 1024
+#define RBUFFERSIZE 262144 /* 256kb */
+#define WBUFFERSIZE 20*262144
+/* #define WBUFFERSIZE 100*262144 /*
+/*--------------------------------------------------------------------------*/
+typedef struct {
+ int socket;
+ int handle;
+ int type;
+ prwBuffer readBuffer;
+ prwBuffer writeBuffer;
+ time_t lastOpenForWrite;
+ ANETcallback readCallback;
+ void *userData;
+ ANETkill killUser;
+ char host[132];
+} SocketDescriptor, *pSocketDescriptor;
+
+static SocketDescriptor connections[MAXCONNECTIONS];
+static int noConnections = 0;
+static unsigned int handleID = 0;
+/*------------------------------------------------------------------------*/
+static int SocketCompare(const void *s1, const void *s2)
+{
+ pSocketDescriptor socke1, socke2;
+
+ socke1 = (pSocketDescriptor) s1;
+ socke2 = (pSocketDescriptor) s2;
+ return socke1->handle - socke2->handle;
+}
+
+/*------------------------------------------------------------------------*/
+static void sortConnections()
+{
+ qsort(connections, noConnections,
+ sizeof(SocketDescriptor), SocketCompare);
+}
+
+/*------------------------------------------------------------------------*/
+static pSocketDescriptor findSocketDescriptor(int handle)
+{
+ SocketDescriptor key;
+ pSocketDescriptor result;
+
+ key.handle = handle;
+ result = bsearch(&key, connections, noConnections,
+ sizeof(SocketDescriptor), SocketCompare);
+ return result;
+}
+
+/*------------------------------------------------------------------------*/
+static ANETlog logOutput = NULL;
+static void *logUserData = NULL;
+/*------------------------------------------------------------------------*/
+static void anetLog(int level, char *fmt, ...)
+{
+ va_list ap;
+ char buf[256];
+ char *text = NULL;
+ int l;
+
+ if (logOutput == NULL) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ l = vsnprintf(buf, sizeof buf, fmt, ap);
+ va_end(ap);
+ if (l < sizeof buf) {
+ text = buf;
+ logOutput(level, text, logUserData);
+ } else {
+ /* assuming we have a C99 conforming snprintf and need a larger buffer */
+ text = calloc(l, 1);
+ va_start(ap, fmt);
+ vsnprintf(text, l, fmt, ap);
+ va_end(ap);
+ logOutput(level, text, logUserData);
+ free(text);
+ }
+}
+
+/*============= public interface =========================================*/
+void ANETsetLog(ANETlog lcb, void *userData)
+{
+ logOutput = lcb;
+ logUserData = userData;
+}
+
+/*------------------------------------------------------------------------*/
+int ANETopenServerPort(int iPort, ANETcallback cb, void *userData)
+{
+ SocketDescriptor socke;
+ int i = 1, status;
+ struct sockaddr_in addresse;
+
+ assert(iPort > 0);
+ assert(cb != NULL);
+
+ memset(&socke, 0, sizeof(SocketDescriptor));
+ socke.socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (socke.socket < 0) {
+ anetLog(ANETERROR, "Failed to open server port: socket: %d", iPort);
+ return ANETOPENFAIL;
+ }
+ status =
+ setsockopt(socke.socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int));
+ if (status < 0) {
+ anetLog(ANETERROR,
+ "Failed to open server port: setsockopt: %d, errno = %d",
+ iPort, errno);
+ return ANETOPENFAIL;
+ }
+ memset(&addresse, 0, sizeof(struct sockaddr_in));
+ addresse.sin_family = AF_INET;
+ addresse.sin_addr.s_addr = htonl(INADDR_ANY);
+ addresse.sin_port = htons(iPort);
+ status = bind(socke.socket, (struct sockaddr *) &addresse,
+ sizeof(struct sockaddr_in));
+ if (status < 0) {
+ anetLog(ANETERROR, "Failed to open server port: bind: %d, errno = %d",
+ iPort, errno);
+ return ANETOPENFAIL;
+ }
+ status = listen(socke.socket, 8);
+ if (status < 0) {
+ anetLog(ANETERROR, "Failed to open server port: listen: %d", iPort);
+ return ANETOPENFAIL;
+ }
+ socke.type = SERVERSOCKET;
+ socke.handle = handleID;
+ handleID++;
+ socke.readCallback = cb;
+ socke.userData = userData;
+ socke.lastOpenForWrite = time(NULL);
+ connections[noConnections] = socke;
+ noConnections++;
+ sortConnections();
+ anetLog(ANETCON, "Opened server port %d", iPort);
+ return socke.handle;
+}
+
+/*-----------------------------------------------------------------------*/
+int ANETregisterSocket(int socket)
+{
+ SocketDescriptor socke;
+ int flags, status;
+
+ if (noConnections >= MAXCONNECTIONS) {
+ anetLog(ANETERROR, "Maximum number of connections exceeded");
+ return ANETOUTOFSOCKETS;
+ }
+
+ memset(&socke, 0, sizeof(SocketDescriptor));
+ flags = fcntl(socket, F_GETFL, 0);
+ status = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
+ if (status < 0) {
+ return ANETSOCKERROR;
+ }
+ flags =1;
+ setsockopt(socket,IPPROTO_TCP,TCP_NODELAY,(char *) &flags, sizeof(int));
+ socke.readBuffer = MakeRWPuffer(RBUFFERSIZE);
+ socke.writeBuffer = MakeRWPuffer(WBUFFERSIZE);
+ if (socke.readBuffer == NULL || socke.writeBuffer == NULL) {
+ return ANETMEM;
+ }
+ socke.socket = socket;
+ socke.handle = handleID;
+ handleID++;
+ socke.type = DATASOCKET;
+ socke.lastOpenForWrite = time(NULL);
+ connections[noConnections] = socke;
+ noConnections++;
+ sortConnections();
+ return socke.handle;
+}
+
+/*-------------------------------------------------------------------------*/
+int ANETconnect(char *name, int iPort)
+{
+ struct in_addr addr;
+ struct sockaddr_in addresse;
+ struct hostent *host;
+ int socke, status;
+
+ memset(&addresse, 0, sizeof(struct sockaddr_in));
+ addresse.sin_family = AF_INET;
+ addresse.sin_port = htons((unsigned short)(iPort &0xFFFF));
+ host = gethostbyname(name);
+ if (host != NULL) {
+ memcpy((char *) &addr,
+ (char *)host->h_addr_list[0], (size_t)host->h_length);
+ } else {
+ /* check for aaa.bbbb.ccc.dddd */
+ addr.s_addr = inet_addr(name);
+ if(addr.s_addr == (unsigned long) -1) {
+ anetLog(ANETERROR, "Failed to locate host: %s", name);
+ return ANETOPENFAIL;
+ }
+ }
+ addresse.sin_addr.s_addr = addr.s_addr;
+ socke = socket(AF_INET, SOCK_STREAM, 0);
+ status = connect(socke, (struct sockaddr *) &addresse,
+ sizeof(struct sockaddr_in));
+ if (status < 0) {
+ anetLog(ANETERROR, "Failed to open socket to %s:%d", name, iPort);
+ return ANETOPENFAIL;
+ }
+ anetLog(ANETCON, "Opened socket %d to %s:%d", socke, name, iPort);
+ return ANETregisterSocket(socke);
+}
+
+/*--------------------------------------------------------------------------*/
+void ANETclose(int handle)
+{
+ pSocketDescriptor socke = NULL;
+
+ socke = findSocketDescriptor(handle);
+ if (socke == NULL) {
+ return;
+ }
+ close(socke->socket);
+ anetLog(ANETCON, "Closed socket %d", socke->socket);
+ if (socke->readBuffer != NULL) {
+ KillRWBuffer(socke->readBuffer);
+ }
+ if (socke->writeBuffer != NULL) {
+ KillRWBuffer(socke->writeBuffer);
+ }
+ if (socke->userData && socke->killUser) {
+ socke->killUser(socke->userData);
+ }
+ if (noConnections > 1) {
+ *socke = connections[noConnections - 1];
+ noConnections--;
+ sortConnections();
+ } else {
+ noConnections = 0;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+static int anetWrite(SocketDescriptor con)
+{
+ int status, length;
+ void *pPtr;
+
+ pPtr = GetRWBufferData(con.writeBuffer, &length);
+ if (length > 0) {
+ status = send(con.socket, pPtr, length, 0);
+ if (status < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+ return 1;
+ }
+ ANETclose(con.handle);
+ return 0;
+ }
+ RemoveRWBufferData(con.writeBuffer, status);
+ }
+ return 1;
+}
+/*--------------------------------------------------------------------------
+ * I have seen that select did not report the write possibility set,
+ * though the send buffer was empty. Thus I try to write if data is there
+ * and leave the lastOpenForWrite flag only when the socket would block
+ * on write.
+ *--------------------------------------------------------------------------*/
+static int anetTestWrite(SocketDescriptor con)
+{
+ int status, length;
+ void *pPtr;
+ time_t lastTime;
+
+ if(con.type != DATASOCKET){
+ return 1;
+ }
+
+ lastTime = con.lastOpenForWrite;
+ con.lastOpenForWrite = time(NULL);
+ pPtr = GetRWBufferData(con.writeBuffer, &length);
+ if (length > 0) {
+ status = send(con.socket, pPtr, length, 0);
+ if (status < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+ con.lastOpenForWrite = lastTime;
+ return 1;
+ }
+ ANETclose(con.handle);
+ return 0;
+ }
+ RemoveRWBufferData(con.writeBuffer, status);
+ }
+ return 1;
+}
+/*--------------------------------------------------------------------------*/
+static int anetRead(SocketDescriptor con)
+{
+ int socke, handle, status;
+ unsigned int len;
+ struct sockaddr addresse;
+ char buffer[8192];
+
+ switch (con.type) {
+ case SERVERSOCKET:
+ len = sizeof(struct sockaddr);
+ socke = accept(con.socket, &addresse, &len);
+ if (socke < 0) {
+ return 1;
+ }
+ handle = ANETregisterSocket(socke);
+ if (handle > 0) {
+ status = con.readCallback(handle, con.userData);
+ if (status != 1) {
+ ANETclose(handle);
+ return 0;
+ }
+ }
+ anetLog(ANETCON, "Accepted socket %d on port %d, handle %d",
+ socke, con.socket, handle);
+ break;
+ case DATASOCKET:
+ memset(buffer, 0, 8192);
+ status = recv(con.socket, buffer, 8192, 0);
+ if (status < 0) {
+ if (errno == EAGAIN) {
+ return 1;
+ }
+ ANETclose(con.handle);
+ return 0;
+ } else if (status == 0) {
+ /* this means EOF */
+ ANETclose(con.handle);
+ return 0;
+ } else {
+ status = StoreRWBuffer(con.readBuffer, buffer, status);
+ if (status != 1) {
+ anetLog(ANETERROR, "Read buffer overrun at handle %d, socket %d",
+ con.handle, con.socket);
+ }
+ if (con.readCallback != NULL) {
+ con.readCallback(con.handle, con.userData);
+ }
+ }
+ break;
+ }
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+void ANETprocess(void)
+{
+ int i, status, count = 0, socke = 0, length;
+ fd_set readMask, writeMask;
+ struct timeval tmo = { 0, 10 };
+
+ FD_ZERO(&readMask);
+ FD_ZERO(&writeMask);
+ for (i = 0; i < noConnections; i++) {
+ socke = connections[i].socket;
+ FD_SET(socke, &readMask);
+ FD_SET(socke, &writeMask);
+ if (socke > count) {
+ count = socke;
+ }
+ }
+
+ count++;
+ status = select(count, &readMask, &writeMask, NULL, &tmo);
+ if (status < 0) {
+ if (errno == EINTR) {
+ return;
+ }
+ return;
+ }
+
+ /**
+ * I always jump out of this loop when a socket is created or closed
+ * because then the order in the connections array is no longer valid.
+ * Try again the next time round.
+ */
+ for (i = 0; i < noConnections; i++) {
+ socke = connections[i].socket;
+ if (FD_ISSET(socke, &readMask)) {
+ if (anetRead(connections[i]) == 0) {
+ return;
+ }
+ }
+ if (FD_ISSET(socke, &writeMask)) {
+ /*
+ * This has to be here, as I found out tracing a subtle bug:
+ * If the time is set in writeANET the modification will not
+ * propagate into the array as C copies the structure for the function call.
+ */
+ connections[i].lastOpenForWrite = time(NULL);
+ if (anetWrite(connections[i]) == 0) {
+ return;
+ }
+ } else {
+ /*
+ * If I could not write to the socket for 5 minutes,
+ * the socket is considered broken and is closed.
+ */
+ if (time(NULL) > connections[i].lastOpenForWrite + 300 &&
+ connections[i].type == DATASOCKET) {
+ GetRWBufferData(connections[i].writeBuffer, &length);
+ anetLog(ANETCON, "Closing socket because of time overrun: %d, delay = %d, bytes to be written = %d, write bit = %d\n", connections[i].socket,
+ (int)(time(NULL) - connections[i].lastOpenForWrite), length, FD_ISSET(connections[i].socket, &writeMask) );
+ ANETclose(connections[i].handle);
+ return;
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+int ANETvalidHandle(int handle)
+{
+ pSocketDescriptor con = NULL;
+
+ con = findSocketDescriptor(handle);
+ if (con != NULL) {
+ return ANETOK;
+ } else {
+ return 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+int ANETinfo(int handle, char *hostname, int hostnameLen)
+{
+ pSocketDescriptor con = NULL;
+ struct sockaddr_in sin;
+ struct hostent *host;
+ socklen_t len;
+
+ con = findSocketDescriptor(handle);
+ if (con == NULL) {
+ return ANETDISCONNECTED;
+ } else {
+ if(strlen(con->host) < 3){
+ len = sizeof sin;
+ if (getpeername(con->socket, (struct sockaddr *) &sin, &len) < 0) {
+ return ANETSOCKERROR;
+ }
+ if ((host = gethostbyaddr((char *) &sin.sin_addr,
+ sizeof(sin.sin_addr), AF_INET)) == NULL) {
+ return ANETSOCKERROR;
+ }
+ strlcpy(con->host,host->h_name, 132);
+ }
+ memset(hostname, 0, hostnameLen);
+ strlcpy(hostname, con->host, hostnameLen);
+ }
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+int ANETwrite(int handle, void *buffer, int count)
+{
+ pSocketDescriptor con = NULL;
+ int status;
+
+ con = findSocketDescriptor(handle);
+ if (con == NULL) {
+ return ANETDISCONNECTED;
+ } else {
+ status = StoreRWBuffer(con->writeBuffer, buffer, count);
+ /*
+ first try if ANETprocess can write some and free the buffer
+ before giving up
+ */
+ if (status != 1) {
+ ANETprocess();
+ status = StoreRWBuffer(con->writeBuffer, buffer, count);
+ }
+ if (status != 1) {
+ anetLog(ANETERROR, "Write buffer overrun on handle %d, socket %d, trying to write %d bytes",
+ con->handle, con->socket, count);
+ return ANETWRITEBUFFERFULL;
+ }
+ }
+ return ANETOK;
+}
+
+/*---------------------------------------------------------------------------*/
+int ANETread(int handle, void *buffer, int bufferLength)
+{
+ pSocketDescriptor con = NULL;
+ int status, length, len;
+ void *data = NULL;
+
+ con = findSocketDescriptor(handle);
+ if (con == NULL) {
+ return ANETDISCONNECTED;
+ } else {
+ data = GetRWBufferData(con->readBuffer, &length);
+ if (length == 0) {
+ len = 0;
+ } else if (length >= bufferLength) {
+ len = bufferLength;
+ } else {
+ len = length;
+ }
+ if (len > 0) {
+ memcpy(buffer, data, len);
+ }
+ }
+ return len;
+}
+
+/*---------------------------------------------------------------------------*/
+void *ANETreadPtr(int handle, int *length)
+{
+ pSocketDescriptor con = NULL;
+ void *data = NULL;
+
+ con = findSocketDescriptor(handle);
+ if (con == NULL) {
+ return NULL;
+ } else {
+ data = GetRWBufferData(con->readBuffer, length);
+ return data;
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+void ANETreadConsume(int handle, int count)
+{
+ pSocketDescriptor con = NULL;
+
+ con = findSocketDescriptor(handle);
+ if (con == NULL) {
+ return;
+ } else {
+ RemoveRWBufferData(con->readBuffer, count);
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+void ANETsetReadCallback(int handle, ANETcallback cb,
+ void *userData, ANETkill killUser)
+{
+ pSocketDescriptor con = NULL;
+
+ con = findSocketDescriptor(handle);
+ if (con == NULL) {
+ return;
+ } else {
+ con->readCallback = cb;
+ con->userData = userData;
+ con->killUser = killUser;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+int ANETreadTillTerm(int handle,
+ ANETtermCallback tcb, void *termData,
+ ANETwait wcb, void *waitData, char **buffer)
+{
+ pSocketDescriptor con = NULL;
+ char *data;
+ int length, status;
+
+ while (wcb(waitData) > 0) {
+ ANETprocess();
+ con = findSocketDescriptor(handle);
+ if (con == NULL) {
+ return ANETDISCONNECTED;
+ }
+ data = GetRWBufferData(con->readBuffer, &length);
+ if (length > 0) {
+ status = tcb(data, length, termData);
+ if (status > 0) {
+ *buffer = malloc(status * sizeof(char));
+ if (*buffer != NULL) {
+ memcpy(*buffer, data, status);
+ }
+ RemoveRWBufferData(con->readBuffer, status);
+ return ANETOK;
+ }
+ }
+ }
+ return ANETTIMEOUT;
+}
diff --git a/asynnet.h b/asynnet.h
new file mode 100644
index 00000000..9912b70f
--- /dev/null
+++ b/asynnet.h
@@ -0,0 +1,210 @@
+/**
+ * Asynchronous networking for SICS and other programs. This module centrally manages
+ * a number of network connections for a client program. It is a layer between the
+ * program and the network which manages non blocking network I/O. To this purpose, the
+ * client program has to call ANETprocess at convenient intervals. This module
+ * has a couple of features:
+ * - Connections are abstracted to handles which are guaranteed to be unique
+ * rather then socket numbers. Socket numbers may be reused by the OS.
+ * - This module allows upper level code to figure out if a connection is still
+ * connected or not.
+ * - This module introduces a buffer layer between the socket and the application.
+ * Thus the upper layer does not have to worry much about I/O blocking. This
+ * is taken care of by this module both for reading and writing.
+ * - All I/O is non blocking.
+ * - This module can detect if a client is hanging and close the connection then.
+ * Hanging is detected by not being able to write to the client for some period
+ * of time.
+ *
+ * copyright: see file COPYRIGHT
+ *
+ * Mark Koennecke, January 2009
+ */
+#ifndef ASYNNET_H_
+#define ASYNNET_H_
+/*=================== error codes ========================================*/
+#define ANETOK 1
+#define ANETDISCONNECTED -10000
+#define ANETWRITEBUFFERFULL -10001
+#define ANETTIMEOUT -10002
+#define ANETOPENFAIL -10003
+#define ANETSOCKERROR -10004
+#define ANETMEM -10005
+#define ANETOUTOFSOCKETS -10006
+/*================== log levels ==========================================*/
+#define ANETNONE 0
+#define ANETERROR 1
+#define ANETIO 2
+#define ANETCON 3
+/*================== callback functions ==================================*/
+/**
+ * \brief Callback called when a connection has been accepted on a
+ * port or data is ready.
+ * \param handle The handle of the new network connection
+ * \return 1 if the new connection can be accepted or 0 if not.
+ * Same for data.
+ */
+typedef int (*ANETcallback) (int handle, void *userData);
+/**
+ * \brief a callback which is called in order to determine if a
+ * a terminator is present in the data.
+ * \param data The data to inspect
+ * \param length The length of the data to inspect
+ * \param userData An opaque pointer passed through to this
+ * function
+ * \return -1 when no terminator is in the data, an integer pointing
+ * to after the terminator in data (in bytes).
+ */
+typedef int (*ANETtermCallback) (void *data, int length, void *userData);
+/**
+ * \brief a callback function for waiting on some event.
+ * This is typically called to do something else while waiting
+ * for data to arrive. It can also return a negative return value,
+ * which will effectively implement a timeout.
+ * \param userData An opaque pointer passed through to this callback
+ * \return 1 to continue waiting, -1 for a timeout.
+ */
+typedef int (*ANETwait) (void *userData);
+/**
+ * \brief callback to log events in ANET
+ * \param level The level of the logging message
+ * \param txt The logging data
+ * \param userData An opaque pointer passed through to ANETlog
+ */
+typedef void (*ANETlog) (int level, char *txt, void *userData);
+/**
+ * \brief a callback for killing userdata associated with a read callback.
+ * This is called in ANETclose, if defined.
+ * \param userData The user data to kill.
+ */
+typedef void (*ANETkill) (void *userData);
+/*===================== open/close functions =============================*/
+/**
+ * * \brief open a server port
+ * \param iPort The port number at which to listen for
+ * connections.
+ * \param cb A callback which will be called whenever a new connection
+ * has been accepted on this port.
+ * \prama userData An opaque pointer to be passed as an argument to the
+ * callback function.
+ * \return A handle for the server port or a negative error code.
+ */
+int ANETopenServerPort(int iPort, ANETcallback cb, void *userData);
+/**
+ * \brief open a client connection to a server.
+ * \param name the computer name of the server
+ * \param iPort The port number at which the server is listening
+ * \return A handle to the open port or a negative error code.
+ */
+int ANETconnect(char *name, int iPort);
+/**
+ * \brief register a socket to be managed by this module. The socket
+ * may have been obtained by any means.
+ * \param socket The file descriptor of the socket
+ * \return A handle to use for this socket later on.
+ */
+int ANETregisterSocket(int socket);
+/**
+ * \brief close a connection
+ * \param handle The handle of the connection
+ */
+void ANETclose(int handle);
+/**
+ * \brief This function drives I/O processing, i.e. reading and writing.
+ * This has to be called by the client of this module at regular intervalls.
+ */
+void ANETprocess(void);
+/**
+ * \brief tests if a handle is still a valid connection
+ * \param handle The handle to test.
+ * \return 1 if this is still a connected socket, 0 else.
+ */
+int ANETvalidHandle(int handle);
+/**
+ * \brief figure out to which host we are connected.
+ * \param handle The connection handle
+ * \param hostname a buffer to copy the hostname into
+ * \param hostNameLen the length of the hostname buffer
+ * \return 1 on success, a negative error code else.
+ */
+int ANETinfo(int handle, char *hostname, int hostNameLen);
+/*=================== I/O functions ===========================================
+ * For reading there are possibilities:
+ * - Raw reading happens through the combination of
+ * ANETread and ANETreadConsume.
+ * - Another way for raw reading is to register a read callback which is
+ * called anytime new data arrives.
+ * - The usual case is to wait for a line of terminated command input. This is
+ * done through ANETreadTillterm.
+ * ==========================================================================*/
+/**
+ * \brief write to the network
+ * \param handle The handle for the connection
+ * \param buffer A pointer to the data to write
+ * \param count The number of bytes to write.
+ * \return 1 on success, 0 on failure
+ */
+int ANETwrite(int handle, void *buffer, int count);
+/**
+ * \brief copy at max bufferLength bytes into buffer. The data is not deleted from
+ * the read buffer yet.
+ * \param handle The handle of the connection to read from
+ * \param buffer a pointer to an area for holding the data
+ * \param bufferLength The maximum number of bytes which can be copied into
+ * the buffer.
+ * \return The number of bytes copied. Can be 0 if no data is available. On
+ * errors a negative error code is returned.
+ */
+int ANETread(int handle, void *buffer, int bufferLength);
+/**
+ * \brief Get a pointer to the data which has been read up to now.
+ * Do not mess with the data!! Else the result may be badly defined!
+ * \param handle The handle for the connection
+ * \param length will be set to the length of the data read so far.
+ * \return NULL when the socket is disconnected, a pointer else.
+ */
+void *ANETreadPtr(int handle, int *length);
+/**
+ * \brief remove count bytes from the read buffer.
+ * \param handle The handle for the connection.
+ * \param count The number of bytes which can be removed from the
+ * read buffer.
+ */
+void ANETreadConsume(int handle, int count);
+/**
+ * \brief set a callback to be called when data is available at the port.
+ * \param handle The handle of the connection
+ * \param cb The callback function to call
+ * \param userData An opaque pointer passed on as a parameter to the
+ * callback function.
+ */
+void ANETsetReadCallback(int handle, ANETcallback cb, void *userData,
+ ANETkill killUser);
+/**
+ * \brief wait for terminated data to arrive.
+ * \param handle The connection handle to read from
+ * \param tcb a callback function which determines if a terminator is in the
+ * data.
+ * \param termData An opaque data pointer passed on to tcb
+ * \param wcb A callback function called while waiting for data
+ * to arrive.
+ * \param waitData An opaque pointer passed on to wcb
+ * \param buffer A newly allocated buffer holding the data as read
+ * including the terminator.
+ * \return 1 on success, a negative error code else.
+ */
+int ANETreadTillTerm(int handle,
+ ANETtermCallback tcb, void *termData,
+ ANETwait wcb, void *waitData, char **buffer);
+/**
+ * Note to Markus: suitable callbacks for the standard case: waiting for \n and
+ * TaskYield for waiting to a timeout will become part of nread.h, .c.
+ */
+/*========================== system ====================================*/
+/**
+ * \brief install a logging function
+ * \param lcb The logging function to install
+ * \param userData An opaque pointer with data for lcb
+ */
+void ANETsetLog(ANETlog lcb, void *userData);
+#endif /*ASYNNET_H_ */
diff --git a/background.c b/background.c
new file mode 100644
index 00000000..0558ce07
--- /dev/null
+++ b/background.c
@@ -0,0 +1,87 @@
+/**
+ * This is for backgrounding operations in SICS. They run in an own
+ * task.
+ *
+ * copyright: see file COPYRIGHT
+ *
+ * Mark Koennecke, February 2009
+ */
+#include
+#include "splitter.h"
+#include "background.h"
+
+/*---------------------------------------------------------------------------*/
+typedef struct {
+ SConnection *con;
+ char *command;
+} BckTask, *pBckTask;
+/*---------------------------------------------------------------------------*/
+static void KillBckTask(void *data)
+{
+ pBckTask self = (pBckTask) data;
+ if (self == NULL) {
+ return;
+ }
+ if (self->con) {
+ SCDeleteConnection(self->con);
+ }
+ if (self->command) {
+ free(self->command);
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+static int BackgroundTask(void *data)
+{
+ pBckTask self = (pBckTask) data;
+
+ assert(self != NULL);
+
+ InterpExecute(pServ->pSics, self->con, self->command);
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+int BackgroundCommand(SConnection * pCon, char *command)
+{
+ pBckTask self = NULL;
+
+ self = calloc(1, sizeof(BckTask));
+ if (self == NULL) {
+ return 0;
+ }
+
+ self->con = SCCopyConnection(pCon);
+ self->command = strdup(command);
+ if (self->con == NULL || self->command == NULL) {
+ free(self);
+ return 0;
+ }
+
+ TaskRegister(pServ->pTasker, BackgroundTask, NULL, KillBckTask, self, 1);
+ return 1;
+}
+
+/*------------------------------------------------------------------------*/
+int BackgroundAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[])
+{
+ int status;
+ char command[1024];
+
+ memset(command, 0, 1024);
+ Arg2Text(argc - 1, &argv[1], command, 1024);
+ status = BackgroundCommand(pCon, command);
+ if (status == 0) {
+ SCWrite(pCon, "ERROR: out of memory starting task", eError);
+ return 0;
+ }
+ SCSendOK(pCon);
+ return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+void InstallBackground(void)
+{
+ AddCmd("bg", BackgroundAction);
+}
diff --git a/background.h b/background.h
new file mode 100644
index 00000000..61965821
--- /dev/null
+++ b/background.h
@@ -0,0 +1,26 @@
+/**
+ * This is for backgrounding operations in SICS. They run in an own
+ * task.
+ *
+ * copyright: see file COPYRIGHT
+ *
+ * Mark Koennecke, February 2009
+ */
+#ifndef BACKGROUND_H_
+#define BACKGROUND_H_
+
+/**
+ * interpreter inteface
+ */
+int BackgroundAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[]);
+/*
+ * actual function which does the backgrounding
+ */
+int BackgroundCommand(SConnection * pCon, char *command);
+/*
+ * used only once for installing Background
+*/
+void InstallBackground(void);
+
+#endif /*BACKGROUND_H_ */
diff --git a/bit.h b/bit.h
index 45b3cbf3..2e35778f 100644
--- a/bit.h
+++ b/bit.h
@@ -8,7 +8,7 @@
----------------------------------------------------------------------------*/
-#include /* for CHAR_BIT */
+#include /* for CHAR_BIT */
#define BITMASK(bit) (1 << ((bit) % CHAR_BIT))
#define BITSLOT(bit) ((bit) / CHAR_BIT)
diff --git a/callback.c b/callback.c
index ab713fe5..d6a2331c 100644
--- a/callback.c
+++ b/callback.c
@@ -50,270 +50,294 @@
#include "splitter.h"
#define CALLBACK 17777
+static int debug = 0;
-/*--------------------- The interface datastructure ---------------------*/
- typedef struct __ICallBack {
- int iID;
- int iList;
- } ICallBack;
-
/*-------------- The data stored for a single callback ------------------*/
- typedef struct {
- long iID;
- SICSCallBack pFunc;
- void *pUserData;
- KillFuncIT pKill;
- int iEvent;
- commandContext comCon;
- } CallBackItem, *pCallBackItem;
+typedef struct __CBItem {
+ long iID;
+ SICSCallBack pFunc;
+ void *pUserData;
+ KillFuncIT pKill;
+ int iEvent;
+ int killFlag;
+ struct __CBItem *next;
+} CallBackItem, *pCallBackItem;
+/*--------------------- The interface datastructure ---------------------*/
+typedef struct __ICallBack {
+ int iID;
+ pCallBackItem head;
+} ICallBack;
+
/*------------------------------------------------------------------------*/
- static int CheckPointer(pICallBack self)
- {
- if(self == NULL) return 0;
- if(self->iID != CALLBACK)
- {
- return 0;
- }
- return 1;
- }
-/*-------------------------------------------------------------------------*/
-
- pICallBack CreateCallBackInterface(void)
- {
- pICallBack pNew = NULL;
-
- pNew = (pICallBack)malloc(sizeof(ICallBack));
- if(!pNew)
- {
- return 0;
- }
-
- pNew->iID = CALLBACK;
- pNew->iList = LLDcreate(sizeof(CallBackItem));
- if(pNew->iList < 0)
- {
- free(pNew);
- return NULL;
- }
- return pNew;
- }
-/*--------------------------------------------------------------------------*/
- void DeleteCallBackInterface(pICallBack self)
- {
- int iRet;
- CallBackItem sItem;
-
- if(!CheckPointer(self))
- {
- return;
- }
-
- /* kill all userdata associated with callbacks */
- iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- LLDnodeDataTo(self->iList,&sItem);
- if(sItem.pKill != NULL)
- {
- sItem.pKill(sItem.pUserData);
- }
- iRet = LLDnodePtr2Next(self->iList);
- }
-
- LLDdelete(self->iList);
- free(self);
- }
-/*--------------------------------------------------------------------------*/
- int InvokeCallBack(pICallBack self, int iEvent, void *pEventData)
- {
- CallBackItem sItem;
- int iCurrent, iRet;
- int iResult = 1;
-
- if(!CheckPointer(self))
- {
- return 0;
- }
-
- iCurrent = LLDnodePtr2First(self->iList);
- while(iCurrent != 0)
- {
- LLDnodeDataTo(self->iList,&sItem);
- if(sItem.iEvent == iEvent)
- {
- iRet = sItem.pFunc(iEvent, pEventData,sItem.pUserData,sItem.comCon);
- if(!iRet)
- {
- iResult = 0;
- }
- }
- iCurrent = LLDnodePtr2Next(self->iList);
- }
- return iResult;
- }
-/*--------------------------------------------------------------------------*/
- static long lCount = 1L;
-
- long RegisterCallback(pICallBack self, commandContext comCon, int iEvent,
- SICSCallBack pFunc,
- void *pUserData, KillFunc pKFunc)
- {
- CallBackItem sItem;
-
- if(!CheckPointer(self))
- {
- return 0;
- }
-
- sItem.iID = lCount++;
- assert(pFunc);
- sItem.pFunc = pFunc;
- sItem.iEvent = iEvent;
- sItem.pUserData = pUserData;
- sItem.pKill = pKFunc;
- sItem.comCon = comCon;
-
- LLDnodeAppendFrom(self->iList,&sItem);
- return sItem.iID;
- }
-/*-------------------------------------------------------------------------*/
- int RemoveCallback(pICallBack self, long lID)
- {
- CallBackItem sItem;
- int iCurrent;
-
- if(!CheckPointer(self))
- {
- return 0;
- }
-
- iCurrent = LLDnodePtr2First(self->iList);
- while(iCurrent != 0)
- {
- LLDnodeDataTo(self->iList,&sItem);
- if(sItem.iID == lID)
- {
- if(sItem.pKill != NULL)
- {
- sItem.pKill(sItem.pUserData);
- }
- LLDnodeDelete(self->iList);
- return 1;
- }
- iCurrent = LLDnodePtr2Next(self->iList);
- }
- return 0;
- }
-/*--------------------------------------------------------------------------*/
- int RemoveCallback2(pICallBack self, void *pUserData)
- {
- CallBackItem sItem;
- int iCurrent;
-
- if(!CheckPointer(self))
- {
- return 0;
- }
-
- iCurrent = LLDnodePtr2First(self->iList);
- while(iCurrent != 0)
- {
- LLDnodeDataTo(self->iList,&sItem);
- if(sItem.pUserData == pUserData)
- {
- if(sItem.pKill != NULL)
- {
- sItem.pKill(sItem.pUserData);
- }
- LLDnodeDelete(self->iList);
- }
- iCurrent = LLDnodePtr2Next(self->iList);
- }
- return 1;
- }
-/*--------------------------------------------------------------------------*/
- int RemoveCallback3(pICallBack self, SICSCallBack pFunc, int (*func)(const void* context, const void* pUserData), void *context)
- {
- CallBackItem sItem;
- int iCurrent;
-
- if(!CheckPointer(self))
- {
- return 0;
- }
-
- iCurrent = LLDnodePtr2First(self->iList);
- while(iCurrent != 0)
- {
- LLDnodeDataTo(self->iList,&sItem);
- if(sItem.pFunc == pFunc && func(context, sItem.pUserData) == 0)
- {
- if(sItem.pKill != NULL)
- {
- sItem.pKill(sItem.pUserData);
- }
- LLDnodeDelete(self->iList);
- iCurrent = LLDnodePtr2First(self->iList);
- continue;
- }
- iCurrent = LLDnodePtr2Next(self->iList);
- }
- return 1;
- }
-/*-------------------------------------------------------------------
- a write function for the connection which writes to stdout
- -------------------------------------------------------------------*/
-static int CallbackWrite(SConnection *pCon,char *message, int outCode)
+static int CheckPointer(pICallBack self)
{
- if(outCode >= eWarning)
- {
- fputs(message,stdout);
- fputs("\n",stdout);
+ if (self == NULL)
+ return 0;
+ if (self->iID != CALLBACK) {
+ return 0;
}
return 1;
}
+
+/*-------------------------------------------------------------------------*/
+
+pICallBack CreateCallBackInterface(void)
+{
+ pICallBack pNew = NULL;
+
+ pNew = (pICallBack) malloc(sizeof(ICallBack));
+ if (!pNew) {
+ return 0;
+ }
+
+ pNew->iID = CALLBACK;
+ pNew->head = NULL;
+ return pNew;
+}
+
+/*--------------------------------------------------------------------------*/
+void DeleteCallBackInterface(pICallBack self)
+{
+ int iRet;
+ pCallBackItem pItem, pTmp;
+
+ if (!CheckPointer(self)) {
+ return;
+ }
+
+ /* kill all userdata associated with callbacks */
+ pItem = self->head;
+ while (pItem != NULL) {
+ pTmp = pItem->next;
+ if (pItem->pKill != NULL) {
+ pItem->pKill(pItem->pUserData);
+ }
+ free(pItem);
+ pItem = pTmp;
+ }
+ free(self);
+}
+
+/*--------------------------------------------------------------------------*/
+static void markUserdata4Kill(pICallBack self, void *pData)
+{
+ pCallBackItem pItem = NULL;
+
+ pItem = self->head;
+ while (pItem != NULL) {
+ if (pData != NULL && pItem->pUserData == pData) {
+ pItem->killFlag = 1;
+ }
+ pItem = pItem->next;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+static void cleanCallbackList(pICallBack self)
+{
+ pCallBackItem toKill, current, previous;
+
+ previous = NULL;
+ current = self->head;
+ while (current != NULL) {
+ if (current->killFlag == 1) {
+ toKill = current;
+ current = current->next;
+
+ /* update link from previous item or from head */
+ if (previous == NULL) {
+ self->head = current;
+ } else {
+ previous->next = current;
+ }
+
+ if (toKill->pKill != NULL) {
+ toKill->pKill(toKill->pUserData);
+ }
+ free(toKill);
+ } else {
+ previous = current;
+ current = current->next;
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+int InvokeCallBack(pICallBack self, int iEvent, void *pEventData)
+{
+ pCallBackItem pItem;
+ int iCurrent, iRet;
+ int iResult = 1, iKill = 0;;
+
+ if (!CheckPointer(self)) {
+ return 0;
+ }
+
+ pItem = self->head;
+ while (pItem != NULL) {
+ if (pItem->iEvent == iEvent && pItem->killFlag == 0) {
+ iRet = pItem->pFunc(iEvent, pEventData, pItem->pUserData);
+ if (iRet < 0) {
+ pItem->killFlag = 1;
+ if (pItem->pUserData != NULL) {
+ markUserdata4Kill(self, pItem->pUserData);
+ iKill = 1;
+ }
+ } else if (iRet != 1) {
+ iResult = 0;
+ }
+ }
+ pItem = pItem->next;
+ }
+
+ /* kill run */
+ if (iKill == 1) {
+ cleanCallbackList(self);
+ }
+
+ return iResult;
+}
+
+/*--------------------------------------------------------------------------*/
+static long lCount = 1L;
+
+long RegisterCallback(pICallBack self, int iEvent,
+ SICSCallBack pFunc, void *pUserData, KillFunc pKFunc)
+{
+ pCallBackItem pItem = NULL;
+
+ if (!CheckPointer(self)) {
+ return 0;
+ }
+
+ pItem = calloc(1, sizeof(CallBackItem));
+ if (pItem == NULL) {
+ return -1;
+ }
+ pItem->iID = lCount++;
+ assert(pFunc);
+ pItem->pFunc = pFunc;
+ pItem->iEvent = iEvent;
+ pItem->pUserData = pUserData;
+ pItem->pKill = pKFunc;
+ pItem->killFlag = 0;
+ pItem->next = self->head;
+ self->head = pItem;
+ if (debug) {
+ printf("Registered callback at %p\n", self);
+ }
+ return pItem->iID;
+}
+
+/*------------------------------------------------------------------------*/
+static void markById(pICallBack self, int lID)
+{
+ pCallBackItem pItem = NULL;
+
+ pItem = self->head;
+ while (pItem != NULL) {
+ if (pItem->iID == lID) {
+ pItem->killFlag = 1;
+ }
+ pItem = pItem->next;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+int RemoveCallback(pICallBack self, long lID)
+{
+ CallBackItem sItem;
+ int iCurrent;
+
+ if (!CheckPointer(self)) {
+ return 0;
+ }
+ markById(self, lID);
+ cleanCallbackList(self);
+ return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+int RemoveCallback2(pICallBack self, void *pUserData)
+{
+ CallBackItem sItem;
+ int iCurrent;
+
+ if (!CheckPointer(self)) {
+ return 0;
+ }
+ markUserdata4Kill(self, pUserData);
+ cleanCallbackList(self);
+ return 1;
+}
+
+ /*--------------------------------------------------------------------------*/
+int RemoveCallbackCon(pICallBack self, SConnection * con)
+{
+ pCallBackItem pItem;
+ SConnection *tst = NULL;
+
+ if (!CheckPointer(self)) {
+ return 0;
+ }
+
+ pItem = self->head;
+ while (pItem != NULL) {
+ tst = (SConnection *) pItem->pUserData;
+ if (VerifyConnection(tst) && tst->ident == con->ident) {
+ if (debug) {
+ printf("Killing callback on connection.ident = %ld\n", con->ident);
+ }
+ pItem->killFlag = 1;
+ }
+ pItem = pItem->next;
+ }
+ cleanCallbackList(self);
+ return 1;
+}
+
+/*-------------------------------------------------------------------
+ a write function for the connection which writes to stdout
+ -------------------------------------------------------------------*/
+static int CallbackWrite(SConnection * pCon, char *message, int outCode)
+{
+ if (outCode >= eWarning) {
+ fputs(message, stdout);
+ fputs("\n", stdout);
+ }
+ return 1;
+}
+
/*-----------------------------------------------------------------------
the actual callback function invoking the script
------------------------------------------------------------------------*/
-static int ScriptCallback(int iEvent, void *pEventData, void *pUserData,
- commandContext cc)
+static int ScriptCallback(int iEvent, void *pEventData, void *pUserData)
{
SConnection *pCon = NULL;
Tcl_Interp *pTcl;
int status;
pCon = SCCreateDummyConnection(pServ->pSics);
- if(!pCon)
- {
- fprintf(stdout,"ERROR: failed to create dummy connection\n");
+ if (!pCon) {
+ fprintf(stdout, "ERROR: failed to create dummy connection\n");
return 0;
}
- if(pUserData == NULL)
- {
- fprintf(stdout,"ERROR: ScriptCallback: no script to execute\n");
+ if (pUserData == NULL) {
+ SCDeleteConnection(pCon);
+ fprintf(stdout, "ERROR: ScriptCallback: no script to execute\n");
return 0;
}
- /*
- SCSetWriteFunc(pCon,CallbackWrite);
- MacroPush(pCon);
- pTcl = InterpGetTcl(pServ->pSics);
- status = Tcl_Eval(pTcl,(char *)pUserData);
- if(status != TCL_OK)
- {
- fprintf(stdout,"ERROR: in CallbackScript: %s\n",(char *)pUserData);
- fprintf(stdout,"Tcl-error: %s\n",pTcl->result);
- }
- MacroPop();
- */
- SCSetRights(pCon,usInternal);
- status = InterpExecute(pServ->pSics,pCon,(char *)pUserData);
+ SCSetRights(pCon, usInternal);
+ SCSetWriteFunc(pCon,SCNotWrite);
+ status = InterpExecute(pServ->pSics, pCon, (char *) pUserData);
SCDeleteConnection(pCon);
return 1;
}
+
/*------------------------------------------------------------------------*/
-int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
+int CallbackScript(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
{
long lID;
int iEvent, status;
@@ -321,88 +345,76 @@ int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,
CommandList *pCom = NULL;
char pBuffer[132];
- if(argc < 2)
- {
- SCWrite(pCon,"ERROR: insufficient number of arguments to callbackScript",
- eError);
+ if (argc < 2) {
+ SCWrite(pCon,
+ "ERROR: insufficient number of arguments to callbackScript",
+ eError);
return 0;
}
/*
- only managers may do this
- */
- if(!SCMatchRights(pCon,usMugger))
- {
+ only managers may do this
+ */
+ if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
strtolower(argv[1]);
- if(strcmp(argv[1],"connect") == 0)
- {
- if(argc < 4)
- {
- SCWrite(pCon,"ERROR: not enough arguments to CallbackScript connect",
- eError);
+ if (strcmp(argv[1], "connect") == 0) {
+ if (argc < 4) {
+ SCWrite(pCon,
+ "ERROR: not enough arguments to CallbackScript connect",
+ eError);
return 0;
}
strtolower(argv[2]);
- pCom = FindCommand(pSics,argv[2]);
- if(!pCom)
- {
- SCWrite(pCon,"ERROR: object to connect to not found",eError);
+ pCom = FindCommand(pSics, argv[2]);
+ if (!pCom) {
+ SCWrite(pCon, "ERROR: object to connect to not found", eError);
return 0;
}
pCall = GetCallbackInterface(pCom->pData);
- if(!pCall)
- {
- SCWrite(pCon,"ERROR: object has no callback interface",eError);
+ if (!pCall) {
+ SCWrite(pCon, "ERROR: object has no callback interface", eError);
return 0;
}
iEvent = Text2Event(argv[3]);
- if(iEvent < 0)
- {
- SCWrite(pCon,"ERROR: event type not known",eError);
+ if (iEvent < 0) {
+ SCWrite(pCon, "ERROR: event type not known", eError);
return 0;
}
- Arg2Text(argc-4,&argv[4],pBuffer,131);
- lID = RegisterCallback(pCall,SCGetContext(pCon),
- iEvent,ScriptCallback,
- strdup(pBuffer),free);
- sprintf(pBuffer,"callback = %ld", lID);
- SCWrite(pCon,pBuffer,eValue);
+ Arg2Text(argc - 4, &argv[4], pBuffer, 131);
+ lID = RegisterCallback(pCall,
+ iEvent, ScriptCallback, strdup(pBuffer), free);
+ sprintf(pBuffer, "callback = %ld", lID);
+ SCWrite(pCon, pBuffer, eValue);
return 1;
- }
- else if(strcmp(argv[1],"remove") == 0)
- {
- if(argc < 4)
- {
- SCWrite(pCon,"ERROR: not enough arguments to CallbackScript remove",
- eError);
+ } else if (strcmp(argv[1], "remove") == 0) {
+ if (argc < 4) {
+ SCWrite(pCon, "ERROR: not enough arguments to CallbackScript remove",
+ eError);
return 0;
}
strtolower(argv[2]);
- pCom = FindCommand(pSics,argv[2]);
- if(!pCom)
- {
- SCWrite(pCon,"ERROR: object to remove to not found",eError);
+ pCom = FindCommand(pSics, argv[2]);
+ if (!pCom) {
+ SCWrite(pCon, "ERROR: object to remove to not found", eError);
return 0;
}
pCall = GetCallbackInterface(pCom->pData);
- if(!pCall)
- {
- SCWrite(pCon,"ERROR: object has no callback interface",eError);
+ if (!pCall) {
+ SCWrite(pCon, "ERROR: object has no callback interface", eError);
return 0;
}
- status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&iEvent);
- if(status != TCL_OK)
- {
- SCWrite(pCon,"ERROR: failed to convert callback ID to int",eError);
+ status = Tcl_GetInt(InterpGetTcl(pSics), argv[3], &iEvent);
+ if (status != TCL_OK) {
+ SCWrite(pCon, "ERROR: failed to convert callback ID to int", eError);
return 0;
}
- RemoveCallback(pCall,(long)iEvent);
+ RemoveCallback(pCall, (long) iEvent);
SCSendOK(pCon);
return 1;
}
- SCWrite(pCon,"ERROR: subcommand to CallbackScript not known",eError);
+ SCWrite(pCon, "ERROR: subcommand to CallbackScript not known", eError);
return 0;
}
diff --git a/cell.c b/cell.c
index d9c73391..b0ba8958 100644
--- a/cell.c
+++ b/cell.c
@@ -16,11 +16,12 @@
#ifndef PI
#define PI (3.1415926536) /* pi */
#endif
-#define TWOPI (2*PI) /* 2*pi */
+#define TWOPI (2*PI) /* 2*pi */
/*****************************************************************************
* default value for a cell
****************************************************************************/
-void defaultCell(plattice cell){
+void defaultCell(plattice cell)
+{
cell->a = 1.;
cell->b = 1.;
cell->c = 1.;
@@ -28,6 +29,7 @@ void defaultCell(plattice cell){
cell->beta = 90.;
cell->gamma = 90.;
}
+
/*******************************************************************************
* Transform direct lattice to reciprocal lattice.
*******************************************************************************/
@@ -43,37 +45,39 @@ int directToReciprocalLattice(lattice direct, plattice reciprocal)
beta = direct.beta;
gamma = direct.gamma;
- cos_alfa = Cosd (alfa);
- cos_beta = Cosd (beta);
- cos_gamma = Cosd (gamma);
+ cos_alfa = Cosd(alfa);
+ cos_beta = Cosd(beta);
+ cos_gamma = Cosd(gamma);
- sin_alfa = Sind (alfa);
- sin_beta = Sind (beta);
- sin_gamma = Sind (gamma);
+ sin_alfa = Sind(alfa);
+ sin_beta = Sind(beta);
+ sin_gamma = Sind(gamma);
- reciprocal->alpha = Acosd ((cos_beta*cos_gamma - cos_alfa)/sin_beta/sin_gamma);
- reciprocal->beta =Acosd ((cos_alfa*cos_gamma - cos_beta)/sin_alfa/sin_gamma);
- reciprocal->gamma = Acosd ((cos_alfa*cos_beta - cos_gamma)/sin_alfa/sin_beta);
+ reciprocal->alpha =
+ Acosd((cos_beta * cos_gamma - cos_alfa) / sin_beta / sin_gamma);
+ reciprocal->beta =
+ Acosd((cos_alfa * cos_gamma - cos_beta) / sin_alfa / sin_gamma);
+ reciprocal->gamma =
+ Acosd((cos_alfa * cos_beta - cos_gamma) / sin_alfa / sin_beta);
ad = direct.a;
bd = direct.b;
cd = direct.c;
- arg = 1 + 2*cos_alfa*cos_beta*cos_gamma - cos_alfa*cos_alfa -
- cos_beta*cos_beta -
- cos_gamma*cos_gamma;
- if (arg < 0.0)
- {
- return REC_NO_VOLUME;
- }
+ arg = 1 + 2 * cos_alfa * cos_beta * cos_gamma - cos_alfa * cos_alfa -
+ cos_beta * cos_beta - cos_gamma * cos_gamma;
+ if (arg < 0.0) {
+ return REC_NO_VOLUME;
+ }
- vol = ad*bd*cd*sqrt (arg);
- reciprocal->a = bd*cd*sin_alfa/vol;
- reciprocal->b = ad*cd*sin_beta/vol;
- reciprocal->c = bd*ad*sin_gamma/vol;
+ vol = ad * bd * cd * sqrt(arg);
+ reciprocal->a = bd * cd * sin_alfa / vol;
+ reciprocal->b = ad * cd * sin_beta / vol;
+ reciprocal->c = bd * ad * sin_gamma / vol;
return (0);
}
+
/*******************************************************************************
* Transform reciprocal lattice to direct lattice.
*******************************************************************************/
@@ -89,89 +93,94 @@ int reciprocalToDirectLattice(lattice reciprocal, plattice direct)
beta = reciprocal.beta;
gamma = reciprocal.gamma;
- cos_alfa = Cosd (alfa);
- cos_beta = Cosd (beta);
- cos_gamma = Cosd (gamma);
+ cos_alfa = Cosd(alfa);
+ cos_beta = Cosd(beta);
+ cos_gamma = Cosd(gamma);
- sin_alfa = Sind (alfa);
- sin_beta = Sind (beta);
- sin_gamma = Sind (gamma);
+ sin_alfa = Sind(alfa);
+ sin_beta = Sind(beta);
+ sin_gamma = Sind(gamma);
- direct->alpha = Acosd ((cos_beta*cos_gamma - cos_alfa)/sin_beta/sin_gamma);
- direct->beta = Acosd ((cos_alfa*cos_gamma - cos_beta)/sin_alfa/sin_gamma);
- direct->gamma = Acosd ((cos_alfa*cos_beta - cos_gamma)/sin_alfa/sin_beta);
+ direct->alpha =
+ Acosd((cos_beta * cos_gamma - cos_alfa) / sin_beta / sin_gamma);
+ direct->beta =
+ Acosd((cos_alfa * cos_gamma - cos_beta) / sin_alfa / sin_gamma);
+ direct->gamma =
+ Acosd((cos_alfa * cos_beta - cos_gamma) / sin_alfa / sin_beta);
ar = reciprocal.a;
br = reciprocal.b;
cr = reciprocal.c;
- arg = 1 + 2*cos_alfa*cos_beta*cos_gamma - cos_alfa*cos_alfa -
- cos_beta*cos_beta -
- cos_gamma*cos_gamma;
- if (arg < 0.0)
- {
- return REC_NO_VOLUME;
- }
+ arg = 1 + 2 * cos_alfa * cos_beta * cos_gamma - cos_alfa * cos_alfa -
+ cos_beta * cos_beta - cos_gamma * cos_gamma;
+ if (arg < 0.0) {
+ return REC_NO_VOLUME;
+ }
- vol = ar*br*cr*sqrt (arg);
- direct->a = br*cr*sin_alfa/vol;
- direct->b = ar*cr*sin_beta/vol;
- direct->c = br*ar*sin_gamma/vol;
+ vol = ar * br * cr * sqrt(arg);
+ direct->a = br * cr * sin_alfa / vol;
+ direct->b = ar * cr * sin_beta / vol;
+ direct->c = br * ar * sin_gamma / vol;
return (0);
}
+
/***************************************************************************************
* Build a B matrix
***************************************************************************************/
-int calculateBMatrix(lattice direct, MATRIX B) {
+int calculateBMatrix(lattice direct, MATRIX B)
+{
lattice reciprocal;
int status;
assert(MatRow(B) == 3);
assert(MatCol(B) == 3);
- status = directToReciprocalLattice(direct,&reciprocal);
- if(status < 0) {
+ status = directToReciprocalLattice(direct, &reciprocal);
+ if (status < 0) {
return status;
}
-
- mat_fill(B,ZERO_MATRIX);
-
- /*
- top row
- */
- B[0][0] = reciprocal.a;
- B[0][1] = reciprocal.b*Cosd(reciprocal.gamma);
- B[0][2] = reciprocal.c*Cosd(reciprocal.beta);
+
+ mat_fill(B, ZERO_MATRIX);
/*
- middle row
- */
- B[1][1] = reciprocal.b*Sind(reciprocal.gamma);
- B[1][2] = -reciprocal.c*Sind(reciprocal.beta)*Cosd(direct.alpha);
-
+ top row
+ */
+ B[0][0] = reciprocal.a;
+ B[0][1] = reciprocal.b * Cosd(reciprocal.gamma);
+ B[0][2] = reciprocal.c * Cosd(reciprocal.beta);
+
/*
- bottom row
- */
- B[2][2] = 1./direct.c;
-
+ middle row
+ */
+ B[1][1] = reciprocal.b * Sind(reciprocal.gamma);
+ B[1][2] = -reciprocal.c * Sind(reciprocal.beta) * Cosd(direct.alpha);
+
+ /*
+ bottom row
+ */
+ B[2][2] = 1. / direct.c;
+
return 1;
}
+
/*--------------------------------------------------------------------------*/
-int cellFromUB(MATRIX UB, plattice direct){
+int cellFromUB(MATRIX UB, plattice direct)
+{
MATRIX UBTRANS, GINV, G;
UBTRANS = mat_tran(UB);
- if(UBTRANS == NULL){
+ if (UBTRANS == NULL) {
return CELLNOMEMORY;
}
- GINV = mat_mul(UBTRANS,UB);
- if(GINV == NULL){
+ GINV = mat_mul(UBTRANS, UB);
+ if (GINV == NULL) {
mat_free(UBTRANS);
return CELLNOMEMORY;
}
G = mat_inv(GINV);
- if(G == NULL){
+ if (G == NULL) {
mat_free(UBTRANS);
mat_free(GINV);
return CELLNOMEMORY;
@@ -179,9 +188,8 @@ int cellFromUB(MATRIX UB, plattice direct){
direct->a = sqrt(G[0][0]);
direct->b = sqrt(G[1][1]);
direct->c = sqrt(G[2][2]);
- direct->alpha = Acosd(G[1][2]/(direct->b * direct->c));
- direct->beta = Acosd(G[2][0]/(direct->a * direct->c));
- direct->gamma = Acosd(G[0][1]/(direct->a * direct->c));
+ direct->alpha = Acosd(G[1][2] / (direct->b * direct->c));
+ direct->beta = Acosd(G[2][0] / (direct->a * direct->c));
+ direct->gamma = Acosd(G[0][1] / (direct->a * direct->c));
return 1;
}
-
diff --git a/cell.h b/cell.h
index 40e74c2b..83ff02de 100644
--- a/cell.h
+++ b/cell.h
@@ -18,10 +18,10 @@
/**
* lattice parameters: either reciprocal or direct
*/
- typedef struct {
- double a,b,c;
- double alpha, beta, gamma;
- }lattice, *plattice;
+typedef struct {
+ double a, b, c;
+ double alpha, beta, gamma;
+} lattice, *plattice;
/**
* defaultCell assigns defualt values to cell parameters
* @param cell The lattice to assign default too
@@ -32,15 +32,15 @@ void defaultCell(plattice cell);
* @param direct The input direct cell parameters.
* @param reciprocal The output reciprocal cell constants
* @return 0 on success, > 0 else
- */
- int directToReciprocalLattice(lattice direct, plattice reciprocal);
+ */
+int directToReciprocalLattice(lattice direct, plattice reciprocal);
/**
* conversion from a reciprocal lattice to the directone.
* @param reciprocal The input reciprocal cell parameters.
* @param direct The output direct cell constants
* @return 0 on success, > 0 else
- */
- int reciprocalToDirectLattice(lattice reciprocal, plattice direct);
+ */
+int reciprocalToDirectLattice(lattice reciprocal, plattice direct);
/**
* calculate a crystallographic B matrix from the cell constants
* @param direct The direct cell lattice to calculate B from
diff --git a/chadapter.c b/chadapter.c
index 49f188c5..9e7d3237 100644
--- a/chadapter.c
+++ b/chadapter.c
@@ -24,488 +24,455 @@
#define NOTIMPLEMENTED -11555
/*-------------------------------------------------------------------------*/
- static void *AdapterGetInterface(void *pData, int iID)
- {
- pCHAdapter self = NULL;
-
- self = (pCHAdapter)pData;
- assert(self);
- if(iID == DRIVEID)
- {
- return self->pInt;
- }
- return NULL;
+static void *AdapterGetInterface(void *pData, int iID)
+{
+ pCHAdapter self = NULL;
+
+ self = (pCHAdapter) pData;
+ assert(self);
+ if (iID == DRIVEID) {
+ return self->pInt;
}
+ return NULL;
+}
+
/*-------------------------------------------------------------------------*/
- static int CHHalt(void *pData)
- {
- pCHAdapter self = NULL;
+static int CHHalt(void *pData)
+{
+ pCHAdapter self = NULL;
- self = (pCHAdapter)pData;
- assert(self);
+ self = (pCHAdapter) pData;
+ assert(self);
- self->pDriv->Halt(self->pDriv);
+ self->pDriv->Halt(self->pDriv);
+
+ return 1;
+}
- return 1;
- }
/*-------------------------------------------------------------------------*/
- static int CHLimits(void *pData, float fVal, char *error, int iErrlen)
- {
- pCHAdapter self = NULL;
+static int CHLimits(void *pData, float fVal, char *error, int iErrlen)
+{
+ pCHAdapter self = NULL;
- self = (pCHAdapter)pData;
- assert(self);
+ self = (pCHAdapter) pData;
+ assert(self);
- if(fVal < self->fLower)
- {
- strncpy(error,"Lower limit violated",iErrlen);
- return 0;
- }
- if(fVal > self->fUpper)
- {
- strncpy(error,"Upper limit violated",iErrlen);
- return 0;
- }
- return 1;
+ if (fVal < self->fLower) {
+ strlcpy(error, "Lower limit violated", iErrlen);
+ return 0;
}
+ if (fVal > self->fUpper) {
+ strlcpy(error, "Upper limit violated", iErrlen);
+ return 0;
+ }
+ return 1;
+}
+
/*------------------------------------------------------------------------*/
- static float CHGetValue(void *pData, SConnection *pCon)
- {
- pCHAdapter self = NULL;
- float fVal;
- int iRet;
- char pBueffel[80];
+static float CHGetValue(void *pData, SConnection * pCon)
+{
+ pCHAdapter self = NULL;
+ float fVal;
+ int iRet;
+ char pBueffel[80];
- self = (pCHAdapter)pData;
- assert(self);
+ self = (pCHAdapter) pData;
+ assert(self);
- iRet = self->pDriv->GetPar(self->pDriv,self->pParName,pBueffel,79);
- if(!iRet)
- {
- fVal = -9999999.99;
- self->pDriv->GetError(self->pDriv,&iRet,pBueffel,79);
- SCWrite(pCon,pBueffel,eError);
- return fVal;
- }
- sscanf(pBueffel,"%f",&fVal);
- return fVal;
+ iRet = self->pDriv->GetPar(self->pDriv, self->pParName, pBueffel, 79);
+ if (!iRet) {
+ fVal = -9999999.99;
+ self->pDriv->GetError(self->pDriv, &iRet, pBueffel, 79);
+ SCWrite(pCon, pBueffel, eError);
+ return fVal;
}
+ sscanf(pBueffel, "%f", &fVal);
+ return fVal;
+}
+
/*-----------------------------------------------------------------------*/
- static int CHStatus(void *pData, SConnection *pCon)
- {
- pCHAdapter self = NULL;
- int iRet, iCode;
- static int iRetry = 0;
- char pBueffel[80], pError[132];
+static int CHStatus(void *pData, SConnection * pCon)
+{
+ pCHAdapter self = NULL;
+ int iRet, iCode;
+ static int iRetry = 0;
+ char pBueffel[80], pError[132];
- self = (pCHAdapter)pData;
- assert(self);
+ self = (pCHAdapter) pData;
+ assert(self);
- iRet = self->pDriv->CheckPar(self->pDriv,self->pParName);
- switch(iRet)
- {
- case OKOK:
- case HWIdle:
- iRetry = 0;
- return HWIdle;
- case HWFault:
- self->pDriv->GetError(self->pDriv,&iCode,pBueffel,79);
- iRet = self->pDriv->TryFixIt(self->pDriv,iCode);
- sprintf(pError,"ERROR: %s",pBueffel);
- SCWrite(pCon,pError,eError);
- if(iRet == CHFAIL || iRetry >= 3)
- {
- iRetry = 0;
- return HWFault;
- }
- else
- {
- iRetry++;
- self->pDriv->SetPar(self->pDriv,self->pParName,
- self->fTarget);
- return HWBusy;
- }
- break;
- case HWBusy:
- return HWBusy;
- }
- return HWFault;
+ iRet = self->pDriv->CheckPar(self->pDriv, self->pParName);
+ switch (iRet) {
+ case OKOK:
+ case HWIdle:
+ iRetry = 0;
+ return HWIdle;
+ case HWFault:
+ self->pDriv->GetError(self->pDriv, &iCode, pBueffel, 79);
+ iRet = self->pDriv->TryFixIt(self->pDriv, iCode);
+ snprintf(pError,131, "ERROR: %s", pBueffel);
+ SCWrite(pCon, pError, eError);
+ if (iRet == CHFAIL || iRetry >= 3) {
+ iRetry = 0;
+ return HWFault;
+ } else {
+ iRetry++;
+ self->pDriv->SetPar(self->pDriv, self->pParName, self->fTarget);
+ return HWBusy;
+ }
+ break;
+ case HWBusy:
+ return HWBusy;
}
+ return HWFault;
+}
+
/*-------------------------------------------------------------------------*/
- static long CHSetValue(void *pData, SConnection *pCon, float fValue)
- {
- pCHAdapter self = NULL;
- char pBueffel[80], pError[132];
- int iRet, iCode, i;
+static long CHSetValue(void *pData, SConnection * pCon, float fValue)
+{
+ pCHAdapter self = NULL;
+ char pBueffel[80], pError[132];
+ int iRet, iCode, i;
- self = (pCHAdapter)pData;
- assert(self);
+ self = (pCHAdapter) pData;
+ assert(self);
- /* check privilege */
- if(!SCMatchRights(pCon,usUser))
- {
- SCWrite(pCon,"ERROR: Insufficient privilege for driving",eError);
- return 0;
- }
-
- for(i = 0; i < 3; i++)
- {
- iRet = self->pDriv->SetPar(self->pDriv,self->pParName,fValue);
- if(iRet)
- {
- self->fTarget = fValue;
- return 1;
- }
- self->pDriv->GetError(self->pDriv,&iCode,pBueffel,79);
- sprintf(pError,"ERROR: %s",pBueffel);
- SCWrite(pCon,pError,eError);
- iRet = self->pDriv->TryFixIt(self->pDriv,iCode);
- if(iRet == CHFAIL)
- return 0;
- }
- return 0;
- }
-/*------------------------------------------------------------------------*/
- static void KillAdapter(void *pData)
- {
- pCHAdapter self = NULL;
-
- self = (pCHAdapter)pData;
- if(!self)
- return;
-
- if(self->pDes)
- DeleteDescriptor(self->pDes);
-
- if(self->pInt)
- free(self->pInt);
-
- if(self->pParName)
- free(self->pParName);
-
- free(self);
+ /* check privilege */
+ if (!SCMatchRights(pCon, usUser)) {
+ SCWrite(pCon, "ERROR: Insufficient privilege for driving", eError);
+ return 0;
}
+
+ for (i = 0; i < 3; i++) {
+ iRet = self->pDriv->SetPar(self->pDriv, self->pParName, fValue);
+ if (iRet) {
+ self->fTarget = fValue;
+ return 1;
+ }
+ self->pDriv->GetError(self->pDriv, &iCode, pBueffel, 79);
+ sprintf(pError, "ERROR: %s", pBueffel);
+ SCWrite(pCon, pError, eError);
+ iRet = self->pDriv->TryFixIt(self->pDriv, iCode);
+ if (iRet == CHFAIL)
+ return 0;
+ }
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+static void KillAdapter(void *pData)
+{
+ pCHAdapter self = NULL;
+
+ self = (pCHAdapter) pData;
+ if (!self)
+ return;
+
+ if (self->pDes)
+ DeleteDescriptor(self->pDes);
+
+ if (self->pInt)
+ free(self->pInt);
+
+ if (self->pParName);
+ free(self->pParName);
+
+ free(self);
+}
+
/*-----------------------------------------------------------------------
Syntax: ChopperAdapter name choppercontroller parname upper lower
*/
- int CHAdapterFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- char pBueffel[256];
- pCHAdapter pNew = NULL;
- pChoco pChopper = NULL;
- CommandList *pCom = NULL;
- pDummy pDum = NULL;
- double dUpper, dLower;
- int iRet;
+int CHAdapterFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ char pBueffel[256];
+ pCHAdapter pNew = NULL;
+ pChoco pChopper = NULL;
+ CommandList *pCom = NULL;
+ pDummy pDum = NULL;
+ double dUpper, dLower;
+ int iRet;
- /* do we have enough arguments? */
- if(argc < 6)
- {
- SCWrite(pCon,
- "ERROR: Insufficient number of arguments to ChopperAdapter",
+ /* do we have enough arguments? */
+ if (argc < 6) {
+ SCWrite(pCon,
+ "ERROR: Insufficient number of arguments to ChopperAdapter",
eError);
- return 0;
- }
-
- /* find the chopper first */
- pCom = FindCommand(pSics,argv[2]);
- if(pCom)
- {
- pDum = (pDummy)pCom->pData;
- if(pDum)
- {
- if(strcmp(pDum->pDescriptor->name,"Chopper") == 0)
- {
- pChopper = (pChoco)pCom->pData;
- }
- }
- }
- if(!pChopper)
- {
- sprintf(pBueffel,"ERROR: %s is NO chopper controller",
- argv[3]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
- /* interpret limits */
- iRet = Tcl_GetDouble(pSics->pTcl,argv[5],&dUpper);
- if(iRet != TCL_OK)
- {
- sprintf(pBueffel,
- "ERROR: expected numeric argument for upper limit, got %s",
- argv[4]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dLower);
- if(iRet != TCL_OK)
- {
- sprintf(pBueffel,
- "ERROR: expected numeric argument for lower limit, got %s",
- argv[5]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
- /* allocate new adapter data structure */
- pNew = (pCHAdapter)malloc(sizeof(CHAdapter));
- if(!pNew)
- {
- SCWrite(pCon,"ERROR: out of memory in ChopperAdapter",eError);
- return 0;
- }
- memset(pNew,0,sizeof(CHAdapter));
-
- pNew->pDes = CreateDescriptor("ChopperAdapter");
- pNew->pDriv = CHGetDriver(pChopper);
- pNew->pInt = CreateDrivableInterface();
- pNew->pParName = strdup(argv[3]);
- if( !pNew->pDes || !pNew->pDriv || !pNew->pInt || !pNew->pParName)
- {
- SCWrite(pCon,"ERROR: out of memory in ChopperAdapter",eError);
- return 0;
- }
-
- /* initialize other fields */
- pNew->fTarget = 0.;
- pNew->fLower = (float)dLower;
- pNew->fUpper = (float)dUpper;
- pNew->pDes->GetInterface = AdapterGetInterface;
- pNew->pInt->Halt = CHHalt;
- pNew->pInt->CheckLimits = CHLimits;
- pNew->pInt->SetValue = CHSetValue;
- pNew->pInt->CheckStatus = CHStatus;
- pNew->pInt->GetValue = CHGetValue;
-
- /* install command */
- iRet = AddCommand(pSics, argv[1],CHAdapterAction,KillAdapter,pNew);
- if(!iRet)
- {
- sprintf(pBueffel,
- "ERROR: duplicate ChopperAdapter command %s NOT created",
- argv[1]);
- SCWrite(pCon,pBueffel,eError);
- KillAdapter(pNew);
- return 0;
- }
- return 1;
+ return 0;
}
+
+ /* find the chopper first */
+ pCom = FindCommand(pSics, argv[2]);
+ if (pCom) {
+ pDum = (pDummy) pCom->pData;
+ if (pDum) {
+ if (strcmp(pDum->pDescriptor->name, "Chopper") == 0) {
+ pChopper = (pChoco) pCom->pData;
+ }
+ }
+ }
+ if (!pChopper) {
+ snprintf(pBueffel,255, "ERROR: %s is NO chopper controller", argv[3]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+ /* interpret limits */
+ iRet = Tcl_GetDouble(pSics->pTcl, argv[5], &dUpper);
+ if (iRet != TCL_OK) {
+ snprintf(pBueffel,255,
+ "ERROR: expected numeric argument for upper limit, got %s",
+ argv[4]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ iRet = Tcl_GetDouble(pSics->pTcl, argv[4], &dLower);
+ if (iRet != TCL_OK) {
+ snprintf(pBueffel,255,
+ "ERROR: expected numeric argument for lower limit, got %s",
+ argv[5]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+ /* allocate new adapter data structure */
+ pNew = (pCHAdapter) malloc(sizeof(CHAdapter));
+ if (!pNew) {
+ SCWrite(pCon, "ERROR: out of memory in ChopperAdapter", eError);
+ return 0;
+ }
+ memset(pNew, 0, sizeof(CHAdapter));
+
+ pNew->pDes = CreateDescriptor("ChopperAdapter");
+ pNew->pDriv = CHGetDriver(pChopper);
+ pNew->pInt = CreateDrivableInterface();
+ pNew->pParName = strdup(argv[3]);
+ if (!pNew->pDes || !pNew->pDriv || !pNew->pInt || !pNew->pParName) {
+ SCWrite(pCon, "ERROR: out of memory in ChopperAdapter", eError);
+ return 0;
+ }
+
+ /* initialize other fields */
+ pNew->fTarget = 0.;
+ pNew->fLower = (float) dLower;
+ pNew->fUpper = (float) dUpper;
+ pNew->pDes->GetInterface = AdapterGetInterface;
+ pNew->pInt->Halt = CHHalt;
+ pNew->pInt->CheckLimits = CHLimits;
+ pNew->pInt->SetValue = CHSetValue;
+ pNew->pInt->CheckStatus = CHStatus;
+ pNew->pInt->GetValue = CHGetValue;
+
+ /* install command */
+ iRet = AddCommand(pSics, argv[1], CHAdapterAction, KillAdapter, pNew);
+ if (!iRet) {
+ snprintf(pBueffel,255,
+ "ERROR: duplicate ChopperAdapter command %s NOT created",
+ argv[1]);
+ SCWrite(pCon, pBueffel, eError);
+ KillAdapter(pNew);
+ return 0;
+ }
+ return 1;
+}
+
/*------------------------------------------------------------------------*/
- int CHAdapterAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pCHAdapter self = NULL;
- int iRet;
- char pBueffel[132];
- float fValue;
+int CHAdapterAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pCHAdapter self = NULL;
+ int iRet;
+ char pBueffel[132];
+ float fValue;
- self = (pCHAdapter)pData;
- assert(self);
+ self = (pCHAdapter) pData;
+ assert(self);
- /* only action: get value */
- fValue = CHGetValue(self,pCon);
- if(fValue < -99000)
- {
- return 0;
- }
- else
- {
- sprintf(pBueffel,"%s = %f",argv[0],fValue);
- SCWrite(pCon,pBueffel,eValue);
- }
-
- return 1;
+ /* only action: get value */
+ fValue = CHGetValue(self, pCon);
+ if (fValue < -99000) {
+ return 0;
+ } else {
+ sprintf(pBueffel, "%s = %f", argv[0], fValue);
+ SCWrite(pCon, pBueffel, eValue);
}
+
+ return 1;
+}
+
/*=========================================================================
An environment driver based on top of a controller object.
-------------------------------------------------------------------------*/
- static int AVEVSetValue(pEVDriver self, float fNew)
- {
- pCHev myData;
+static int AVEVSetValue(pEVDriver self, float fNew)
+{
+ pCHev myData;
- assert(self);
- myData = (pCHev)self->pPrivate;
- assert(myData);
- myData->iLastError = 0;
+ assert(self);
+ myData = (pCHev) self->pPrivate;
+ assert(myData);
+ myData->iLastError = 0;
+
+ return myData->pDriv->SetPar(myData->pDriv, myData->pParName, fNew);
+}
- return myData->pDriv->SetPar(myData->pDriv,myData->pParName,fNew);
- }
/*-----------------------------------------------------------------------*/
- static int AVEVGetValue(pEVDriver self, float *fNew)
- {
- pCHev myData;
- int iRet;
- char pBueffel[80];
+static int AVEVGetValue(pEVDriver self, float *fNew)
+{
+ pCHev myData;
+ int iRet;
+ char pBueffel[80];
- assert(self);
- myData = (pCHev)self->pPrivate;
- assert(myData);
+ assert(self);
+ myData = (pCHev) self->pPrivate;
+ assert(myData);
+
+ iRet = myData->pDriv->GetPar(myData->pDriv, myData->pParName,
+ pBueffel, 79);
+ sscanf(pBueffel, "%f", fNew);
+ return iRet;
+}
- iRet = myData->pDriv->GetPar(myData->pDriv,myData->pParName,
- pBueffel,79);
- sscanf(pBueffel,"%f",fNew);
- return iRet;
- }
/*-----------------------------------------------------------------------*/
- static int AVEVSend(pEVDriver self, char *pCommand,
- char *pReply, int iLen)
- {
- pCHev myData;
+static int AVEVSend(pEVDriver self, char *pCommand, char *pReply, int iLen)
+{
+ pCHev myData;
- assert(self);
- myData = (pCHev)self->pPrivate;
- assert(myData);
- myData->iLastError = NOTIMPLEMENTED;
+ assert(self);
+ myData = (pCHev) self->pPrivate;
+ assert(myData);
+ myData->iLastError = NOTIMPLEMENTED;
+
+ return 0;
+}
- return 0;
- }
/*-----------------------------------------------------------------------*/
- static int AVEVGetError(pEVDriver self, int *iCode,
- char *pReply, int iLen)
- {
- pCHev myData;
+static int AVEVGetError(pEVDriver self, int *iCode, char *pReply, int iLen)
+{
+ pCHev myData;
- assert(self);
- myData = (pCHev)self->pPrivate;
- assert(myData);
+ assert(self);
+ myData = (pCHev) self->pPrivate;
+ assert(myData);
+
+ if (myData->iLastError == NOTIMPLEMENTED) {
+ strlcpy(pReply, "ERROR: Not Implemented here!", iLen);
+ *iCode = NOTIMPLEMENTED;
+ myData->iLastError = 0;
+ return 1;
+ } else {
+ return myData->pDriv->GetError(myData->pDriv, iCode, pReply, iLen);
+ }
+}
- if(myData->iLastError == NOTIMPLEMENTED)
- {
- strncpy(pReply,"ERROR: Not Implemented here!", iLen);
- *iCode = NOTIMPLEMENTED;
- myData->iLastError = 0;
- return 1;
- }
- else
- {
- return myData->pDriv->GetError(myData->pDriv, iCode,
- pReply, iLen);
- }
- }
/*------------------------------------------------------------------------*/
- static int AVEVTryFixIt(pEVDriver self, int iCode)
- {
- pCHev myData;
+static int AVEVTryFixIt(pEVDriver self, int iCode)
+{
+ pCHev myData;
- assert(self);
- myData = (pCHev)self->pPrivate;
- assert(myData);
+ assert(self);
+ myData = (pCHev) self->pPrivate;
+ assert(myData);
+
+ if (iCode == NOTIMPLEMENTED) {
+ return DEVFAULT;
+ } else {
+ return myData->pDriv->TryFixIt(myData->pDriv, iCode);
+ }
+}
- if(iCode == NOTIMPLEMENTED)
- {
- return DEVFAULT;
- }
- else
- {
- return myData->pDriv->TryFixIt(myData->pDriv, iCode);
- }
- }
/*---------------------------------------------------------------------*/
- static int AVEVInit(pEVDriver self)
- {
- pCHev myData;
+static int AVEVInit(pEVDriver self)
+{
+ pCHev myData;
- assert(self);
- myData = (pCHev)self->pPrivate;
- assert(myData);
+ assert(self);
+ myData = (pCHev) self->pPrivate;
+ assert(myData);
+
+ return myData->pDriv->Init(myData->pDriv);
+}
- return myData->pDriv->Init(myData->pDriv);
- }
/*---------------------------------------------------------------------*/
- static int AVEVClose(pEVDriver self)
- {
- pCHev myData;
+static int AVEVClose(pEVDriver self)
+{
+ pCHev myData;
- assert(self);
- myData = (pCHev)self->pPrivate;
- assert(myData);
+ assert(self);
+ myData = (pCHev) self->pPrivate;
+ assert(myData);
+
+ return myData->pDriv->Close(myData->pDriv);
+}
- return myData->pDriv->Close(myData->pDriv);
- }
/*----------------------------------------------------------------------*/
- static void AVEVKillPrivate(void *pData)
- {
- pCHev myData;
+static void AVEVKillPrivate(void *pData)
+{
+ pCHev myData;
+
+ if (pData != NULL) {
+ myData = (pCHev) pData;
+ if (myData != NULL) {
+ if (myData->pParName)
+ free(myData->pParName);
+ free(myData);
+ }
+ }
+}
- if(pData != NULL)
- {
- myData = (pCHev)pData;
- if(myData != NULL)
- {
- if(myData->pParName)
- free(myData->pParName);
- free(myData);
- }
- }
- }
/*---------------------------------------------------------------------*/
- pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[])
- {
- pEVDriver pNew = NULL;
- pCHev myData = NULL;
- CommandList *pCom = NULL;
- pDummy pDum = NULL;
- pChoco pChop;
-
- /*
- Two arguments are needed: the name of the controller and the
- name of the parameter
- */
- if(argc < 2)
- {
- return NULL;
- }
- pCom = FindCommand(pServ->pSics,argv[0]);
- if(!pCom)
- {
- return NULL;
- }
- pDum = pCom->pData;
- if(!pDum)
- {
- return NULL;
- }
- if(strcmp(pDum->pDescriptor->name,"Chopper") != 0)
- {
- return NULL;
- }
-
- /* alright: I think we got a controller now, let us create our
- act
- */
- pNew = CreateEVDriver(argc,argv);
- if(!pNew)
- {
- return NULL;
- }
- myData = (pCHev)malloc(sizeof(CHev));
- if(!myData)
- {
- return NULL;
- }
-
- pChop = (pChoco)pCom->pData;
- myData->iLastError = 0;
- myData->pDriv = pChop->pDriv;
- myData->pParName = strdup(argv[1]);
- pNew->pPrivate = myData;
- pNew->SetValue =AVEVSetValue;
- pNew->GetValue =AVEVGetValue;
- pNew->Send = AVEVSend;
- pNew->GetError =AVEVGetError;
- pNew->TryFixIt =AVEVTryFixIt;
- pNew->Init =AVEVInit;
- pNew->Close =AVEVClose;
- pNew->KillPrivate =AVEVKillPrivate;
-
- return pNew;
- }
-
-
-
+pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[])
+{
+ pEVDriver pNew = NULL;
+ pCHev myData = NULL;
+ CommandList *pCom = NULL;
+ pDummy pDum = NULL;
+ pChoco pChop;
+ /*
+ Two arguments are needed: the name of the controller and the
+ name of the parameter
+ */
+ if (argc < 2) {
+ return NULL;
+ }
+ pCom = FindCommand(pServ->pSics, argv[0]);
+ if (!pCom) {
+ return NULL;
+ }
+ pDum = pCom->pData;
+ if (!pDum) {
+ return NULL;
+ }
+ if (strcmp(pDum->pDescriptor->name, "Chopper") != 0) {
+ return NULL;
+ }
+ /* alright: I think we got a controller now, let us create our
+ act
+ */
+ pNew = CreateEVDriver(argc, argv);
+ if (!pNew) {
+ return NULL;
+ }
+ myData = (pCHev) malloc(sizeof(CHev));
+ if (!myData) {
+ return NULL;
+ }
+ pChop = (pChoco) pCom->pData;
+ myData->iLastError = 0;
+ myData->pDriv = pChop->pDriv;
+ myData->pParName = strdup(argv[1]);
+ pNew->pPrivate = myData;
+ pNew->SetValue = AVEVSetValue;
+ pNew->GetValue = AVEVGetValue;
+ pNew->Send = AVEVSend;
+ pNew->GetError = AVEVGetError;
+ pNew->TryFixIt = AVEVTryFixIt;
+ pNew->Init = AVEVInit;
+ pNew->Close = AVEVClose;
+ pNew->KillPrivate = AVEVKillPrivate;
+ return pNew;
+}
diff --git a/chadapter.h b/chadapter.h
index ec3319f8..83cd822a 100644
--- a/chadapter.h
+++ b/chadapter.h
@@ -11,37 +11,35 @@
#define SICSCHADA
#include "codri.h"
- typedef struct __CHADAPTER *pCHAdapter;
+typedef struct __CHADAPTER *pCHAdapter;
/*-----------------------------------------------------------------------*/
- int CHAdapterFactory(SConnection *pCon, SicsInterp *pSics,
- void *pData,
- int argc, char *argv[]);
-
- int CHAdapterAction(SConnection *pCon, SicsInterp *pSics,
- void *pData,
- int argc, char *argv[]);
+int CHAdapterFactory(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[]);
+
+int CHAdapterAction(SConnection * pCon, SicsInterp * pSics,
+ void *pData, int argc, char *argv[]);
+
+pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[]);
- pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[]);
-
#ifdef CHADAINTERNAL
- typedef struct __CHADAPTER {
- pObjectDescriptor pDes;
- pCodri pDriv;
- pIDrivable pInt;
- float fUpper;
- float fLower;
- float fTarget;
- char *pParName;
- }CHAdapter;
+typedef struct __CHADAPTER {
+ pObjectDescriptor pDes;
+ pCodri pDriv;
+ pIDrivable pInt;
+ float fUpper;
+ float fLower;
+ float fTarget;
+ char *pParName;
+} CHAdapter;
- typedef struct __CHEV {
- char *pParName;
- pCodri pDriv;
- int iLastError;
- }CHev, *pCHev;
+typedef struct __CHEV {
+ char *pParName;
+ pCodri pDriv;
+ int iLastError;
+} CHev, *pCHev;
#endif
#endif
diff --git a/choco.c b/choco.c
index 65ca8d01..4fba277f 100644
--- a/choco.c
+++ b/choco.c
@@ -17,234 +17,209 @@
#include "choco.h"
-
+
/*------------------------------------------------------------------------*/
- int CHGetParameter(pChoco self, char *parname, char *pParValue,
- int iBuflen)
- {
- int iRet, iCode;
+int CHGetParameter(pChoco self, char *parname, char *pParValue,
+ int iBuflen)
+{
+ int iRet, iCode;
- assert(self);
+ assert(self);
- iRet = self->pDriv->GetPar(self->pDriv, parname, pParValue,
- iBuflen);
- if(!iRet)
- {
- iRet = 0;
- self->pDriv->GetError(self->pDriv,&iCode,pParValue, iBuflen);
- }
- return iRet;
+ iRet = self->pDriv->GetPar(self->pDriv, parname, pParValue, iBuflen);
+ if (!iRet) {
+ iRet = 0;
+ self->pDriv->GetError(self->pDriv, &iCode, pParValue, iBuflen);
}
+ return iRet;
+}
+
/*------------------------------------------------------------------------*/
- pCodri CHGetDriver(pChoco self)
- {
- assert(self);
-
- return self->pDriv;
+pCodri CHGetDriver(pChoco self)
+{
+ assert(self);
+
+ return self->pDriv;
+}
+
+/*------------------------------------------------------------------------*/
+int CHList(pChoco self, SConnection * pCon, char *name)
+{
+ char *pPar, *pCopy = NULL;
+ char pValue[80];
+ char pMessage[256];
+ int iRet, iLen;
+ Tcl_DString tlist;
+
+ assert(self);
+
+ /* copy pParList as it will be destroyed by strtok */
+ iLen = strlen(self->pDriv->pParList);
+ pCopy = (char *) malloc((iLen + 10) * sizeof(char));
+ if (!pCopy) {
+ SCWrite(pCon, "ERROR: out of memory in CHList", eError);
+ return 0;
}
-/*------------------------------------------------------------------------*/
- int CHList(pChoco self, SConnection *pCon, char *name)
- {
- char *pPar, *pCopy = NULL;
- char pValue[80];
- char pMessage[256];
- int iRet, iLen;
- Tcl_DString tlist;
+ memset(pCopy, 0, iLen + 10);
+ strcpy(pCopy, self->pDriv->pParList);
+ Tcl_DStringInit(&tlist);
- assert(self);
-
- /* copy pParList as it will be destroyed by strtok */
- iLen = strlen(self->pDriv->pParList);
- pCopy = (char *)malloc((iLen+10)*sizeof(char));
- if(!pCopy)
- {
- SCWrite(pCon,"ERROR: out of memory in CHList",eError);
- return 0;
+ pPar = strtok(pCopy, ",");
+ while (pPar != NULL) {
+ iRet = CHGetParameter(self, pPar, pValue, 79);
+ if (iRet) {
+ sprintf(pMessage, "%s.%s = %s \n", name, pPar, pValue);
+ } else {
+ sprintf(pMessage, "ERROR: %s : while reading parameter %s \n",
+ pValue, pPar);
}
- memset(pCopy,0,iLen+10);
- strcpy(pCopy,self->pDriv->pParList);
- Tcl_DStringInit(&tlist);
-
- pPar = strtok(pCopy,",");
- while(pPar != NULL)
- {
- iRet = CHGetParameter(self,pPar,pValue,79);
- if(iRet)
- {
- sprintf(pMessage,"%s.%s = %s \n",name,pPar,pValue);
- }
- else
- {
- sprintf(pMessage,"ERROR: %s : while reading parameter %s \n",
- pValue,pPar);
- }
- Tcl_DStringAppend(&tlist, pMessage,-1);
- pPar = strtok(NULL,",");
- }
- SCWrite(pCon,Tcl_DStringValue(&tlist),eValue);
- Tcl_DStringFree(&tlist);
- free(pCopy);
- return 1;
+ Tcl_DStringAppend(&tlist, pMessage, -1);
+ pPar = strtok(NULL, ",");
}
+ SCWrite(pCon, Tcl_DStringValue(&tlist), eValue);
+ Tcl_DStringFree(&tlist);
+ free(pCopy);
+ return 1;
+}
+
/*-----------------------------------------------------------------------*/
- int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pChoco self = NULL;
- char pValue[80], pMessage[256];
- int iRet;
+int ChocoAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pChoco self = NULL;
+ char pValue[80], pMessage[256];
+ int iRet;
- self = (pChoco)pData;
- assert(self);
+ self = (pChoco) pData;
+ assert(self);
- if(argc < 2)
- {
- sprintf(pMessage, "ERROR: argument required for %s",argv[0]);
- SCWrite(pCon,pMessage,eError);
- return 0;
- }
-
- /* argument can either be list or parameter name */
- strtolower(argv[1]);
- if(strcmp(argv[1],"list") == 0)
- {
- return CHList(self,pCon,argv[0]);
- }
- else
- {
- if(argc > 2)
- {
- /* set case */
- iRet = self->pDriv->SetPar2(self->pDriv,argv[1],argv[2]);
- if(!iRet)
- {
- self->pDriv->GetError(self->pDriv,&iRet,pValue,79);
- sprintf(pMessage,"ERROR: %s",pValue);
- SCWrite(pCon,pMessage,eError);
- return 0;
- }
- else
- {
- SCSendOK(pCon);
- return 1;
- }
- }
- else
- {
- /* get case */
- iRet = CHGetParameter(self,argv[1],pValue,79);
- if(iRet)
- {
- sprintf(pMessage,"%s.%s = %s",argv[0],argv[1],pValue);
- }
- else
- {
- sprintf(pMessage,"ERROR: %s : while reading parameter %s",
- pValue,argv[1]);
- }
- SCWrite(pCon,pMessage,eValue);
- return iRet;
- }
- }
- return 0;
+ if (argc < 2) {
+ snprintf(pMessage,255, "ERROR: argument required for %s", argv[0]);
+ SCWrite(pCon, pMessage, eError);
+ return 0;
}
+
+ /* argument can either be list or parameter name */
+ strtolower(argv[1]);
+ if (strcmp(argv[1], "list") == 0) {
+ return CHList(self, pCon, argv[0]);
+ } else {
+ if (argc > 2) {
+ /* set case */
+ iRet = self->pDriv->SetPar2(self->pDriv, argv[1], argv[2]);
+ if (!iRet) {
+ self->pDriv->GetError(self->pDriv, &iRet, pValue, 79);
+ sprintf(pMessage, "ERROR: %s", pValue);
+ SCWrite(pCon, pMessage, eError);
+ return 0;
+ } else {
+ SCSendOK(pCon);
+ return 1;
+ }
+ } else {
+ /* get case */
+ iRet = CHGetParameter(self, argv[1], pValue, 79);
+ if (iRet) {
+ sprintf(pMessage, "%s.%s = %s", argv[0], argv[1], pValue);
+ } else {
+ sprintf(pMessage, "ERROR: %s : while reading parameter %s",
+ pValue, argv[1]);
+ }
+ SCWrite(pCon, pMessage, eValue);
+ return iRet;
+ }
+ }
+ return 0;
+}
+
/*----------------------------------------------------------------------*/
- void KillChoco(void *pData)
- {
- pChoco self = NULL;
+void KillChoco(void *pData)
+{
+ pChoco self = NULL;
- self = (pChoco)pData;
- if(!self)
- return;
+ self = (pChoco) pData;
+ if (!self)
+ return;
- if(self->pDriv)
- {
- self->pDriv->Close(self->pDriv);
- self->pDriv->Delete(self->pDriv);
- free(self->pDriv);
- }
- if(self->pDes)
- DeleteDescriptor(self->pDes);
-
- free(self);
+ if (self->pDriv) {
+ self->pDriv->Close(self->pDriv);
+ self->pDriv->Delete(self->pDriv);
+ free(self->pDriv);
}
+ if (self->pDes)
+ DeleteDescriptor(self->pDes);
+
+ free(self);
+}
+
/*-----------------------------------------------------------------------
DRIVERS
*/
extern pCodri MakeSimChopper(void);
/*-----------------------------------------------------------------------*/
- int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pChoco pNew = NULL;
- pCodri pDriv = NULL;
- pObjectDescriptor pDes = NULL;
- char pBueffel[132];
- int iRet, iPort, iChannel;
- int iSingle = 0;
- pSite site = NULL;
+int ChocoFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pChoco pNew = NULL;
+ pCodri pDriv = NULL;
+ pObjectDescriptor pDes = NULL;
+ char pBueffel[132];
+ int iRet, iPort, iChannel;
+ int iSingle = 0;
+ pSite site = NULL;
- if(argc < 3)
- {
- SCWrite(pCon,
+ if (argc < 3) {
+ SCWrite(pCon,
"ERROR: Insufficient number of arguments to MakeController",
- eError);
- return 0;
- }
-
-
- /* first try to get everything done */
- pNew = (pChoco)malloc(sizeof(Choco));
- pDes = CreateDescriptor("Chopper");
- /* do driver */
- strtolower(argv[2]);
- if(strcmp(argv[2],"sim") == 0)
- {
- pDriv = MakeSimChopper();
- }
- else
- {
- site = getSite();
- if(site != NULL){
- pDriv = site->CreateControllerDriver(pCon,argc-2,&argv[2]);
- } else {
- pDriv = NULL;
- }
- if(pDriv == NULL){
- sprintf(pBueffel,"ERROR: Driver %s NOT supported for MakeController",
- argv[2]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- }
- if( (pNew == NULL) || (pDes == NULL) || (pDriv == NULL) )
- {
- SCWrite(pCon,"ERROR: No memory left to create controller",eError);
- return 0;
- }
- pNew->pDes = pDes;
- pNew->pDriv = pDriv;
-
- /* initialize driver */
- iRet = pDriv->Init(pDriv);
- if(!iRet)
- {
- SCWrite(pCon,"ERROR: Failed to initialize driver",eError);
- KillChoco(pNew);
- return 0;
- }
-
- /* install as command */
- iRet = AddCommand(pSics, argv[1],ChocoAction,KillChoco,pNew);
- if(!iRet)
- {
- sprintf(pBueffel,"ERROR: duplicate command %s NOT created",
- argv[1]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- return 1;
+ eError);
+ return 0;
}
+ /* first try to get everything done */
+ pNew = (pChoco) malloc(sizeof(Choco));
+ pDes = CreateDescriptor("Chopper");
+ /* do driver */
+ strtolower(argv[2]);
+ if (strcmp(argv[2], "sim") == 0) {
+ pDriv = MakeSimChopper();
+ } else {
+ site = getSite();
+ if (site != NULL) {
+ pDriv = site->CreateControllerDriver(pCon, argc - 2, &argv[2]);
+ } else {
+ pDriv = NULL;
+ }
+ if (pDriv == NULL) {
+ snprintf(pBueffel,131,
+ "ERROR: Driver %s NOT supported for MakeController",
+ argv[2]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ }
+ if ((pNew == NULL) || (pDes == NULL) || (pDriv == NULL)) {
+ SCWrite(pCon, "ERROR: No memory left to create controller", eError);
+ return 0;
+ }
+ pNew->pDes = pDes;
+ pNew->pDriv = pDriv;
+
+ /* initialize driver */
+ iRet = pDriv->Init(pDriv);
+ if (!iRet) {
+ SCWrite(pCon, "ERROR: Failed to initialize driver", eError);
+ KillChoco(pNew);
+ return 0;
+ }
+
+ /* install as command */
+ iRet = AddCommand(pSics, argv[1], ChocoAction, KillChoco, pNew);
+ if (!iRet) {
+ snprintf(pBueffel, 131, "ERROR: duplicate command %s NOT created", argv[1]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ return 1;
+}
diff --git a/choco.h b/choco.h
index 94bbe7e2..3a9eff7a 100644
--- a/choco.h
+++ b/choco.h
@@ -11,27 +11,27 @@
#define CHOCOSICS
#include "codri.h"
- typedef struct __CHOCO *pChoco;
+typedef struct __CHOCO *pChoco;
/*------------------------------------------------------------------------*/
- int CHGetParameter(pChoco self, char *pParName,
- char *pParValue, int iBuflen);
-
- pCodri CHGetDriver(pChoco self);
- int CHList(pChoco self, SConnection *pCon, char *name);
+int CHGetParameter(pChoco self, char *pParName,
+ char *pParValue, int iBuflen);
+
+pCodri CHGetDriver(pChoco self);
+int CHList(pChoco self, SConnection * pCon, char *name);
/*------------------------------------------------------------------------*/
- void KillChoco(void *pData);
- int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
- int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
-
+void KillChoco(void *pData);
+int ChocoAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+int ChocoFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+
#ifdef CHOCOINTERNAL
- typedef struct __CHOCO {
- pObjectDescriptor pDes;
- pCodri pDriv;
- } Choco;
+typedef struct __CHOCO {
+ pObjectDescriptor pDes;
+ pCodri pDriv;
+} Choco;
#endif
-#endif
+#endif
diff --git a/circular.c b/circular.c
index 5a855a66..13597967 100644
--- a/circular.c
+++ b/circular.c
@@ -12,111 +12,111 @@
Definitions of Structures
*/
- typedef struct __CircularItem {
- void *pData;
- struct __CircularItem *next;
- struct __CircularItem *previous;
- }CircularItem, *pCircularItem;
+typedef struct __CircularItem {
+ void *pData;
+ struct __CircularItem *next;
+ struct __CircularItem *previous;
+} CircularItem, *pCircularItem;
- typedef struct __CIRCULAR {
- pCircularItem pPointer;
- CirKillFunc killer;
- }Circular;
+typedef struct __CIRCULAR {
+ pCircularItem pPointer;
+ CirKillFunc killer;
+} Circular;
/*=========================================================================
Functions for Birth and Death
*/
- pCircular createCircular(int iSize, CirKillFunc kf)
- {
- pCircular pNew = NULL;
- pCircularItem pItem = NULL, pFirst = NULL;
- int i;
-
-
- assert(iSize > 0);
+pCircular createCircular(int iSize, CirKillFunc kf)
+{
+ pCircular pNew = NULL;
+ pCircularItem pItem = NULL, pFirst = NULL;
+ int i;
- /* create data structure */
- pNew = (pCircular)malloc(sizeof(Circular));
- if(!pNew)
- return NULL;
- memset(pNew,0,sizeof(Circular));
- /* create all the members of the circular buffer */
- pItem = (pCircularItem)malloc(sizeof(CircularItem));
- if(!pItem)
- return NULL;
- memset(pItem,0,sizeof(CircularItem));
- pNew->pPointer = pItem;
- pFirst = pItem;
- for(i = 1; i < iSize; i++)
- {
- pItem = (pCircularItem)malloc(sizeof(CircularItem));
- if(!pItem)
- return NULL;
- memset(pItem,0,sizeof(CircularItem));
- pItem->previous = pNew->pPointer;
- pNew->pPointer->next = pItem;
- pNew->pPointer = pItem;
- }
- pItem->next = pFirst;
- pFirst->previous = pItem;
- pNew->killer = kf;
- return pNew;
+ assert(iSize > 0);
+
+ /* create data structure */
+ pNew = (pCircular) malloc(sizeof(Circular));
+ if (!pNew)
+ return NULL;
+ memset(pNew, 0, sizeof(Circular));
+
+ /* create all the members of the circular buffer */
+ pItem = (pCircularItem) malloc(sizeof(CircularItem));
+ if (!pItem)
+ return NULL;
+ memset(pItem, 0, sizeof(CircularItem));
+ pNew->pPointer = pItem;
+ pFirst = pItem;
+ for (i = 1; i < iSize; i++) {
+ pItem = (pCircularItem) malloc(sizeof(CircularItem));
+ if (!pItem)
+ return NULL;
+ memset(pItem, 0, sizeof(CircularItem));
+ pItem->previous = pNew->pPointer;
+ pNew->pPointer->next = pItem;
+ pNew->pPointer = pItem;
}
+ pItem->next = pFirst;
+ pFirst->previous = pItem;
+ pNew->killer = kf;
+ return pNew;
+}
+
/*---------------------------------------------------------------------*/
- void deleteCircular(pCircular self)
- {
- pCircularItem pNext = NULL, pCurrent = NULL;
+void deleteCircular(pCircular self)
+{
+ pCircularItem pNext = NULL, pCurrent = NULL;
- assert(self);
+ assert(self);
+
+ self->pPointer->previous->next = NULL;
+ pNext = self->pPointer;
+ while (pNext != NULL) {
+ pCurrent = pNext;
+ pNext = pCurrent->next;
+ if (pCurrent->pData && self->killer) {
+ self->killer(pCurrent->pData);
+ }
+ free(pCurrent);
+ }
+ free(self);
+}
- self->pPointer->previous->next = NULL;
- pNext = self->pPointer;
- while(pNext != NULL)
- {
- pCurrent = pNext;
- pNext = pCurrent->next;
- if(pCurrent->pData && self->killer)
- {
- self->killer(pCurrent->pData);
- }
- free(pCurrent);
- }
- free(self);
- }
/*========================================================================
Data Manipulation functions
*/
- void setCircular(pCircular self, void *pData)
- {
- assert(self);
+void setCircular(pCircular self, void *pData)
+{
+ assert(self);
- /* delete if present */
- if(self->pPointer->pData && self->killer)
- {
- self->killer(self->pPointer->pData);
- }
- self->pPointer->pData = pData;
+ /* delete if present */
+ if (self->pPointer->pData && self->killer) {
+ self->killer(self->pPointer->pData);
}
+ self->pPointer->pData = pData;
+}
+
/*----------------------------------------------------------------------*/
- void *getCircular(pCircular self)
- {
- assert(self);
- return self->pPointer->pData;
- }
+void *getCircular(pCircular self)
+{
+ assert(self);
+ return self->pPointer->pData;
+}
+
/*========================================================================
Pointer movement
*/
- void nextCircular(pCircular self)
- {
- assert(self);
- self->pPointer = self->pPointer->next;
- }
-/*---------------------------------------------------------------------*/
- void previousCircular(pCircular self)
- {
- assert(self);
- self->pPointer = self->pPointer->previous;
- }
+void nextCircular(pCircular self)
+{
+ assert(self);
+ self->pPointer = self->pPointer->next;
+}
+/*---------------------------------------------------------------------*/
+void previousCircular(pCircular self)
+{
+ assert(self);
+ self->pPointer = self->pPointer->previous;
+}
diff --git a/circular.h b/circular.h
index b4bdac3b..5edd7b73 100644
--- a/circular.h
+++ b/circular.h
@@ -8,24 +8,24 @@
#ifndef CIRCULAR
#define CIRCULAR
- typedef struct __CIRCULAR *pCircular;
- typedef void (*CirKillFunc)(void *pData);
+typedef struct __CIRCULAR *pCircular;
+typedef void (*CirKillFunc) (void *pData);
/* ----------------- birth and death -----------------------------------*/
- pCircular createCircular(int iSize,CirKillFunc kf);
+pCircular createCircular(int iSize, CirKillFunc kf);
/*
- iSize is the size of the circular Buffer.
- KillFunc is a function which can safely delete the data item held
- as content of the circular buffer.
- */
- void deleteCircular(pCircular self);
+ iSize is the size of the circular Buffer.
+ KillFunc is a function which can safely delete the data item held
+ as content of the circular buffer.
+ */
+void deleteCircular(pCircular self);
/*-------------- access and modify data item at current position ----------*/
- void setCircular(pCircular self, void *pData);
- void *getCircular(pCircular self);
+void setCircular(pCircular self, void *pData);
+void *getCircular(pCircular self);
/*---------------- pointer movement --------------------------------------*/
- void nextCircular(pCircular self);
- void previousCircular(pCircular self);
+void nextCircular(pCircular self);
+void previousCircular(pCircular self);
#endif
diff --git a/codri.h b/codri.h
index a44f1e0e..991efb95 100644
--- a/codri.h
+++ b/codri.h
@@ -13,32 +13,21 @@
#define CHREDO -2
#define CHOK -3
- typedef struct __CODRI *pCodri;
- typedef struct __CODRI {
- int (*Init)(pCodri self);
- int (*Close)(pCodri self);
- int (*Delete)(pCodri self);
- int (*SetPar)(pCodri self,
- char *parname,
- float fValue);
- int (*SetPar2)(pCodri self,
- char *parname,
- char *value);
- int (*GetPar)(pCodri self,
- char *parname,
- char *pBuffer,
- int iBufLen);
- int (*CheckPar)(pCodri self,
- char *parname);
- int (*GetError)(pCodri self, int *iCode,
- char *pError,
- int iErrLen);
- int (*TryFixIt)(pCodri self, int iCode);
- int (*Halt)(pCodri self);
- char *pParList;
- void *pPrivate;
- }Codri;
-
+typedef struct __CODRI *pCodri;
+typedef struct __CODRI {
+ int (*Init) (pCodri self);
+ int (*Close) (pCodri self);
+ int (*Delete) (pCodri self);
+ int (*SetPar) (pCodri self, char *parname, float fValue);
+ int (*SetPar2) (pCodri self, char *parname, char *value);
+ int (*GetPar) (pCodri self, char *parname, char *pBuffer, int iBufLen);
+ int (*CheckPar) (pCodri self, char *parname);
+ int (*GetError) (pCodri self, int *iCode, char *pError, int iErrLen);
+ int (*TryFixIt) (pCodri self, int iCode);
+ int (*Halt) (pCodri self);
+ char *pParList;
+ void *pPrivate;
+} Codri;
+
#endif
-
diff --git a/comentry.h b/comentry.h
index 1aebd28a..40beb9cc 100644
--- a/comentry.h
+++ b/comentry.h
@@ -8,47 +8,46 @@
---------------------------------------------------------------------------*/
#ifndef COMENTRY
#define COMENTRY
-
+
#define MAXDEV 10
- typedef struct {
- void *pData;
- char name[80];
- pObjectDescriptor pDescriptor;
- float fVal;
- int iCount;
- } DevEntry;
-
+typedef struct {
+ void *pData;
+ char name[80];
+ pObjectDescriptor pDescriptor;
+ float fVal;
+ int iCount;
+} DevEntry;
+
/* -------------------The Entry per registered command --------------------*/
- typedef struct __ComEntry {
- char name[10];
- char *pCommand;
- int iDevice;
- DevEntry pDevice[MAXDEV];
- struct __ComEntry *pNext;
- struct __ComEntry *pPrevious;
- }ComEntry, *pComEntry;
+typedef struct __ComEntry {
+ char name[10];
+ char *pCommand;
+ int iDevice;
+ DevEntry pDevice[MAXDEV];
+ struct __ComEntry *pNext;
+ struct __ComEntry *pPrevious;
+} ComEntry, *pComEntry;
- typedef struct __NAMPOS {
- char *name; /* the name */
- pComEntry pCom; /* the positions */
- char *text; /* explanatory text */
- struct __NAMPOS *pNext;
- struct __NAMPOS *pPrevious;
- } NamPos, *pNamPos;
+typedef struct __NAMPOS {
+ char *name; /* the name */
+ pComEntry pCom; /* the positions */
+ char *text; /* explanatory text */
+ struct __NAMPOS *pNext;
+ struct __NAMPOS *pPrevious;
+} NamPos, *pNamPos;
- typedef struct __NAMMAP {
- char *alias;
- char *motname;
- pMotor pMot;
- } NamMap, *pNamMap;
-
- int CheckComEntryBounds(pComEntry self, SConnection *pCon);
- int AddExeEntry(pExeList self, pComEntry pNew, SConnection *pCon);
- pComEntry CreateComEntry(void);
- pComEntry CopyComEntry(pComEntry pOld);
- int AddDevEntry(pComEntry pCom, char *name, void *pData, pObjectDescriptor pDes,
- float fVal);
- pNamPos LinkNamPos(pNamPos pHead, pNamPos pNew);
- pNamPos UnlinkNamPos(pNamPos pHead, pNamPos pOld);
+typedef struct __NAMMAP {
+ char *alias;
+ char *motname;
+ pMotor pMot;
+} NamMap, *pNamMap;
+
+int CheckComEntryBounds(pComEntry self, SConnection * pCon);
+int AddExeEntry(pExeList self, pComEntry pNew, SConnection * pCon);
+pComEntry CreateComEntry(void);
+pComEntry CopyComEntry(pComEntry pOld);
+int AddDevEntry(pComEntry pCom, char *name, void *pData,
+ pObjectDescriptor pDes, float fVal);
+pNamPos LinkNamPos(pNamPos pHead, pNamPos pNew);
+pNamPos UnlinkNamPos(pNamPos pHead, pNamPos pOld);
#endif
-
diff --git a/commandcontext.h b/commandcontext.h
index 1a293ba9..af7eea4c 100644
--- a/commandcontext.h
+++ b/commandcontext.h
@@ -7,10 +7,10 @@
#ifndef SICSCOMCONTEXT
#define SICSCOMCONTEXT
-typedef struct{
- int transID;
- char deviceID[256];
- }commandContext, *pCommandContext;
+typedef struct {
+ int transID;
+ char deviceID[256];
+} commandContext, *pCommandContext;
#define SCDEVIDLEN 256
#endif
diff --git a/commandlog.c b/commandlog.c
index 1f315529..e6439ec7 100644
--- a/commandlog.c
+++ b/commandlog.c
@@ -16,530 +16,635 @@
- timestamps look different and are omitted if no other text is written
- socket number information is written on the timestamp line
+ Added command history logging. Due to problems this is currently disabled by
+ writeHistory = 0 and code in SetWriteHistory
+
+ Mark Koennecke, July 2010
--------------------------------------------------------------------------*/
#include
#include
#include
#include
#include
+#include "splitter.h"
#include "sics.h"
#include "ifile.h"
#include "sicsvar.h"
#include "scaldate.h"
#include "network.h"
#include "circular.h"
-
+#include "stptok.h"
/* in conman.c */
- int TelnetWrite(mkChannel *pSock, char *pText);
+int TelnetWrite(mkChannel * pSock, char *pText);
/*-------------------- the command log file pointer ---------------------*/
- static FILE *fd = NULL;
- static FILE *fauto = NULL;
- static char pFile[256];
+static FILE *fd = NULL;
+static FILE *fauto = NULL;
+static char pFile[256];
+/*------------------------- command history logging --------------------*/
+static char pHistoryFilter[1024] = "";
+static int writeHistory = 0;
/*-------------------- the tail buffer ---------------------------------*/
- static pCircular pTail = NULL;
+static pCircular pTail = NULL;
#define MAXTAIL 1000
#define NOID -1964
- static time_t lastStamp = 0;
- static time_t iCompact = 0;
- static time_t tLastWrite = 0;
- char *cmdPrompt=">";
- static int lastId=NOID;
-
- static time_t tLogfile = 0;
- static time_t tStamp = 0;
- static int iEnd = 1;
- static int iAutoActive = 0;
- static int iIntervall = 60;
+static time_t lastStamp = 0;
+static time_t iCompact = 0;
+static time_t tLastWrite = 0;
+char *cmdPrompt = ">";
+static int lastId = NOID;
+
+static time_t tLogfile = 0;
+static time_t tStamp = 0;
+static int iEnd = 1;
+static int iAutoActive = 0;
+static int iIntervall = 60;
/*----------------------------------------------------------------------*/
- void WriteToCommandLogId(char *prompt, int id, char *text)
- {
- int l, iPos;
- char *pPtr = NULL, *pCopy = NULL, *strippedText = text;
- struct tm *nowTm;
- time_t now;
- char stamp1[32], stamp2[32], buffer[80];
- int doStamp, doStampId;
-
- /* suppress status messages */
- if (strstr(text,"status =") != NULL) {
- return;
- }
-
- /* suppress TRANSACTIONFINISHED as well in order to make the WWW
- commandlog work and TRANSACTIONSTART in order to make the logfiles
- shorter
- */
- if (strstr(text,"TRANSACTIONSTART") != NULL) {
- return;
- }
- if (strstr(text,"TRANSACTIONFINISHED") != NULL) {
- return;
- }
-
- /* we make a local copy, stripping off the newline at the
- end. We anyway need a copy later for the circular buffer */
- l = strlen(text);
- pPtr = strrchr(text,'\n');
- if (pPtr != NULL && (pPtr[1]=='\0' || pPtr[2] == '\0')) {
- l = pPtr - text;
- }
- pCopy = malloc(l+1);
- if (pCopy == NULL) return;
- strncpy(pCopy, text, l);
- pCopy[l]='\0';
+void WriteToCommandLogId(char *prompt, int id, char *text)
+{
+ int l, iPos;
+ char *pPtr = NULL, *pCopy = NULL, *strippedText = text;
+ struct tm *nowTm;
+ time_t now;
+ char stamp1[32], stamp2[32], buffer[80];
+ int doStamp, doStampId;
- if (prompt == cmdPrompt && iCompact) {
- pPtr = strstr(pCopy, "fulltransact ");
- if (pPtr && pPtr < pCopy+3) {
- strippedText = pPtr + 13;
- }
- pPtr = strstr(pCopy, "transact ");
- if (pPtr && pPtr < pCopy+3) {
- strippedText = pPtr + 9;
- }
- }
+ /* suppress status messages */
+ if (strstr(text, "status =") != NULL) {
+ return;
+ }
- /* create tail buffer as needed */
- if (!pTail) {
- pTail = createCircular(MAXTAIL,free);
- }
+ /* suppress TRANSACTIONFINISHED as well in order to make the WWW
+ commandlog work and TRANSACTIONSTART in order to make the logfiles
+ shorter
+ */
+ if (strstr(text, "TRANSACTIONSTART") != NULL) {
+ return;
+ }
+ if (strstr(text, "TRANSACTIONFINISHED") != NULL) {
+ return;
+ }
- now = time(NULL);
+ /* we make a local copy, stripping off the newline at the
+ end. We anyway need a copy later for the circular buffer */
+ l = strlen(text);
+ pPtr = strrchr(text, '\n');
+ if (pPtr != NULL && (pPtr[1] == '\0' || pPtr[2] == '\0')) {
+ l = pPtr - text;
+ }
+ pCopy = malloc(l + 1);
+ if (pCopy == NULL)
+ return;
+ strncpy(pCopy, text, l); /* strlcpy is not correct here */
+ pCopy[l] = '\0';
+ if (prompt == cmdPrompt && iCompact) {
+ pPtr = strstr(pCopy, "fulltransact ");
+ if (pPtr && pPtr < pCopy + 3) {
+ strippedText = pPtr + 13;
+ }
+ pPtr = strstr(pCopy, "transact ");
+ if (pPtr && pPtr < pCopy + 3) {
+ strippedText = pPtr + 9;
+ }
+ }
- doStamp = 0;
- doStampId = 0;
-
- if (id == NOID) {
- if (!prompt) {
- prompt="";
- } else {
- snprintf(buffer, sizeof buffer, "%s ", prompt);
- prompt = buffer;
- }
- } else if (iCompact == 0) {
- if (!prompt) {
- snprintf(buffer, sizeof buffer, "To sock %d : ", id);
- } else {
- snprintf(buffer, sizeof buffer, "sock %d>%s ", id, prompt);
- }
- prompt = buffer;
- } else {
- if (id != lastId) {
- lastId = id;
- doStampId = 1;
- }
- if (!prompt) {
- prompt="";
- } else {
- snprintf(buffer, sizeof buffer, "%s ", prompt);
- prompt = buffer;
- }
- }
-
- if (iCompact > 0) { /* write time stamp */
- if (now/iCompact != lastStamp/iCompact) {
- doStamp = 1;
- doStampId = 1;
- }
- if (doStampId) {
- lastStamp = now;
- nowTm = localtime(&now);
- strftime(stamp1, sizeof stamp1, "=== %H:%M:%S ===", nowTm);
- if (id != NOID) {
- snprintf(stamp2, sizeof stamp2, " socket %d ===", id);
- } else {
- stamp2[0] = '\0';
- }
- }
- }
+ now = time(NULL);
- /* user file */
- if (fd != NULL) {
- if (doStampId) {
- fprintf(fd,"%s %s\n", stamp1, stamp2);
- }
- fprintf(fd,"%s%s\n", prompt, pCopy);
- }
+ /* create tail buffer as needed */
+ if (!pTail) {
+ pTail = createCircular(MAXTAIL, free);
+ }
- /* automatic file */
- if (fauto != NULL) {
- tLastWrite = now;
- if (doStampId) {
- fprintf(fauto,"%s%s\n", stamp1, stamp2);
- }
- fprintf(fauto,"%s%s\n", prompt, strippedText);
- }
+ doStamp = 0;
+ doStampId = 0;
- /* to all listening sockets. The check is necessary to resolve a shutdown problem */
- if (pServ->pTasker != NULL) {
- if (doStamp) {
- TaskSignal(pServ->pTasker,COMLOG,stamp1);
- }
- TaskSignal(pServ->pTasker,COMLOG,pCopy);
- }
-
- /* tail buffer */
- if (pTail != NULL) {
- if (doStamp) {
- setCircular(pTail,strdup(stamp1));
- nextCircular(pTail);
- }
- setCircular(pTail,pCopy);
- nextCircular(pTail);
- }
+ if (iCompact == 1) {
+ nowTm = localtime(&now);
+ strftime(stamp1, sizeof stamp1, "%H:%M:%S", nowTm);
+ if (prompt == NULL)
+ prompt = "";
+ if (id == NOID) {
+ if (!prompt)
+ prompt = " ";
+ snprintf(buffer, sizeof buffer, "%s %s ", stamp1, prompt);
+ } else {
+ snprintf(buffer, sizeof buffer, "%s %2.0d| ", stamp1, id);
+ }
+ prompt = buffer;
+ } else if (id == NOID) {
+ if (!prompt) {
+ prompt = "";
+ } else {
+ snprintf(buffer, sizeof buffer, "%s ", prompt);
+ prompt = buffer;
+ }
+ } else if (iCompact == 0) {
+ if (!prompt) {
+ snprintf(buffer, sizeof buffer, "To sock %d : ", id);
+ } else {
+ snprintf(buffer, sizeof buffer, "sock %d>%s ", id, prompt);
+ }
+ prompt = buffer;
+ } else if (iCompact > 1) {
+ if (id != lastId) {
lastId = id;
- }
-/*------------------------------------------------------------------------*/
- void WriteToCommandLog(char *prompt, char *text)
- {
- WriteToCommandLogId(prompt, NOID, text);
- }
-/*------------------------------------------------------------------------*/
- void WriteToCommandLogCmd(int id, char *text)
- {
- WriteToCommandLogId(cmdPrompt, id, text);
- }
-/*------------------------------------------------------------------------*/
- int CompactCommandLog(void) {
- return iCompact > 0;
- }
-/*------------------------------------------------------------------------*/
- static void PrintTail(int iNum, SConnection *pCon)
- {
- char *pPtr = NULL;
- int i;
+ doStampId = 1;
+ }
+ if (!prompt) {
+ prompt = "";
+ } else {
+ snprintf(buffer, sizeof buffer, "%s ", prompt);
+ prompt = buffer;
+ }
+ }
- if(pTail == NULL)
- {
- SCWrite(pCon,"Nothing to print",eError);
- return;
- }
+ if (iCompact > 1) { /* write time stamp */
+ if (now / iCompact != lastStamp / iCompact) {
+ doStamp = 1;
+ doStampId = 1;
+ }
+ if (doStampId) {
+ lastStamp = now;
+ nowTm = localtime(&now);
+ strftime(stamp1, sizeof stamp1, "=== %H:%M:%S ===", nowTm);
+ if (id != NOID) {
+ snprintf(stamp2, sizeof stamp2, " socket %d ===", id);
+ } else {
+ stamp2[0] = '\0';
+ }
+ }
+ }
- /* step back */
- for(i = 0; i < iNum; i++)
- {
- previousCircular(pTail);
- }
+ /* user file */
+ if (fd != NULL) {
+ if (doStampId) {
+ fprintf(fd, "%s %s\n", stamp1, stamp2);
+ }
+ fprintf(fd, "%s%s\n", prompt, pCopy);
+ }
+
+ /* automatic file */
+ if (fauto != NULL) {
+ tLastWrite = now;
+ if (doStampId) {
+ fprintf(fauto, "%s%s\n", stamp1, stamp2);
+ }
+ fprintf(fauto, "%s%s\n", prompt, strippedText);
+ }
+
+ /* to all listening sockets. The check is necessary to resolve a shutdown problem */
+ if (pServ->pTasker != NULL) {
+ if (doStamp) {
+ TaskSignal(pServ->pTasker, COMLOG, stamp1);
+ }
+ TaskSignal(pServ->pTasker, COMLOG, pCopy);
+ }
+
+ /* tail buffer */
+ if (pTail != NULL) {
+ if (doStamp) {
+ setCircular(pTail, strdup(stamp1));
+ nextCircular(pTail);
+ }
+ setCircular(pTail, strdup(pCopy));
+ nextCircular(pTail);
+ }
+ lastId = id;
+ if(pCopy != NULL){
+ free(pCopy);
+ }
+}
- /* now step ahead and print. I have to use a trick here: I do not
- want the tail stuff to show up in log files. Thus I write it
- directly to the connection socket.
- */
- for(i = 0; i < iNum; i++)
- {
- pPtr = (char *)getCircular(pTail);
- if(pCon->pSock && pPtr != NULL)
- {
- TelnetWrite(pCon->pSock, pPtr);
- }
- nextCircular(pTail);
- }
- }
/*------------------------------------------------------------------------*/
- void CLFormatTime(char *pBuffer, int iBufLen)
- {
- time_t iDate;
- struct tm *psTime;
+void WriteToCommandLog(char *prompt, char *text)
+{
+ WriteToCommandLogId(prompt, NOID, text);
+}
+
+/*------------------------------------------------------------------------*/
+void WriteToCommandLogCmd(int id, char *text)
+{
+ WriteToCommandLogId(cmdPrompt, id, text);
+}
+
+/*------------------------------------------------------------------------*/
+int CompactCommandLog(void)
+{
+ return iCompact > 0;
+}
+
+/*------------------------------------------------------------------------*/
+static void PrintTail(int iNum, SConnection * pCon)
+{
+ char *pPtr = NULL;
+ int i;
+
+ if (pTail == NULL) {
+ SCWrite(pCon, "Nothing to print", eError);
+ return;
+ }
+
+ /* step back */
+ for (i = 0; i < iNum; i++) {
+ previousCircular(pTail);
+ }
+
+ /* now step ahead and print. I have to use a trick here: I do not
+ want the tail stuff to show up in log files. Thus I write it
+ directly to the connection socket.
+ */
+ for (i = 0; i < iNum; i++) {
+ pPtr = (char *) getCircular(pTail);
+ if (pPtr != NULL) {
+ SCPureSockWrite(pCon, pPtr, eWarning);
+ }
+ nextCircular(pTail);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+void CLFormatTime(char *pBuffer, int iBufLen)
+{
+ time_t iDate;
+ struct tm *psTime;
+
+ /* make time string */
+ iDate = time(NULL);
+ psTime = localtime(&iDate);
+ memset(pBuffer, 0, iBufLen);
+ strftime(pBuffer, iBufLen, "%Y-%m-%d@%H-%M-%S", psTime);
+}
- /* make time string */
- iDate = time(NULL);
- psTime = localtime(&iDate);
- memset(pBuffer,0,iBufLen);
- strftime(pBuffer,iBufLen,"%Y-%m-%d@%H-%M-%S",psTime);
- }
/*----------------------------------------------------------------------
Build an automatically generated log file name and open it.
*/
- static void AutoLog(void)
- {
- char pBueffel[1024];
- char pTime[80];
- pSicsVariable pInst = NULL;
- char *pPtr = NULL;
- SConnection *pIntern = NULL;
+static void AutoLog(void)
+{
+ char pBueffel[1024];
+ char pTime[80];
+ pSicsVariable pInst = NULL;
+ char *pPtr = NULL;
+ SConnection *pIntern = NULL;
- if(fauto)
- {
- fclose(fauto);
- fauto = NULL;
- }
+ if (fauto) {
+ fclose(fauto);
+ fauto = NULL;
+ }
- /* find path */
- pPtr = IFindOption(pSICSOptions,"LogFileDir");
- if(!pPtr)
- {
- pPtr = strdup("~/log");
- printf("WARNING: Required SICS option LogFileDir not found");
- }
+ /* find path */
+ pPtr = IFindOption(pSICSOptions, "LogFileDir");
+ if (!pPtr) {
+ pPtr = strdup("~/log");
+ printf("WARNING: Required SICS option LogFileDir not found");
+ }
- /* get time */
- CLFormatTime(pTime,79);
-
- /* build file name */
- sprintf(pBueffel,"%s/auto%s.log",pPtr,pTime);
-
- /* open file */
- fauto = fopen(pBueffel,"w");
- if(!fauto)
- {
- ServerWriteGlobal("ERROR: failed to open autolog file",eError);
- }
+ /* get time */
+ CLFormatTime(pTime, 79);
- /* write the instrument name to it for identification */
- pInst = FindVariable(pServ->pSics,"instrument");
- if(pInst)
- {
- sprintf(pBueffel,"Logfile started at instrument %s at %s",
- pInst->text,pTime);
- WriteToCommandLog("SYS>>", pBueffel);
- }
+ /* build file name */
+ snprintf(pBueffel,1024, "%s/auto%s.log", pPtr, pTime);
+
+ /* open file */
+ fauto = fopen(pBueffel, "w");
+ if (!fauto) {
+ ServerWriteGlobal("ERROR: failed to open autolog file", eError);
+ }
+
+ /* write the instrument name to it for identification */
+ pInst = FindVariable(pServ->pSics, "instrument");
+ if (pInst) {
+ snprintf(pBueffel,1024, "Logfile started at instrument %s at %s",
+ pInst->text, pTime);
+ WriteToCommandLog("SYS>>", pBueffel);
+ }
+
+ /* if a file to execute is configured, execute it */
+ pPtr = NULL;
+ pPtr = IFindOption(pSICSOptions, "logstartfile");
+ if (pPtr != NULL) {
+ pIntern = SCCreateDummyConnection(pServ->pSics);
+ if (!pIntern) {
+ return;
+ }
+ SCnoSock(pIntern);
+ SCSetRights(pIntern, usUser);
+ snprintf(pBueffel,1024, "fileeval %s", pPtr);
+ InterpExecute(pServ->pSics, pIntern, pBueffel);
+ SCDeleteConnection(pIntern);
+ }
+}
- /* if a file to execute is configured, execute it */
- pPtr = NULL;
- pPtr = IFindOption(pSICSOptions,"logstartfile");
- if(pPtr != NULL)
- {
- pIntern = SCCreateDummyConnection(pServ->pSics);
- if(!pIntern)
- {
- return;
- }
- SCnoSock(pIntern);
- SCSetRights(pIntern,usUser);
- sprintf(pBueffel,"fileeval %s",pPtr);
- InterpExecute(pServ->pSics,pIntern,pBueffel);
- SCDeleteConnection(pIntern);
- }
- }
/*----------------------------------------------------------------------
AutoTask puts a time stamp into the auto log file any hour and
creates a new log file any 24 hours
*/
- static int AutoTask(void *pData)
- {
- time_t tNow;
- char pTime[80];
- struct tm *sTime;
- long julian;
- unsigned yr, mo, dd;
+static int AutoTask(void *pData)
+{
+ time_t tNow;
+ char pTime[80];
+ struct tm *sTime;
+ long julian;
+ unsigned yr, mo, dd;
- tNow = time(NULL);
- if(tNow > tLogfile)
- {
- AutoLog();
- sTime = localtime(&tNow);
- /* find next day, do so by converting to julian Date, add one
- and calculate back. The (stolen) julian calculations will
- take care of all the leaps and month and year etc.
- */
- julian = ymd_to_scalar(sTime->tm_year+1900, sTime->tm_mon+1,
- sTime->tm_mday);
- julian++;
- scalar_to_ymd(julian, &yr, &mo, &dd);
- sTime->tm_sec = 0;
- sTime->tm_min = 1;
- sTime->tm_hour = 0;
- sTime->tm_mday = dd;
- sTime->tm_mon = mo - 1;
- sTime->tm_year = yr - 1900;
- tLogfile = mktime(sTime);
- if(tLogfile < 0)
- tLogfile = tNow + 60*60*24;
+ tNow = time(NULL);
+ if (tNow > tLogfile) {
+ AutoLog();
+ sTime = localtime(&tNow);
+ /* find next day, do so by converting to julian Date, add one
+ and calculate back. The (stolen) julian calculations will
+ take care of all the leaps and month and year etc.
+ */
+ julian = ymd_to_scalar(sTime->tm_year + 1900, sTime->tm_mon + 1,
+ sTime->tm_mday);
+ julian++;
+ scalar_to_ymd(julian, &yr, &mo, &dd);
+ sTime->tm_sec = 0;
+ sTime->tm_min = 1;
+ sTime->tm_hour = 0;
+ sTime->tm_mday = dd;
+ sTime->tm_mon = mo - 1;
+ sTime->tm_year = yr - 1900;
+ tLogfile = mktime(sTime);
+ if (tLogfile < 0)
+ tLogfile = tNow + 60 * 60 * 24;
+ }
+ if (tNow > tStamp && iIntervall > 0) {
+ CLFormatTime(pTime, 79);
+ WriteToCommandLog("TIMESTAMP>> ", pTime);
+ sTime = localtime(&tNow);
+ sTime->tm_sec = 0;
+ sTime->tm_min += iIntervall;
+ if (sTime->tm_min >= 60) {
+ sTime->tm_min = 0;
+ sTime->tm_hour++;
+ }
+ if (sTime->tm_hour >= 24)
+ sTime->tm_hour = 0;
+ tStamp = mktime(sTime);
+ if ((tStamp < 0) || ((tStamp - tNow) < 100)) {
+ tStamp = tNow + iIntervall * 60;
+ }
+ if (fauto)
+ fflush(fauto);
+ }
+
+ if (fauto && tLastWrite > 0 && tNow > tLastWrite) {
+ fflush(fauto);
+ tLastWrite = 0;
+ }
+ return iEnd;
+}
+
+/*----------- a command to configure the log --------------------------*/
+int CommandLog(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ char *pPtr = NULL;
+ char pBueffel[1024];
+ int iVal, iRet;
+
+ if (argc == 1) {
+ if (fd) {
+ sprintf(pBueffel, "Command log ACTIVE at %s", pFile);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else {
+ SCWrite(pCon, "Command logging DISABLED", eValue);
+ return 1;
+ }
+ }
+
+ /* handle tail */
+ strtolower(argv[1]);
+ if (strcmp(argv[1], "tail") == 0) {
+ /* check for optional number of lines argument */
+ iVal = 20;
+ if (argc >= 3) {
+ iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iVal);
+ if (iRet != TCL_OK)
+ iVal = 20;
+ }
+ PrintTail(iVal, pCon);
+ return 1;
+ }
+ /**
+ * handle write
+ */
+
+ if (strcmp(argv[1], "write") == 0) {
+ Arg2Text(argc-2, &argv[2],pBueffel,sizeof(pBueffel));
+ WriteToCommandLogId(NULL, pCon->sockHandle,pBueffel);
+ SCSendOK(pCon);
+ return 1;
+ }
+
+ /* check rights */
+ if (!SCMatchRights(pCon, usMugger)) {
+ SCWrite(pCon, "ERROR: only managers may configure the logfile",
+ eError);
+ SCWrite(pCon, "ERROR: Request refused", eError);
+ return 0;
+ }
+
+ /* check no of args */
+ if (argc < 2) {
+ SCWrite(pCon,
+ "ERROR: Insufficient number or arguments to commandlog",
+ eError);
+ return 0;
+ }
+
+ if (strcmp(argv[1], "new") == 0) { /* new command */
+ if (argc < 3) {
+ SCWrite(pCon,
+ "ERROR: Insufficient number or arguments to commandlog new",
+ eError);
+ return 0;
+ }
+ if (fd) {
+ fclose(fd);
+ fd = NULL;
+ }
+ /* make the filename */
+ pPtr = IFindOption(pSICSOptions, "LogFileDir");
+ if (!pPtr) {
+ SCWrite(pCon, "WARNING: no log file directory specified", eWarning);
+ snprintf(pBueffel,1023, "%s", argv[2]);
+
+ } else {
+ snprintf(pBueffel,1023, "%s/%s", pPtr, argv[2]);
+ }
+ fd = fopen(pBueffel, "w");
+ if (!fd) {
+ snprintf(pBueffel,1023, "ERROR: cannot open %s/%s for writing", pPtr,
+ argv[2]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ strlcpy(pFile, argv[2],255);
+ SCSendOK(pCon);
+ return 1;
+ } else if (strcmp(argv[1], "auto") == 0) {
+ if (iAutoActive) {
+ SCWrite(pCon, "ERROR: autologging is already active", eError);
+ return 0;
+ }
+ TaskRegister(pServ->pTasker, AutoTask, NULL, NULL, NULL, 1);
+ SCSendOK(pCon);
+ iAutoActive = 1;
+ return 1;
+ } else if (strcmp(argv[1], "intervall") == 0) {
+ if (argc > 2) {
+ iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iVal);
+ if (iRet != TCL_OK) {
+ SCWrite(pCon, "ERROR: failed to convert new intervall to number",
+ eError);
+ return 0;
}
- if(tNow > tStamp && iIntervall > 0)
- {
- CLFormatTime(pTime,79);
- WriteToCommandLog("TIMESTAMP>> ",pTime);
- sTime = localtime(&tNow);
- sTime->tm_sec = 0;
- sTime->tm_min += iIntervall;
- if(sTime->tm_min >= 60)
- {
- sTime->tm_min = 0;
- sTime->tm_hour++;
- }
- if(sTime->tm_hour >= 24)
- sTime->tm_hour = 0;
- tStamp = mktime(sTime);
- if((tStamp < 0) || ( (tStamp-tNow) < 100) )
- {
- tStamp = tNow + iIntervall*60;
- }
- if(fauto)
- fflush(fauto);
- }
-
- if (fauto && tLastWrite > 0 && tNow > tLastWrite) {
- fflush(fauto);
- tLastWrite = 0;
- }
- return iEnd;
- }
-/*----------- a command to configure the log --------------------------*/
- int CommandLog(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- char *pPtr = NULL;
- char pBueffel[1024];
- int iVal, iRet;
-
- if(argc == 1)
- {
- if(fd)
- {
- sprintf(pBueffel,"Command log ACTIVE at %s",pFile);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- else
- {
- SCWrite(pCon,"Command logging DISABLED",eValue);
- return 1;
- }
- }
-
- /* handle tail */
- strtolower(argv[1]);
- if(strcmp(argv[1],"tail") == 0)
- {
- /* check for optional number of lines argument */
- iVal = 20;
- if(argc >= 3)
- {
- iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iVal);
- if(iRet != TCL_OK)
- iVal = 20;
- }
- PrintTail(iVal,pCon);
- return 1;
- }
-
- /* check rights */
- if(!SCMatchRights(pCon,usMugger))
- {
- SCWrite(pCon,"ERROR: only managers may configure the logfile",
- eError);
- SCWrite(pCon,"ERROR: Request refused",eError);
- return 0;
- }
-
- /* check no of args */
- if(argc < 2)
- {
- SCWrite(pCon,
- "ERROR: Insufficient number or arguments to commandlog",
+ iIntervall = iVal;
+ }
+ SCPrintf(pCon, eValue, "%s.intervall [min] = %d", argv[0], iIntervall);
+ return 1;
+ } else if (strcmp(argv[1], "history") == 0) {
+ if (argc > 2) {
+ iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iVal);
+ if (iRet != TCL_OK) {
+ SCWrite(pCon, "ERROR: failed to convert new history to number",
eError);
- return 0;
- }
-
- if(strcmp(argv[1],"new") == 0) /* new command */
- {
- if(argc < 3)
- {
- SCWrite(pCon,
- "ERROR: Insufficient number or arguments to commandlog new",
- eError);
- return 0;
- }
- if(fd)
- {
- fclose(fd);
- fd = NULL;
- }
- /* make the filename */
- pPtr = IFindOption(pSICSOptions,"LogFileDir");
- if(!pPtr)
- {
- SCWrite(pCon,"WARNING: no log file directory specified",eWarning);
- sprintf(pBueffel,"%s",argv[2]);
-
- }
- else
- {
- sprintf(pBueffel,"%s/%s",pPtr,argv[2]);
- }
- fd = fopen(pBueffel,"w");
- if(!fd)
- {
- sprintf(pBueffel,"ERROR: cannot open %s/%s for writing",pPtr,
- argv[2]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- strcpy(pFile,argv[2]);
- SCSendOK(pCon);
- return 1;
- }
- else if(strcmp(argv[1],"auto") == 0)
- {
- if(iAutoActive)
- {
- SCWrite(pCon,"ERROR: autologging is already active",eError);
- return 0;
- }
- TaskRegister(pServ->pTasker,
- AutoTask,
- NULL,
- NULL,
- NULL,
- 1);
- SCSendOK(pCon);
- iAutoActive = 1;
- return 1;
- }
- else if(strcmp(argv[1],"intervall") == 0)
- {
- if(argc > 2)
- {
- iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iVal);
- if(iRet != TCL_OK)
- {
- SCWrite(pCon,"ERROR: failed to convert new intervall to number",
- eError);
- return 0;
- }
- iIntervall = iVal;
- }
- SCPrintf(pCon,eValue,"%s.intervall [min] = %d", argv[0], iIntervall);
- return 1;
- }
- else if(strcmp(argv[1],"compact") == 0)
- {
- if(argc > 2)
- {
- iCompact = atoi(argv[2]);
- if (iCompact > 0) iIntervall = 0;
- }
- SCPrintf(pCon,eValue,"%s.compact [sec] = %d", argv[0], iCompact);
- return 1;
- }
- else if(strcmp(argv[1],"close") == 0) /* close command */
- {
- fclose(fd);
- fd = NULL;
- SCSendOK(pCon);
- return 1;
- }
- sprintf(pBueffel,"ERROR: subcommand %s to commandlog unknown",
- argv[1]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
+ return 0;
+ }
+ writeHistory = iVal;
+ }
+ SCPrintf(pCon, eValue, "%s.writeHistory = %d", argv[0], writeHistory);
+ return 1;
+ } else if (strcmp(argv[1], "historyfilter") == 0) {
+ if (argc > 2) {
+ if(strlen(argv[2]) < 1024){
+ strcpy(pHistoryFilter,argv[2]);
+ } else {
+ SCWrite(pCon,"ERROR: history filter to long", eError);
+ return 0;
+ }
+ SCSendOK(pCon);
+ return 1;
+ }
+ SCPrintf(pCon, eValue, "%s.historyFilter = %s", argv[0], pHistoryFilter);
+ return 1;
+ } else if (strcmp(argv[1], "compact") == 0) {
+ if (argc > 2) {
+ iCompact = atoi(argv[2]);
+ if (iCompact > 0)
+ iIntervall = 0;
+ }
+ SCPrintf(pCon, eValue, "%s.compact [sec] = %d", argv[0], iCompact);
+ return 1;
+ } else if (strcmp(argv[1], "close") == 0) { /* close command */
+ fclose(fd);
+ fd = NULL;
+ SCSendOK(pCon);
+ return 1;
+ }
+ snprintf(pBueffel, 1024,"ERROR: subcommand %s to commandlog unknown", argv[1]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+}
+
/*-------------------------------------------------------------------------*/
- void CommandLogClose(void *pData)
- {
- if(fd)
- {
- fclose(fd);
- }
- if(fauto)
- fclose(fauto);
- if(pData)
- KillDummy(pData);
- if(pTail)
- deleteCircular(pTail);
- }
+void CommandLogClose(void *pData)
+{
+ if (fd) {
+ fclose(fd);
+ }
+ if (fauto)
+ fclose(fauto);
+ if (pData)
+ KillDummy(pData);
+ if (pTail)
+ deleteCircular(pTail);
+}
+/*-------------------------------------------------------------------------*/
+void CommandLogInit(void)
+{
+ AddCommand(pServ->pSics, "commandlog", CommandLog, CommandLogClose, NULL);
+}
+/*---------------------- History -----------------------------------------*/
+static FILE *comHistory = NULL;
+/*-----------------------------------------------------------------------*/
+static int openHistoryLog()
+{
+ char *fileName = NULL;
+ char fileBuffer[1024];
+ time_t iDate;
+ struct tm *psTime;
+ if (comHistory == NULL) {
+ fileName = IFindOption(pSICSOptions, "historylog");
+ if (fileName != NULL) {
+ strlcpy(fileBuffer, fileName,1024);
+ } else {
+ iDate = time(NULL);
+ psTime = localtime(&iDate);
+ fileBuffer[0] = '\0';
+ fileName = getenv("HOME");
+ if (fileName != NULL) {
+ snprintf(fileBuffer, 1023, "%s/log/comhistory%4.4d.log",
+ fileName, psTime->tm_year + 1900);
+ }
+ }
+ comHistory = fopen(fileBuffer, "a+");
+ }
+ if (comHistory == NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+/*---------------------------------------------------------------------------
+ * This is to suppress certain stuff from the history log in order to stop it
+ * from filling with garbage
+ -----------------------------------------------------------------------------*/
+static int historyFilter(char *command)
+{
+ static char *toRemove[] = {"sct", "hupdate","contextdo","transact", NULL};
+ char token[50];
+ char *pPtr = NULL;
+ int i = 0;
+ while(toRemove[i] != NULL){
+ if(strstr(command,toRemove[i]) != NULL){
+ return 0;
+ }
+ i++;
+ }
+
+ pPtr = pHistoryFilter;
+ while((pPtr = stptok(pPtr,token,50,":")) != NULL){
+ if(strstr(command,token) != NULL){
+ return 0;
+ }
+ }
+
+ return 1;
+}
+/*-----------------------------------------------------------------------*/
+void WriteCommandHistory(char *txt)
+{
+ if(writeHistory == 0){
+ return;
+ }
+ if(comHistory == NULL){
+ openHistoryLog();
+ }
+ if(comHistory != NULL){
+ if(historyFilter(txt)){
+ fprintf(comHistory,"%s\n", txt);
+ }
+ }
+}
+/*-----------------------------------------------------------------------*/
+void SetWriteHistory(int i)
+{
+ /* writeHistory = i;*/
+ writeHistory = 0;
+}
diff --git a/commandlog.h b/commandlog.h
index 704a264a..d02d1da3 100644
--- a/commandlog.h
+++ b/commandlog.h
@@ -9,13 +9,14 @@
--------------------------------------------------------------------------*/
#ifndef COMMANDLOG
#define COMMANDLOG
- void WriteToCommandLog(char *prompt,char *pText);
- void WriteToCommandLogId(char *prompt, int id, char *text);
- void WriteToCommandLogCmd(int id, char *text);
- int CompactCommandLog(void);
- int CommandLog(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
-
- void CommandLogClose(void *pData);
-#endif
+void WriteToCommandLog(char *prompt, char *pText);
+void WriteToCommandLogId(char *prompt, int id, char *text);
+void WriteToCommandLogCmd(int id, char *text);
+int CompactCommandLog(void);
+int CommandLog(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+void CommandLogClose(void *pData);
+void WriteCommandHistory(char *txt);
+void SetWriteHistory(int i);
+#endif
diff --git a/cone.c b/cone.c
index 4fc4d5d9..b90279ca 100644
--- a/cone.c
+++ b/cone.c
@@ -5,6 +5,10 @@
COPYRIGHT: see file COPYRIGHT
Mark Koennecke, March 2006
+
+ Reworked for new four circle infrastructure.
+
+ Mark Koennecke, August 2008
------------------------------------------------------------------------*/
#include
#include
@@ -12,346 +16,326 @@
#include "hkl.i"
#include "vector.h"
#include "fourlib.h"
+#include "singlex.h"
+#include "sicsobj.h"
+#include "sicshipadaba.h"
/*=================== Object Descriptor Interface ===================================================*/
-static void *ConeGetInterface(void *pData, int iID){
+static void *ConeGetInterface(void *pData, int iID)
+{
pConeData self = NULL;
+ pSICSOBJ obj = (pSICSOBJ) pData;
- self = (pConeData)pData;
- if(self == NULL){
+ self = (pConeData) obj->pPrivate;
+ if (self == NULL) {
return NULL;
}
- if(iID == DRIVEID){
+ if (iID == DRIVEID) {
return self->pDriv;
}
return NULL;
}
-/*---------------------------------------------------------------------------------------------------*/
-static void ConeSaveStatus(void *data, char *name, FILE *fd){
- pConeData self = (pConeData)data;
- if(self == NULL){
- return;
- }
- fprintf(fd,"%s center %d\n", name,self->center);
- fprintf(fd,"%s target %f %f %f\n", name, self->target.h,
- self->target.k, self->target.l);
- fprintf(fd,"%s qscale %f \n", name, self->qScale);
-}
+
/*=================== Drivable Interface ============================================================*/
-static int ConeHalt(void *pData){
+static int ConeHalt(void *pData)
+{
+ pSICSOBJ obj = pData;
pConeData self = NULL;
- self = (pConeData)pData;
+ self = (pConeData) obj->pPrivate;
assert(self != NULL);
-
- self->pHkl->pTheta->pDrivInt->Halt(self->pHkl->pTheta);
- self->pHkl->pOmega->pDrivInt->Halt(self->pHkl->pOmega);
- self->pHkl->pChi->pDrivInt->Halt(self->pHkl->pChi);
- self->pHkl->pPhi->pDrivInt->Halt(self->pHkl->pPhi);
+
+ stopHKLMotors(self->pHkl);
return 1;
}
+
/*-----------------------------------------------------------------------------------------------------*/
-static int ConeCheckLimits(void *self, float fVal, char *error, int errLen){
+static int ConeCheckLimits(void *self, float fVal, char *error, int errLen)
+{
/*
- There is no meaningful implementation here. This gets called when starting the motor.
- At that stage not all other values may be known. If the calculation fails, this will die
- at status check time.
- */
+ There is no meaningful implementation here. This gets called when starting the motor.
+ At that stage not all other values may be known. If the calculation fails, this will die
+ at status check time.
+ */
return 1;
}
+
/*------------------------------------------------------------------------*/
-static MATRIX makeCsToPsiMatrix(reflection center, double lambda){
- MATRIX psiToCs = NULL, csToPsi = NULL, t1, t2;
- double z1[3], u;
-
- psiToCs = makeInstToConeVectorMatrix(center,lambda);
- if(psiToCs == NULL){
+static MATRIX makeCsToPsiMatrix(reflection center, double lambda)
+{
+ MATRIX psiToCs = NULL, csToPsi = NULL, t1, t2;
+ double z1[3], u;
+
+ psiToCs = makeInstToConeVectorMatrix(center, lambda);
+ if (psiToCs == NULL) {
return NULL;
}
csToPsi = mat_inv(psiToCs);
/*
* this is debugging code: remove together with variables
*/
- z1FromAngles(lambda,center.s2t,center.om,center.chi,center.phi,z1);
+ z1FromAngles(lambda, center.s2t, center.om, center.chi, center.phi, z1);
t1 = makeVectorInit(z1);
- t2 = mat_mul(psiToCs,t1);
+ t2 = mat_mul(psiToCs, t1);
normalizeVector(t2);
t1[0][0] = .0;
t1[1][0] = .0;
t1[2][0] = 1.;
- u = angleBetween(t1,t2);
-
+ u = angleBetween(t1, t2);
+
mat_free(psiToCs);
return csToPsi;
}
+
/*----------------------------------------------------------------------------------------------------
* I am lazy in this function: I calculate anew from all the data. This saves
* me a lot of trouble keeping track of parameter changes in UBCALC etc.
- * ---------------------------------------------------------------------------*/
-static long ConeSetValue(void *pData, SConnection *pCon, float fVal){
+ * ---------------------------------------------------------------------------*/
+static long ConeSetValue(void *pData, SConnection * pCon, float fVal)
+{
+ pSICSOBJ obj = pData, refList;
pConeData self = NULL;
- float fSet[4];
+ double fSet[4];
+ float ffSet[4];
double openingAngle, length;
MATRIX csToPsi = NULL, B = NULL, newScat = NULL;
- int status;
- reflection center;
+ int status, i;
+ reflection center, target;
char buffer[131];
+ const double *cell;
+ double hkl[3], ang[4];
+ lattice direct;
+ hdbValue v;
- if(!SCMatchRights(pCon,usUser)){
+ if (!SCMatchRights(pCon, usUser)) {
return 0;
}
- self = (pConeData)pData;
+ self = (pConeData) obj->pPrivate;
assert(self != NULL);
/*
* calculate opening angle
*/
- B = mat_creat(3,3,UNIT_MATRIX);
- status = calculateBMatrix(self->ubi->direct,B);
- if(status < 0){
- SCWrite(pCon,"ERROR: cell has no volume",eError);
+ B = mat_creat(3, 3, UNIT_MATRIX);
+ cell = SXGetCell();
+ direct.a = cell[0];
+ direct.b = cell[1];
+ direct.c = cell[2];
+ direct.alpha = cell[3];
+ direct.beta = cell[4];
+ direct.gamma = cell[5];
+ status = calculateBMatrix(direct, B);
+ if (status < 0) {
+ SCWrite(pCon, "ERROR: cell has no volume", eError);
return 0;
}
- center = getReflection(self->ubi,self->center);
- openingAngle = angleBetweenReflections(B,center,self->target);
-
+ /*
+ * get center from the main reflection list
+ */
+ refList = SXGetReflectionList();
+ SICSHdbGetPar(obj, pCon, "center", &v);
+ if (!GetRefIndexID(refList, v.v.text, hkl)) {
+ SCPrintf(pCon, eError, "ERROR: cannot find reflection with ID: %s",
+ v.v.text);
+ return 0;
+ }
+ center.h = hkl[0];
+ center.k = hkl[1];
+ center.l = hkl[2];
+ GetRefAnglesID(refList, v.v.text, ang);
+ center.s2t = ang[0];
+ center.om = ang[1];
+ center.chi = ang[2];
+ center.phi = ang[3];
+
+ SICSHdbGetPar(obj, pCon, "target", &v);
+ target.h = v.v.floatArray[0];
+ target.k = v.v.floatArray[1];
+ target.l = v.v.floatArray[2];
+ openingAngle = angleBetweenReflections(B, center, target);
+
/*
* calculate conversion matrix from cone system to PSI system
*/
- csToPsi = makeCsToPsiMatrix(center,self->ubi->hkl->fLambda);
- if(csToPsi == NULL){
- SCWrite(pCon,"ERROR: bad parameters: failed to generate conversion matrix",
+ csToPsi = makeCsToPsiMatrix(center, SXGetLambda());
+ if (csToPsi == NULL) {
+ SCWrite(pCon,
+ "ERROR: bad parameters: failed to generate conversion matrix",
eError);
- return 0;
+ return 0;
}
-
+
/*
* calculate scattering vector on cone and make its length
* match the length of the apropriate scattering vector
*/
- length = scatteringVectorLength(B,self->target) * self->qScale;
+ SICSHdbGetPar(obj, pCon, "target", &v);
+ target.h = v.v.floatArray[0];
+ target.k = v.v.floatArray[1];
+ target.l = v.v.floatArray[2];
+ SICSHdbGetPar(obj, pCon, "qscale", &v);
+ /*
+ * calculate scattering vector on cone and make its length
+ * match the length of the apropriate scattering vector
+ */
+ length = scatteringVectorLength(B, target) * v.v.doubleValue;
newScat = calcConeVector(openingAngle, fVal, length, csToPsi);
- if(newScat == NULL){
- SCWrite(pCon,"ERROR: fails to calculate cone vector",eError);
+ if (newScat == NULL) {
+ SCWrite(pCon, "ERROR: fails to calculate cone vector", eError);
return 0;
}
/*
* try to find setting angles for this vector
*/
- status = findAllowedBisecting(self->pHkl->fLambda,newScat, fSet,
- hklInRange, self->pHkl);
+ status = findAllowedBisecting(SXGetLambda(), newScat, fSet,
+ hklInRange, self->pHkl);
/*
* clean up matrices
*/
- mat_free(B);
- mat_free(newScat);
- mat_free(csToPsi);
- if(status != 1){
- SCWrite(pCon,"ERROR: cannot get cone vector into scattering position",
- eError);
- SCSetInterrupt(pCon,eAbortOperation);
- return 0;
- }
- self->lastConeAngle = fVal;
+ mat_free(B);
+ mat_free(newScat);
+ mat_free(csToPsi);
+ if (status != 1) {
+ SCWrite(pCon, "ERROR: cannot get cone vector into scattering position",
+ eError);
+ SCSetInterrupt(pCon, eAbortOperation);
+ return 0;
+ }
+ self->lastConeAngle = fVal;
/*
* start motors
*/
- return startHKLMotors(self->pHkl, pCon,fSet);
+ for (i = 0; i < 4; i++) {
+ ffSet[i] = fSet[i];
+ }
+ return startHKLMotors(self->pHkl, pCon, ffSet);
}
-/*---------------------------------------------------------------------------------------------------*/
-static int checkMotors(pConeData self, SConnection *pCon){
- int status;
- status = self->pHkl->pTheta->pDrivInt->CheckStatus(self->pHkl->pTheta, pCon);
- if(status != HWIdle && status != OKOK){
- return status;
- }
- status = self->pHkl->pOmega->pDrivInt->CheckStatus(self->pHkl->pOmega, pCon);
- if(status != HWIdle && status != OKOK){
- return status;
- }
- status = self->pHkl->pChi->pDrivInt->CheckStatus(self->pHkl->pChi, pCon);
- if(status != HWIdle && status != OKOK){
- return status;
- }
- status = self->pHkl->pPhi->pDrivInt->CheckStatus(self->pHkl->pPhi, pCon);
- if(status != HWIdle && status != OKOK){
- return status;
+/*---------------------------------------------------------------------------------------------------*/
+static int checkMotors(pConeData self, SConnection * pCon)
+{
+ int status, i;
+ pMotor pMot = NULL;
+ MotorFunction mots[] = { TwoTheta, Omega, Chi, Phi };
+
+ for (i = 0; i < 4; i++) {
+ pMot = SXGetMotor(mots[i]);
+ if (pMot != NULL) {
+ status = pMot->pDrivInt->CheckStatus(pMot, pCon);
+ if (status != HWIdle && status != OKOK) {
+ return status;
+ }
+ }
}
return HWIdle;
}
+
/*-----------------------------------------------------------------------------------------------------*/
-static int ConeCheckStatus(void *pData, SConnection *pCon){
+static int ConeCheckStatus(void *pData, SConnection * pCon)
+{
+ pSICSOBJ obj = pData;
pConeData self = NULL;
int status;
- self = (pConeData)pData;
+ self = (pConeData) obj->pPrivate;
assert(self != NULL);
- return checkMotors(self,pCon);
+ return checkMotors(self, pCon);
}
+
/*-----------------------------------------------------------------------------------------------------*/
-static float ConeGetValue(void *pData, SConnection *pCon){
+static float ConeGetValue(void *pData, SConnection * pCon)
+{
+ pSICSOBJ obj = pData;
pConeData self = NULL;
float fVal[3];
int status;
- self = (pConeData)pData;
+ self = (pConeData) obj->pPrivate;
assert(self != NULL);
- return self->lastConeAngle;
+ return self->lastConeAngle;
}
+
/*=============================== Live and Death ====================================*/
-static pConeData MakeConeMot(pUBCALC u){
+static pConeData MakeConeMot()
+{
pConeData self = NULL;
- assert(u != NULL);
-
- self = (pConeData)malloc(sizeof(coneData));
- if(self == NULL){
+ self = (pConeData) malloc(sizeof(coneData));
+ if (self == NULL) {
return NULL;
}
- memset(self,0,sizeof(coneData));
- self->pDes = CreateDescriptor("Cone");
+ memset(self, 0, sizeof(coneData));
self->pDriv = CreateDrivableInterface();
- if(self->pDes == NULL || self->pDriv == NULL){
+ if (self->pDriv == NULL) {
free(self);
return NULL;
}
- self->pDes->GetInterface = ConeGetInterface;
+
self->pDriv->Halt = ConeHalt;
self->pDriv->CheckLimits = ConeCheckLimits;
self->pDriv->SetValue = ConeSetValue;
self->pDriv->CheckStatus = ConeCheckStatus;
self->pDriv->GetValue = ConeGetValue;
- self->ubi = u;
- self->pHkl = u->hkl;
- self->qScale = 1.0;
return self;
}
-/*----------------------------------------------------------------------------------*/
-static void KillConeMot(void *pData){
- pConeData self = NULL;
- self = (pConeData)pData;
- if(self == NULL){
- return;
- }
- if(self->pDes != NULL){
- DeleteDescriptor(self->pDes);
- }
- if(self->pDriv){
- free(self->pDriv);
- }
- free(self);
-}
-/*=============================== Interpreter Interface ============================*/
-int ConeAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){
- pConeData self = NULL;
- float value;
- int id;
- char pBuffer[132];
-
- self = (pConeData)pData;
- assert(self != NULL);
-
- if(argc > 1) {
- strtolower(argv[1]);
- if(strcmp(argv[1],"center") == 0){
- if(argc > 2){
- if(!SCMatchRights(pCon,usUser)){
- return 0;
- }
- id = atoi(argv[2]);
- if(id < 0 || id > 2 ){
- SCWrite(pCon,"ERROR: id must be between 0 - 3",eError);
- return 0;
- }
- self->center = id;
- SCSendOK(pCon);
- return 1;
- } else {
- snprintf(pBuffer,131,"%s.center = %d", argv[0], self->center);
- SCWrite(pCon,pBuffer,eValue);
- return 1;
- }
- } else if(strcmp(argv[1],"qscale") == 0){
- if(argc > 2){
- if(!SCMatchRights(pCon,usUser)){
- return 0;
- }
- self->qScale = atof(argv[2]);
- SCSendOK(pCon);
- return 1;
- } else {
- snprintf(pBuffer,131,"%s.qscale = %f", argv[0], self->qScale);
- SCWrite(pCon,pBuffer,eValue);
- return 1;
- }
- } else if (strcmp(argv[1],"target") == 0){
- if(argc >= 5){
- if(!SCMatchRights(pCon,usUser)){
- return 0;
- }
- self->target.h = atof(argv[2]);
- self->target.k = atof(argv[3]);
- self->target.l = atof(argv[4]);
- self->qScale = 1.;
- SCSendOK(pCon);
- return 1;
- } else {
- snprintf(pBuffer,131,"%s.target = %f %f %f", argv[0],
- self->target.h, self->target.k, self->target.l);
- SCWrite(pCon,pBuffer,eValue);
- return 1;
- }
- } else {
- SCWrite(pCon,"ERROR: subcommand to cone not known",eError);
- return 0;
- }
- }
-
- /*
- * default: print value
- */
- value = self->pDriv->GetValue(self,pCon);
- if(value < -9000.){
- snprintf(pBuffer,131,"ERROR: failed to read %s",argv[0]);
- SCWrite(pCon,pBuffer,eError);
- return 0;
- }
- snprintf(pBuffer,131,"%s = %f", argv[0], value);
- SCWrite(pCon,pBuffer,eValue);
- return 1;
-}
/*------------------------------------------------------------------------------------------*/
-int MakeCone(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){
- pUBCALC ubi = NULL;
+int MakeCone(SConnection * pCon, SicsInterp * pSics, void *pData, int argc,
+ char *argv[])
+{
+ pSICSOBJ pNew = NULL;
pConeData pMot = NULL;
- char pBuffer[131];
+ char pBuffer[131], pName[80];
int status;
+ pHdb cmd;
- if(argc < 3){
- SCWrite(pCon,"ERROR: insuffient number of arguments to MakeCone",eError);
+ if (argc > 1) {
+ strlcpy(pName, argv[1],80);
+ } else {
+ strcpy(pName, "cone");
+ }
+
+ pNew = MakeSICSOBJ(pName, "Cone");
+ pMot = MakeConeMot();
+ if (pNew == NULL || pMot == NULL) {
+ SCWrite(pCon, "ERROR: out of memory creating cone virtual motor",
+ eError);
return 0;
}
-
- ubi = FindCommandData(pSics,argv[2],"UBcalc");
- if(ubi == NULL){
- snprintf(pBuffer,131,"ERROR: %s is no UBcalc object" , argv[2]);
- SCWrite(pCon,pBuffer,eError);
- return 0;
+
+ pNew->pDes->GetInterface = ConeGetInterface;
+ pNew->pPrivate = pMot;
+ pNew->KillPrivate = DefaultFree;
+
+ cmd =
+ AddSICSHdbPar(pNew->objectNode, "target", usUser,
+ makeHdbValue(HIPFLOATAR, 3));
+ SetHdbProperty(cmd, "__save", "true");
+ cmd =
+ AddSICSHdbPar(pNew->objectNode, "qscale", usUser, MakeHdbFloat(1.));
+ SetHdbProperty(cmd, "__save", "true");
+ cmd =
+ AddSICSHdbPar(pNew->objectNode, "center", usUser,
+ MakeHdbText("unknown"));
+ SetHdbProperty(cmd, "__save", "true");
+
+
+ if (argc > 2) {
+ pMot->pHkl = FindCommandData(pSics, argv[2], "4-Circle-Calculus");
+ } else {
+ pMot->pHkl = FindCommandData(pSics, "hkl", "4-Circle-Calculus");
}
-
- pMot = MakeConeMot(ubi);
- if(pMot == NULL){
- SCWrite(pCon,"ERROR: out of memory creating cone virtual motor",eError);
+ if (pMot->pHkl == NULL) {
+ snprintf(pBuffer, 131, "ERROR: %s is no hkl object", argv[2]);
+ SCWrite(pCon, pBuffer, eError);
return 0;
- }
- status = AddCommand(pSics,argv[1],ConeAction,KillConeMot,pMot);
- if(status != 1){
- SCWrite(pCon,"ERROR: failed to create duplicate cone motor",eError);
+ }
+
+ status = AddCommand(pSics, pName, InterInvokeSICSOBJ, KillSICSOBJ, pNew);
+ if (status != 1) {
+ SCWrite(pCon, "ERROR: failed to create duplicate cone motor", eError);
}
return status;
-
}
diff --git a/cone.h b/cone.h
index b30ca423..4aa49263 100644
--- a/cone.h
+++ b/cone.h
@@ -13,21 +13,12 @@
#include "ubcalc.h"
/*-----------------------------------------------------------------------*/
-
typedef struct {
- pObjectDescriptor pDes;
- pIDrivable pDriv;
- reflection target;
- float lastConeAngle;
- float qScale;
- pUBCALC ubi;
- int center;
- pHKL pHkl;
+ pIDrivable pDriv;
+ float lastConeAngle;
+ pHKL pHkl;
} coneData, *pConeData;
-
/*----------------------------------------------------------------------*/
-int MakeCone(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
-int ConeAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int MakeCone(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
#endif
diff --git a/configfu.h b/configfu.h
index 998e7567..d84100df 100644
--- a/configfu.h
+++ b/configfu.h
@@ -8,23 +8,23 @@
--------------------------------------------------------------------------*/
#ifndef SICSCONFIG
#define SICSCONFIG
-
- int AddHalt(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+
+int AddHalt(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
/* configuration command: enters argv objects into Halt List of Interrupt.
This is the means how the server knows which hardware to halt in an
case of emergency. Implemented in intserv.c
- */
+ */
- int ListObjects(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int ListObjects(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
/*
lists all avialable objects. Realised in Scinter.c
- */
- int SicsAtt(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+ */
+int SicsAtt(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
/*
handling of SICS object attributes. In SCinter.c
- */
+ */
#endif
diff --git a/confvirtmot.h b/confvirtmot.h
index 919a18aa..6eb132bc 100644
--- a/confvirtmot.h
+++ b/confvirtmot.h
@@ -14,8 +14,8 @@
#include "sics.h"
int MakeConfigurableVirtualMotor(SConnection *pCon, SicsInterp *pSics,
- void *data, int aargc, char *argv[]);
+ void *data, int aargc, char *argv[]);
int ConfigurableVirtualMotorAction(SConnection *pCon, SicsInterp *pSics,
- void *data, int argc, char *argv[]);
+ void *data, int argc, char *argv[]);
#endif
diff --git a/confvirtmot.i b/confvirtmot.i
index 2aab838c..f1fc5739 100644
--- a/confvirtmot.i
+++ b/confvirtmot.i
@@ -5,19 +5,20 @@
-----------------------------------------------------------------------*/
typedef struct __CONFVIRTMOT {
- pObjectDescriptor pDes;
- pIDrivable pDriv;
- pICallBack pCall;
- char *name;
- char *scriptName;
- char *readScript;
- int motorList;
- float targetValue;
- int targetReached;
- int posCount;
- double last_report_time;
- char scriptError[512];
- int parseOK;
+ pObjectDescriptor pDes;
+ pIDrivable pDriv;
+ pICallBack pCall;
+ char *name;
+ char *scriptName;
+ char *readScript;
+ char *checkScript;
+ char *state;
+ int motorList;
+ float targetValue;
+ int targetReached;
+ int posCount;
+ char scriptError[512];
+ int parseOK;
}ConfigurableVirtualMotor, *pConfigurableVirtualMotor;
diff --git a/confvirtualmot.c b/confvirtualmot.c
index 7e99b2f0..c930f23f 100644
--- a/confvirtualmot.c
+++ b/confvirtualmot.c
@@ -9,6 +9,22 @@
Mark Koennecke, August 2004
interest added: Ferdi Franceschini, April 2006
+
+ Additions:
+ - a checkscript to be run at the end of driving the motor
+ - a means to call the write script multiple times. This is useful if
+ you need to drive to the value in multiple steps. An example is the
+ BOA double crystal monochromator where you first have to pu the baldes to
+ 0, then drive the translation and then drive the blades to the real theta.
+ All this to avoid collisions. In order to support this, a state field and
+ and a readable target field has been added. The mode of operation is such
+ that the on first run the, writescript set the state to something different
+ then idle. This causes after the first set of motors finished running the
+ writescript to be called again. This can figure out by lookin at the
+ state variable what to do. This can be doen in repetition until the
+ writescript sets state to idle again.
+
+ Mark Koennecke, April 2012
-------------------------------------------------------------------------*/
#include
#include
@@ -19,11 +35,7 @@
#include "confvirtmot.h"
#include "confvirtmot.i"
-#define BAD_VALUE (-9999.99)
-
extern char *stptok(char *s, char *t, int len, char *brk);
-extern int CheckMotiMatch(const void* context, const void* pUserData);
-extern double DoubleTime();
/*---------------------------------------------------------------------------
An internal data structure which holds information required to control
@@ -41,194 +53,211 @@ typedef struct {
typedef struct {
float fVal;
char *pName;
-} EventInfo;
+} EventInfo;
/* Data available when registering interest */
typedef struct {
char *pName;
SConnection *pCon;
- float lastValue;
-} RegisteredInfo, *pRegisteredInfo;
+ float lastValue;
+} RegisteredInfo, *pRegisteredInfo;
/*---------------------------------------------------------------------*/
-static int HaltMotors(void *pData){
- pConfigurableVirtualMotor self = (pConfigurableVirtualMotor)pData;
+static int HaltMotors(void *pData)
+{
+ pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
RealMotor tuktuk;
int iRet;
iRet = LLDnodePtr2First(self->motorList);
- while(iRet != 0)
- {
- LLDnodeDataTo(self->motorList,&tuktuk);
+ while (iRet != 0) {
+ LLDnodeDataTo(self->motorList, &tuktuk);
tuktuk.pDriv->Halt(tuktuk.data);
iRet = LLDnodePtr2Next(self->motorList);
}
return 1;
}
+
/*----------------------------------------------------------------------*/
-static char *invokeMotorScript(pConfigurableVirtualMotor self,
- float newValue){
+static char *invokeMotorScript(pConfigurableVirtualMotor self,
+ float newValue)
+{
char pBueffel[512];
Tcl_Interp *pTcl;
int status;
self->parseOK = 1;
- if(self->scriptName == NULL){
- snprintf(self->scriptError,511,
- "ERROR: no script configured for configurable virtual motor");
+ if (self->scriptName == NULL) {
+ snprintf(self->scriptError, 511,
+ "ERROR: no script configured for configurable virtual motor");
self->parseOK = 0;
return NULL;
}
- snprintf(pBueffel,510,"%s %f",self->scriptName, newValue);
+ snprintf(pBueffel, 510, "%s %f", self->scriptName, newValue);
pTcl = InterpGetTcl(pServ->pSics);
status = Tcl_Eval(pTcl, pBueffel);
- if(status != TCL_OK){
- snprintf(self->scriptError,510,"ERROR: Tcl subsystem reported %s",
- Tcl_GetStringResult(pTcl));
+ if (status != TCL_OK) {
+ snprintf(self->scriptError, 510, "ERROR: Tcl subsystem reported %s",
+ Tcl_GetStringResult(pTcl));
self->parseOK = 0;
return NULL;
}
- return (char *)Tcl_GetStringResult(pTcl);
+ return (char *) Tcl_GetStringResult(pTcl);
}
/*--------------------------------------------------------------------*/
-static int parseEntry(pConfigurableVirtualMotor self,
- char *entry){
+static int parseEntry(pConfigurableVirtualMotor self, char *entry)
+{
RealMotor tuktuk;
char *pPtr = NULL;
char number[80], pError[256];
CommandList *pCom = NULL;
int status;
-
+
pPtr = entry;
- pPtr = stptok(pPtr,tuktuk.name,131,"=");
- if(pPtr == NULL){
- snprintf(self->scriptError,510,"ERROR: cannot interpret %s, %s", entry,
- "require format: motor=value");
+ pPtr = stptok(pPtr, tuktuk.name, 131, "=");
+ if (pPtr == NULL) {
+ snprintf(self->scriptError, 510, "ERROR: cannot interpret %s, %s",
+ entry, "require format: motor=value");
self->parseOK = 0;
return 0;
}
- tuktuk.pDriv = (pIDrivable)FindDrivable(pServ->pSics,tuktuk.name);
- pCom = FindCommand(pServ->pSics,tuktuk.name);
- if(!pCom){
- snprintf(self->scriptError,510,"ERROR: %s not found",tuktuk.name);
+ tuktuk.pDriv = (pIDrivable) FindDrivable(pServ->pSics, tuktuk.name);
+ pCom = FindCommand(pServ->pSics, tuktuk.name);
+ if (!pCom) {
+ snprintf(self->scriptError, 510, "ERROR: %s not found", tuktuk.name);
self->parseOK = 0;
return 0;
}
tuktuk.data = pCom->pData;
-
- if(tuktuk.pDriv == NULL){
- snprintf(self->scriptError,510,"ERROR: %s is not drivable",tuktuk.name);
+
+ if (tuktuk.pDriv == NULL) {
+ snprintf(self->scriptError, 510, "ERROR: %s is not drivable",
+ tuktuk.name);
self->parseOK = 0;
return 0;
}
- pPtr = stptok(pPtr,number,79,"=");
+ pPtr = stptok(pPtr, number, 79, "=");
tuktuk.value = atof(number);
- LLDnodeAppendFrom(self->motorList,&tuktuk);
+ LLDnodeAppendFrom(self->motorList, &tuktuk);
return 1;
}
+
/*----------------------------------------------------------------------*/
static int parseCommandList(pConfigurableVirtualMotor self,
- char *commandList){
+ char *commandList)
+{
char pEntry[256], *pPtr;
int status;
LLDdelete(self->motorList);
self->motorList = LLDcreate(sizeof(RealMotor));
-
+
pPtr = commandList;
- while((pPtr = stptok(pPtr,pEntry,255,",")) != NULL){
- status = parseEntry(self,pEntry);
- if(status != 1){
+ while ((pPtr = stptok(pPtr, pEntry, 255, ",")) != NULL) {
+ status = parseEntry(self, pEntry);
+ if (status != 1) {
return 0;
}
- }
+ }
return 1;
}
+
/*-----------------------------------------------------------------------*/
-static int startMotorList(pConfigurableVirtualMotor self, SConnection *pCon){
+static int startMotorList(pConfigurableVirtualMotor self,
+ SConnection * pCon)
+{
RealMotor tuktuk;
int status, iRet;
iRet = LLDnodePtr2First(self->motorList);
- while(iRet != 0)
- {
- LLDnodeDataTo(self->motorList,&tuktuk);
- status = tuktuk.pDriv->SetValue(tuktuk.data,pCon,tuktuk.value);
- if(status != 1){
+ while (iRet != 0) {
+ LLDnodeDataTo(self->motorList, &tuktuk);
+ status = tuktuk.pDriv->SetValue(tuktuk.data, pCon, tuktuk.value);
+ if (status != 1) {
return status;
}
tuktuk.running = 1;
- LLDnodeDataFrom(self->motorList,&tuktuk);
+ LLDnodeDataFrom(self->motorList, &tuktuk);
iRet = LLDnodePtr2Next(self->motorList);
}
return OKOK;
}
+
/*------------------------------------------------------------------------*/
-static long ConfSetValue(void *pData, SConnection *pCon, float newValue){
- pConfigurableVirtualMotor self = (pConfigurableVirtualMotor)pData;
+static long ConfSetValue(void *pData, SConnection * pCon, float newValue)
+{
+ pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
char *commandList = NULL;
- int status;
+ int status;
assert(self != NULL);
- commandList = invokeMotorScript(self,newValue);
- if(commandList == NULL){
- SCWrite(pCon,self->scriptError,eError);
+ commandList = invokeMotorScript(self, newValue);
+ if (commandList == NULL) {
+ SCWrite(pCon, self->scriptError, eError);
return 0;
}
- status = parseCommandList(self,commandList);
- if(status != 1){
- SCWrite(pCon,self->scriptError,eError);
+ status = parseCommandList(self, commandList);
+ if (status != 1) {
+ SCWrite(pCon, self->scriptError, eError);
return 0;
}
self->targetValue = newValue;
self->targetReached = 0;
self->posCount = 0;
- self->last_report_time = 0.0;
- status = startMotorList(self,pCon);
- if(status != OKOK){
+ status = startMotorList(self, pCon);
+ if (status != OKOK) {
HaltMotors(self);
}
return OKOK;
}
+
/*-----------------------------------------------------------------------*/
-static int ConfCheckLimits(void *pData, float fVal, char *error, int errLen){
- pConfigurableVirtualMotor self = (pConfigurableVirtualMotor)pData;
+static int ConfCheckLimits(void *pData, float fVal, char *error,
+ int errLen)
+{
+ pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
char *commandList = NULL;
int status, iRet;
RealMotor tuktuk;
assert(self != NULL);
- if(self->targetValue != fVal){
- commandList = invokeMotorScript(self,fVal);
- if(commandList == NULL){
- strncpy(error,self->scriptError,errLen);
+ if (self->targetValue != fVal) {
+ commandList = invokeMotorScript(self, fVal);
+ if (commandList == NULL) {
+ strlcpy(error, self->scriptError, errLen);
return 0;
}
- status = parseCommandList(self,commandList);
- if(status != 1){
- strncpy(error,self->scriptError,errLen);
+ status = parseCommandList(self, commandList);
+ if (status != 1) {
+ strlcpy(error, self->scriptError, errLen);
return 0;
}
}
+ if(self->state != NULL){
+ free(self->state);
+ }
+ self->state = strdup("idle");
+
iRet = LLDnodePtr2First(self->motorList);
- while(iRet != 0)
- {
- LLDnodeDataTo(self->motorList,&tuktuk);
- status = tuktuk.pDriv->CheckLimits(tuktuk.data,tuktuk.value,error,errLen);
- if(status != 1){
+ while (iRet != 0) {
+ LLDnodeDataTo(self->motorList, &tuktuk);
+ status =
+ tuktuk.pDriv->CheckLimits(tuktuk.data, tuktuk.value, error,
+ errLen);
+ if (status != 1) {
return status;
}
iRet = LLDnodePtr2Next(self->motorList);
@@ -236,192 +265,228 @@ static int ConfCheckLimits(void *pData, float fVal, char *error, int errLen){
return 1;
}
- static void KillInfo(void *pData)
- {
- pRegisteredInfo self = NULL;
-
- assert(pData);
- self = (pRegisteredInfo)pData;
- if(self->pName)
- {
- free(self->pName);
- }
- free(self);
- }
+static void KillInfo(void *pData)
+{
+ pRegisteredInfo self = NULL;
+
+ assert(pData);
+ self = (pRegisteredInfo) pData;
+ if (self->pName) {
+ free(self->pName);
+ }
+ if (self->pCon) {
+ SCDeleteConnection(self->pCon);
+ }
+ free(self);
+}
+
/*------------------- The CallBack function for interest ------------------
* iEvent: Event ID, see event.h for SICS events
* pEvent: May contain data from event generating object
* pUser: Data available when registering interest, see RegisteredInfo struct
- * defined above for available info */
- static int InterestCallback(int iEvent, void *pEvent, void *pUser,
- commandContext cc)
- {
- pRegisteredInfo pInfo = NULL;
- char pBueffel[80];
- EventInfo *pEventData;
-
- assert(pEvent);
- assert(pUser);
-
- pEventData = (EventInfo *)pEvent;
- pInfo = (RegisteredInfo *)pUser;
+ * defined above for available info
+--------------------------------------------------------------------------*/
+static int InterestCallback(int iEvent, void *pEvent, void *pUser)
+{
+ pRegisteredInfo pInfo = NULL;
+ char pBueffel[80];
+ EventInfo *pEventData;
- if (pInfo->lastValue != pEventData->fVal) {
- pInfo->lastValue = pEventData->fVal;
- (pInfo->pCon)->conEventType=POSITION;
- sprintf(pBueffel,"%s.position = %f ", pInfo->pName, pInfo->lastValue);
- SCWriteInContext(pInfo->pCon,pBueffel,eEvent,cc);
- }
- return 1;
- }
+ assert(pEvent);
+ assert(pUser);
+
+ if (!SCisConnected(pInfo->pCon)) {
+ return -1;
+ }
+
+ pEventData = (EventInfo *) pEvent;
+ pInfo = (RegisteredInfo *) pUser;
+
+ if (pInfo->lastValue != pEventData->fVal) {
+ pInfo->lastValue = pEventData->fVal;
+ (pInfo->pCon)->conEventType = POSITION;
+ sprintf(pBueffel, "%s.position = %f ", pInfo->pName, pInfo->lastValue);
+ SCWrite(pInfo->pCon, pBueffel, eEvent);
+ }
+ return 1;
+}
+/*---------------------------------------------------------------------*/
+static void invokeCheckScript(pConfigurableVirtualMotor self,
+ SConnection * pCon)
+{
+ Tcl_Interp *pTcl;
+ int status;
+
+ pTcl = InterpGetTcl(pServ->pSics);
+
+ if(self->checkScript != NULL){
+ status = Tcl_Eval(pTcl, self->checkScript);
+ if (status != TCL_OK) {
+ snprintf(self->scriptError, 510, "ERROR: Tcl subsystem reported %s",
+ Tcl_GetStringResult(pTcl));
+ SCWrite(pCon, self->scriptError, eError);
+ }
+ }
+}
/*------------------------------------------------------------------------*/
-static int ConfCheckStatus(void *pData, SConnection *pCon){
- pConfigurableVirtualMotor self = (pConfigurableVirtualMotor)pData;
+static int ConfCheckStatus(void *pData, SConnection * pCon)
+{
+ pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
RealMotor tuktuk;
int iRet, status, result;
EventInfo event;
result = HWIdle;
iRet = LLDnodePtr2First(self->motorList);
- while(iRet != 0)
- {
- LLDnodeDataTo(self->motorList,&tuktuk);
- if(tuktuk.running == 1){
+ while (iRet != 0) {
+ LLDnodeDataTo(self->motorList, &tuktuk);
+ if (tuktuk.running == 1) {
status = tuktuk.pDriv->CheckStatus(tuktuk.data, pCon);
- switch(status){
+ switch (status) {
case HWIdle:
- tuktuk.running = 0;
- LLDnodeDataFrom(self->motorList,&tuktuk);
- break;
+ tuktuk.running = 0;
+ LLDnodeDataFrom(self->motorList, &tuktuk);
+ break;
case HWBusy:
- result = HWBusy;
- break;
+ result = HWBusy;
+ break;
case HWFault:
case HWPosFault:
- return status;
- break;
+ if(self->state != NULL){
+ free(self->state);
+ self->state = strdup("idle");
+ }
+ return status;
+ break;
default:
- /*
- this is a programming error and has to be fixed
- */
- assert(0);
+ /*
+ this is a programming error and has to be fixed
+ */
+ assert(0);
}
}
iRet = LLDnodePtr2Next(self->motorList);
}
if (result == HWIdle) {
- event.pName = self->name;
- event.fVal = self->pDriv->GetValue(self,pCon);
- InvokeCallBack(self->pCall, MOTDRIVE, &event);
+ /*
+ * Do we have to do another step? If so run it.
+ */
+ if(strstr(self->state,"idle") == NULL){
+ status = ConfSetValue(self,pCon,self->targetValue);
+ if(status == OKOK){
+ result = HWBusy;
+ }
+ } else {
+ invokeCheckScript(self,pCon);
+ event.pName = self->name;
+ event.fVal = self->pDriv->GetValue(self, pCon);
+ InvokeCallBack(self->pCall, MOTDRIVE, &event);
+ }
} else if (result == HWBusy) {
-#if 1
- double current_time, skip_time;
- current_time = DoubleTime();
- skip_time = 0.500;
- if (self->last_report_time + skip_time <= current_time)
-#else
self->posCount++;
- if(self->posCount >= 10/*ObVal(self->ParArray,MOVECOUNT)*/)
-#endif
- {
+ if (self->posCount >= 10 /*ObVal(self->ParArray,MOVECOUNT) */ ) {
event.pName = self->name;
- event.fVal = self->pDriv->GetValue(self,pCon);
+ event.fVal = self->pDriv->GetValue(self, pCon);
InvokeCallBack(self->pCall, MOTDRIVE, &event);
-#if 1
- self->last_report_time = current_time;
-#else
self->posCount = 0;
-#endif
}
}
return result;
}
+
/*---------------------------------------------------------------------*/
-static float invokeReadScript(pConfigurableVirtualMotor self,
- SConnection *pCon){
+static float invokeReadScript(pConfigurableVirtualMotor self,
+ SConnection * pCon)
+{
Tcl_Interp *pTcl;
int status;
pTcl = InterpGetTcl(pServ->pSics);
status = Tcl_Eval(pTcl, self->readScript);
- if(status != TCL_OK){
- snprintf(self->scriptError,510,"ERROR: Tcl subsystem reported %s",
- Tcl_GetStringResult(pTcl));
- SCWrite(pCon,self->scriptError,eError);
+ if (status != TCL_OK) {
+ snprintf(self->scriptError, 510, "ERROR: Tcl subsystem reported %s",
+ Tcl_GetStringResult(pTcl));
+ SCWrite(pCon, self->scriptError, eError);
}
return atof(Tcl_GetStringResult(pTcl));
}
+
/*---------------------------------------------------------------------*/
-static void checkMotorValues(pConfigurableVirtualMotor self,
- SConnection *pCon){
+static void checkMotorValues(pConfigurableVirtualMotor self,
+ SConnection * pCon)
+{
int iRet;
float value;
RealMotor tuktuk;
char pBueffel[512];
iRet = LLDnodePtr2First(self->motorList);
- while(iRet != 0)
- {
- LLDnodeDataTo(self->motorList,&tuktuk);
- value = tuktuk.pDriv->GetValue(tuktuk.data,pCon);
+ while (iRet != 0) {
+ LLDnodeDataTo(self->motorList, &tuktuk);
+ value = tuktuk.pDriv->GetValue(tuktuk.data, pCon);
value -= tuktuk.value;
- if(value < .0){
+ if (value < .0) {
value *= -1;
}
- if(value > .1) {
- snprintf(pBueffel,510,"WARNING: motor %s of position by %f",
- tuktuk.name,value);
- SCWrite(pCon,pBueffel,eWarning);
+ if (value > .1) {
+ snprintf(pBueffel, 510, "WARNING: motor %s of position by %f",
+ tuktuk.name, value);
+ SCWrite(pCon, pBueffel, eWarning);
return;
}
iRet = LLDnodePtr2Next(self->motorList);
}
self->targetReached = 1;
-}
+}
+
/*-----------------------------------------------------------------------*/
-static float ConfGetValue(void *pData, SConnection *pCon){
- pConfigurableVirtualMotor self = (pConfigurableVirtualMotor)pData;
- float currentValue = BAD_VALUE;
+static float ConfGetValue(void *pData, SConnection * pCon)
+{
+ pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
+ float currentValue = -9999.99;
assert(self != NULL);
- if(self->readScript != NULL){
- currentValue = invokeReadScript(self,pCon);
+ if (self->readScript != NULL) {
+ currentValue = invokeReadScript(self, pCon);
} else {
- if(self->targetReached == 1){
+ if (self->targetReached == 1) {
return self->targetValue;
} else {
- checkMotorValues(self,pCon);
- if(self->targetReached){
- currentValue = self->targetValue;
+ checkMotorValues(self, pCon);
+ if (self->targetReached) {
+ currentValue = self->targetValue;
}
}
}
return currentValue;
}
+
/*-----------------------------------------------------------------------*/
-static void *GetConfigurableVirtualMotorInterface(void *pData, int iID){
+static void *GetConfigurableVirtualMotorInterface(void *pData, int iID)
+{
pConfigurableVirtualMotor self = NULL;
- self = (pConfigurableVirtualMotor)pData;
+ self = (pConfigurableVirtualMotor) pData;
assert(self);
- if(iID == DRIVEID){
+ if (iID == DRIVEID) {
return self->pDriv;
- } else if(iID == CALLBACKINTERFACE)
- {
+ } else if (iID == CALLBACKINTERFACE) {
return self->pCall;
}
return NULL;
}
+
/*-----------------------------------------------------------------------*/
-static void KillConfigurableVirtualMotor(void *data){
+static void KillConfigurableVirtualMotor(void *data)
+{
pConfigurableVirtualMotor self = NULL;
-
- self = (pConfigurableVirtualMotor)data;
- if(self != NULL){
- if(self->pDes != NULL){
+
+ self = (pConfigurableVirtualMotor) data;
+ if (self != NULL) {
+ if (self->pDes != NULL) {
DeleteDescriptor(self->pDes);
self->pDes = NULL;
}
@@ -430,60 +495,59 @@ static void KillConfigurableVirtualMotor(void *data){
free(self->name);
self->name = NULL;
}
- if(self->scriptName != NULL){
+ if (self->scriptName != NULL) {
free(self->scriptName);
self->scriptName = NULL;
}
- if(self->readScript != NULL){
+ if (self->readScript != NULL) {
free(self->readScript);
self->readScript = NULL;
}
- if (self->pCall != NULL) {
- DeleteCallBackInterface(self->pCall);
- self->pCall = NULL;
- }
- if (self->pDriv != NULL) {
- free(self->pDriv);
- self->pDriv = NULL;
+ if(self->state != NULL){
+ free(self->state);
+ self->state = NULL;
}
free(self);
self = NULL;
}
}
+
/*------------------------------------------------------------------------*/
-int MakeConfigurableVirtualMotor(SConnection *pCon, SicsInterp *pSics,
- void *data, int argc, char *argv[]){
+int MakeConfigurableVirtualMotor(SConnection * pCon, SicsInterp * pSics,
+ void *data, int argc, char *argv[])
+{
pConfigurableVirtualMotor pNew = NULL;
char pBueffel[512];
- if(argc < 2){
- SCWrite(pCon,"ERROR: need name to create configurable motor",eError);
+ if (argc < 2) {
+ SCWrite(pCon, "ERROR: need name to create configurable motor", eError);
return 0;
}
- pNew = (pConfigurableVirtualMotor)malloc(sizeof(ConfigurableVirtualMotor));
- if(pNew == NULL){
- SCWrite(pCon,"ERROR: no memory to create configurable virtual motor",
- eError);
+ pNew =
+ (pConfigurableVirtualMotor) malloc(sizeof(ConfigurableVirtualMotor));
+ if (pNew == NULL) {
+ SCWrite(pCon, "ERROR: no memory to create configurable virtual motor",
+ eError);
return 0;
}
- memset(pNew,0,sizeof(ConfigurableVirtualMotor));
+ memset(pNew, 0, sizeof(ConfigurableVirtualMotor));
pNew->name = strdup(argv[1]);
pNew->posCount = 0;
- pNew->last_report_time = 0.0;
pNew->pDes = CreateDescriptor("ConfigurableVirtualMotor");
pNew->pDriv = CreateDrivableInterface();
pNew->motorList = LLDcreate(sizeof(RealMotor));
- if(pNew->pDes == NULL || pNew->pDriv == NULL || pNew->motorList < 0){
- SCWrite(pCon,"ERROR: no memory to create configurable virtual motor",
- eError);
+ if (pNew->pDes == NULL || pNew->pDriv == NULL || pNew->motorList < 0) {
+ SCWrite(pCon, "ERROR: no memory to create configurable virtual motor",
+ eError);
return 0;
}
+ pNew->state = strdup("idle");
/*
- assign functions
- */
+ assign functions
+ */
pNew->pDes->GetInterface = GetConfigurableVirtualMotorInterface;
pNew->pDriv->Halt = HaltMotors;
pNew->pDriv->CheckLimits = ConfCheckLimits;
@@ -491,21 +555,20 @@ int MakeConfigurableVirtualMotor(SConnection *pCon, SicsInterp *pSics,
pNew->pDriv->CheckStatus = ConfCheckStatus;
pNew->pDriv->GetValue = ConfGetValue;
- /* initialise callback interface */
- pNew->pCall = CreateCallBackInterface();
- if(!pNew->pCall)
- {
- KillConfigurableVirtualMotor(pNew);
- return 0;
- }
+ /* initialise callback interface */
+ pNew->pCall = CreateCallBackInterface();
+ if (!pNew->pCall) {
+ KillConfigurableVirtualMotor(pNew);
+ return 0;
+ }
/*
- install command
- */
- if( AddCommand(pSics,argv[1],ConfigurableVirtualMotorAction,
- KillConfigurableVirtualMotor,pNew) != 1){
- snprintf(pBueffel,510,"ERROR: duplicate command %s not created",
- argv[1]);
- SCWrite(pCon,pBueffel,eError);
+ install command
+ */
+ if (AddCommand(pSics, argv[1], ConfigurableVirtualMotorAction,
+ KillConfigurableVirtualMotor, pNew) != 1) {
+ snprintf(pBueffel, 510, "ERROR: duplicate command %s not created",
+ argv[1]);
+ SCWrite(pCon, pBueffel, eError);
return 0;
} else {
SCSendOK(pCon);
@@ -513,100 +576,143 @@ int MakeConfigurableVirtualMotor(SConnection *pCon, SicsInterp *pSics,
return 1;
}
+
/*-----------------------------------------------------------------------*/
-int ConfigurableVirtualMotorAction(SConnection *pCon, SicsInterp *pSics,
- void *data, int argc, char *argv[]){
+int ConfigurableVirtualMotorAction(SConnection * pCon, SicsInterp * pSics,
+ void *data, int argc, char *argv[])
+{
pConfigurableVirtualMotor self = NULL;
char pBueffel[512];
float value;
+ int iRet;
long lID;
pRegisteredInfo pRegInfo = NULL;
- self = (pConfigurableVirtualMotor)data;
+ self = (pConfigurableVirtualMotor) data;
assert(self != NULL);
- if(argc > 1){
+ if (argc > 1) {
strtolower(argv[1]);
- if(strcmp(argv[1],"drivescript") == 0){
- if(argc > 2){
- /* set case */
- Arg2Text(argc-2,&argv[2],pBueffel,510);
- self->scriptName = strdup(pBueffel);
- SCSendOK(pCon);
- return 1;
- } else {
- /* inquiry */
- if(self->scriptName == NULL){
- snprintf(pBueffel,510,"%s.drivescript = UNDEFINED", argv[0]);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- } else {
- snprintf(pBueffel,510,"%s.drivescript = %s", argv[0],
- self->scriptName);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- }
- }else if(strcmp(argv[1],"readscript") == 0){
- if(argc > 2){
- /* set case */
- Arg2Text(argc-2,&argv[2],pBueffel,510);
- self->readScript = strdup(pBueffel);
- SCSendOK(pCon);
- return 1;
- } else {
- /* inquiry */
- if(self->readScript == NULL){
- snprintf(pBueffel,510,"%s.readscript = UNDEFINED", argv[0]);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- } else {
- snprintf(pBueffel,510,"%s.readscript = %s", argv[0],
- self->readScript);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- }
- } else if(strcmp(argv[1],"interest") == 0)
- {
- pRegInfo = (pRegisteredInfo)malloc(sizeof(RegisteredInfo));
- if(!pRegInfo)
- {
- SCWrite(pCon,"ERROR: out of memory in confvirtualmot.c",eError);
- return 0;
- }
- pRegInfo->pName = strdup(argv[0]);
- pRegInfo->pCon = pCon;
- value = ConfGetValue(self,pCon);
- if(value == BAD_VALUE)
- {
- sprintf(pBueffel,"Failed to register interest, Reason:Error obtaining current position for %s",argv[0]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- pRegInfo->lastValue = value;
-
- RemoveCallback3(self->pCall, InterestCallback, CheckMotiMatch, pCon); /* only this one */
- lID = RegisterCallback(self->pCall, SCGetContext(pCon),MOTDRIVE, InterestCallback, pRegInfo, KillInfo);
- SCRegister(pCon,pSics, self->pCall,lID);
+ if (strcmp(argv[1], "drivescript") == 0) {
+ if (argc > 2) {
+ /* set case */
+ Arg2Text(argc - 2, &argv[2], pBueffel, 510);
+ self->scriptName = strdup(pBueffel);
SCSendOK(pCon);
- return 1;
- }
- else if(strcmp(argv[1],"uninterest") == 0)
- {
- RemoveCallback3(self->pCall, InterestCallback, CheckMotiMatch, pCon);
- SCSendOK(pCon);
- return 1;
- } else {
- snprintf(pBueffel,5120,"ERROR: subcommand %s to %s unknown",
- argv[1],argv[0]);
- SCWrite(pCon,pBueffel,eError);
+ return 1;
+ } else {
+ /* inquiry */
+ if (self->scriptName == NULL) {
+ snprintf(pBueffel, 510, "%s.drivescript = UNDEFINED", argv[0]);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else {
+ snprintf(pBueffel, 510, "%s.drivescript = %s", argv[0],
+ self->scriptName);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ }
+ }
+ } else if (strcmp(argv[1], "readscript") == 0) {
+ if (argc > 2) {
+ /* set case */
+ Arg2Text(argc - 2, &argv[2], pBueffel, 510);
+ self->readScript = strdup(pBueffel);
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ /* inquiry */
+ if (self->readScript == NULL) {
+ snprintf(pBueffel, 510, "%s.readscript = UNDEFINED", argv[0]);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else {
+ snprintf(pBueffel, 510, "%s.readscript = %s", argv[0],
+ self->readScript);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ }
+ }
+ } else if (strcmp(argv[1], "checkscript") == 0) {
+ if (argc > 2) {
+ /* set case */
+ Arg2Text(argc - 2, &argv[2], pBueffel, 510);
+ self->checkScript = strdup(pBueffel);
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ /* inquiry */
+ if (self->checkScript == NULL) {
+ snprintf(pBueffel, 510, "%s.checkscript = UNDEFINED", argv[0]);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else {
+ snprintf(pBueffel, 510, "%s.checkscript = %s", argv[0],
+ self->checkScript);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ }
+ }
+ } else if (strcmp(argv[1], "state") == 0) {
+ if (argc > 2) {
+ /* set case */
+ Arg2Text(argc - 2, &argv[2], pBueffel, 510);
+ if(self->state != NULL){
+ free(self->state);
+ }
+ self->state = strdup(pBueffel);
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ /* inquiry */
+ if (self->state == NULL) {
+ snprintf(pBueffel, 510, "%s.state = UNDEFINED", argv[0]);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else {
+ snprintf(pBueffel, 510, "%s.state = %s", argv[0],
+ self->state);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ }
+ }
+ } else if (strcmp(argv[1], "target") == 0) {
+ /* inquiry */
+ snprintf(pBueffel, 510, "%s.target = %f", argv[0], self->targetValue);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else if (strcmp(argv[1], "interest") == 0) {
+ pRegInfo = (pRegisteredInfo) malloc(sizeof(RegisteredInfo));
+ if (!pRegInfo) {
+ SCWrite(pCon, "ERROR: out of memory in confvirtualmot.c", eError);
+ return 0;
+ }
+ pRegInfo->pName = strdup(argv[0]);
+ pRegInfo->pCon = SCCopyConnection(pCon);
+ value = ConfGetValue(self, pCon);
+ if (value < -9990.) {
+ snprintf(pBueffel,511,
+ "Failed to register interest, Reason:Error obtaining current position for %s",
+ argv[0]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ pRegInfo->lastValue = value;
+
+ lID = RegisterCallback(self->pCall, MOTDRIVE,
+ InterestCallback, pRegInfo, KillInfo);
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ snprintf(pBueffel, 5120, "ERROR: subcommand %s to %s unknown",
+ argv[1], argv[0]);
+ SCWrite(pCon, pBueffel, eError);
return 0;
}
} else {
- value = self->pDriv->GetValue(self,pCon);
- snprintf(pBueffel,510,"%s = %f", argv[0],value);
- SCWrite(pCon,pBueffel,eValue);
+ value = self->pDriv->GetValue(self, pCon);
+ snprintf(pBueffel, 510, "%s = %f", argv[0], value);
+ SCWrite(pCon, pBueffel, eValue);
return 1;
}
}
diff --git a/confvirtualmot.w b/confvirtualmot.w
index 5a8110da..169ac0c1 100644
--- a/confvirtualmot.w
+++ b/confvirtualmot.w
@@ -16,6 +16,8 @@ typedef struct __CONFVIRTMOT {
char *name;
char *scriptName;
char *readScript;
+ char *checkScript;
+ char *state;
int motorList;
float targetValue;
int targetReached;
@@ -33,6 +35,7 @@ The fields are:
\item[scriptName] The name of the program to calculate the new positions
of the real motors.
\item[readScript] A script to read back the current value of the virtual motor.
+\item[checkScript] A script to check for success at the end of driving.
\item[motorList] A list of the motors to start and control.
\item[targetValue] The target value we wanted to have.
\item[posCount] This counter prevents the callback from being invoked too often. The frequency is currently set to every 10 cycles through the task loop.
diff --git a/conman.c b/conman.c
index 33385e83..99969576 100644
--- a/conman.c
+++ b/conman.c
@@ -5,7 +5,6 @@
below.
-
Mark Koennecke, October 1996
SMInvoke added. Mark Koennecke, April 1997
@@ -42,6 +41,10 @@
Aded buffering support, Mark Koennecke, July 2006
Copyright: see copyright.h
+
+ substantially revised for asynchronous I/O
+
+ Mark Koennecke, January 2009
-----------------------------------------------------------------------------*/
#include "fortify.h"
#include
@@ -76,7 +79,7 @@
extern pServer pServ;
-#include "outcode.c" /* text for OutCode */
+#include "outcode.c" /* text for OutCode */
/*------ Max Size of Command Stack */
@@ -86,580 +89,602 @@ extern pServer pServ;
/*-------------------------------------------------------------------------
a structure for holding callback info
*/
- typedef struct {
- long lID;
- pICallBack pInterface;
- } Item;
+typedef struct {
+ long lID;
+ pICallBack pInterface;
+} Item;
/*------------- a number for generating automatic names --------------------*/
- static int iName = 0;
- static SConnection *freeConnections = NULL;
- static long lastIdent = 0;
+static int iName = 0;
+static long lastIdent = 0;
/*------------- sending connection (prevent double write when listening) ----*/
- static SConnection *sendingConnection = NULL;
+static int sendingConnection = 0;
/*------------- storing connection and context for later use ----*/
- struct SCStore {
- SConnection *pCon;
- long ident;
- int inMacro;
- long macroStack;
- commandContext cc;
- };
+struct SCStore {
+ SConnection *pCon;
+ long ident;
+ int inMacro;
+ long macroStack;
+ commandContext cc;
+};
/*===========================================================================*/
- static char *ConName(long ident) {
- static char name[32];
- snprintf(name, sizeof(name), "CON%ld", ident);
- return name;
- }
+static char *ConName(long ident)
+{
+ static char name[32];
+ snprintf(name, sizeof(name), "CON%ld", ident);
+ return name;
+}
/*--------------------------------------------------------------------------*/
- static void FreeConnection(SConnection *pCon)
- {
- memset(pCon,0,sizeof(SConnection));
- pCon->ident = 0;
- pCon->next = freeConnections;
- pCon->listening = 0;
- freeConnections = pCon;
- }
+char *ConID(SConnection *pCon)
+{
+ static char id[132];
+ char host[80];
+
+ if(ANETvalidHandle(pCon->sockHandle)){
+ ANETinfo(pCon->sockHandle, host, sizeof(host));
+ snprintf(id,sizeof(id),"%s:%2.2d", host, pCon->sockHandle);
+ } else {
+ snprintf(id,sizeof(id),"disconnected:%2.2ld", pCon->ident);
+ }
+ return id;
+}
/*--------------------------------------------------------------------------*/
- static SConnection *CreateConnection(SicsInterp *pSics)
- {
- int i;
- SConnection *pRes = NULL;
- char pBueffel[253];
- char pHost[132];
-
- if (!freeConnections)
- { /* no more free connection: get one by malloc */
- pRes = (SConnection *)malloc(sizeof(SConnection));
- if(!pRes)
- {
- /* This is a serious, very serious error! */
- SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
- return NULL;
- }
- memset(pRes,0,sizeof(SConnection));
- }
- else
- { /* reuse an old connection */
- pRes = freeConnections;
- freeConnections = pRes->next;
- }
-
- do
- { /* loop until an unused ident is found. This test needed only for
- the case there some object has already the name con.
- In a live cycle of SICS, no connection ever can get an earlier
- used name */
- if (lastIdent == LONG_MAX)
- {
- /* This is a serious, very serious error! */
- SICSLogWrite("ERROR: Run out of connection identifiers!!",eInternal);
- return NULL;
- }
- lastIdent++;
- } while (FindCommand(pSics, ConName(lastIdent)));
- pRes->ident = lastIdent;
-
- /* a descriptor */
- pRes->pDes = CreateDescriptor("Connection");
- if(!pRes->pDes)
- {
+static void FreeConnection(SConnection * pCon)
+{
+ free(pCon);
+}
+
+/*------------------------------------------------------------------------*/
+void KillFreeConnections()
+{
+}
+
+ /*-------------------------------------------------------------------------*/
+static SConnection *SCMakeConnection()
+{
+ SConnection *pRes = NULL;
+
+ pRes = (SConnection *) malloc(sizeof(SConnection));
+ if (!pRes) {
+ /* This is a serious, very serious error! */
+ SICSLogWrite("ERROR: No memory to allocate connection!!", eInternal);
+ return NULL;
+ }
+ memset(pRes, 0, sizeof(SConnection));
+ return pRes;
+}
+
+/*--------------------------------------------------------------------------*/
+static SConnection *CreateConnection(SicsInterp * pSics)
+{
+ int i;
+ SConnection *pRes = NULL;
+ char pBueffel[253];
+ char pHost[132];
+
+ pRes = SCMakeConnection();
+
+ do { /* loop until an unused ident is found. This test needed only for
+ the case there some object has already the name con.
+ In a live cycle of SICS, no connection ever can get an earlier
+ used name */
+ if (lastIdent == LONG_MAX) {
/* This is a serious, very serious error! */
- SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
- FreeConnection(pRes);
- return NULL;
- }
-
- /* the callback registry */
- pRes->iList = LLDcreate(sizeof(Item));
-
- /* the command stack */
- pRes->pStack = CreateCommandStack();
- if( (pRes->iList <0) || (!pRes->pStack))
- {
- /* This is a serious, very serious error! */
- SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
- DeleteDescriptor(pRes->pDes);
- FreeConnection(pRes);
+ SICSLogWrite("ERROR: Run out of connection identifiers!!",
+ eInternal);
return NULL;
}
+ lastIdent++;
+ } while (FindCommand(pSics, ConName(lastIdent)));
+ pRes->ident = lastIdent;
- pRes->iOutput = eInError; /* gets everything except internal messages */
- pRes->iFiles = 0; /* default: no logfiles */
- pRes->inUse = 0;
- pRes->iMacro = 0;
- pRes->iTelnet = 0;
- pRes->eInterrupt = eContinue;
- pRes->lMagic = CONMAGIC;
- pRes->iLogin = 0;
- pRes->listening = 0;
- pRes->conStart = time(NULL);
- pRes->write = SCNormalWrite;
- for(i = 0; i < 10; i++)
- {
- pRes->pFiles[i] = NULL;
- }
-
- /* initialise context variables */
- pRes->iCmdCtr = 0;
- pRes->conEventType=-1;
- pRes->conStatus=-1;
- pRes->contextStack = LLDcreate(sizeof(commandContext));
-
- /* install command */
- AddCommand(pSics, ConName(pRes->ident), ConSicsAction, NULL,pRes);
- return pRes;
-
+ /* a descriptor */
+ pRes->pDes = CreateDescriptor("Connection");
+ if (!pRes->pDes) {
+ /* This is a serious, very serious error! */
+ SICSLogWrite("ERROR: No memory to allocate connection!!", eInternal);
+ FreeConnection(pRes);
+ return NULL;
}
-/*--------------------------------------------------------------------------*/
- SConnection *SCreateConnection(SicsInterp *pSics,mkChannel *pSock, int iUser)
- {
- SConnection *pRes = NULL;
- char pBueffel[253];
- char pHost[132];
-
- assert(pSock);
-
- pRes = CreateConnection(pSics);
-
- SetCommandStackMaxSize(pRes->pStack,MAXSTACK);
- pRes->pSock = pSock;
- pRes->iUserRights = iUser;
- pRes->iGrab = TokenGrabActive();
+ /* the callback registry */
+ pRes->iList = LLDcreate(sizeof(Item));
-
- return pRes;
-
+ /* the command stack */
+ pRes->pStack = CreateCommandStack();
+ if ((pRes->iList < 0) || (!pRes->pStack)) {
+ /* This is a serious, very serious error! */
+ SICSLogWrite("ERROR: No memory to allocate connection!!", eInternal);
+ DeleteDescriptor(pRes->pDes);
+ FreeConnection(pRes);
+ return NULL;
}
+
+ pRes->iOutput = eInError; /* gets everything except internal messages */
+ pRes->inUse = 0;
+ pRes->iMacro = 0;
+ pRes->iTelnet = 0;
+ pRes->eInterrupt = eContinue;
+ pRes->lMagic = CONMAGIC;
+ pRes->iLogin = 0;
+ pRes->listening = 0;
+ pRes->conStart = time(NULL);
+ pRes->write = SCNormalWrite;
+ pRes->runLevel = RUNDRIVE;
+
+ /* initialise context variables */
+ pRes->iCmdCtr = 0;
+ pRes->conEventType = -1;
+ pRes->conStatus = -1;
+ pRes->contextStack = LLDcreate(sizeof(commandContext));
+
+ /* install command */
+ AddCommand(pSics, ConName(pRes->ident), ConSicsAction, NULL, pRes);
+ return pRes;
+
+}
+
/*--------------------------------------------------------------------------*/
- SConnection *SCCreateDummyConnection(SicsInterp *pSics)
- {
- SConnection *pRes = NULL;
-
- pRes = CreateConnection(pSics);
-
- pRes->pSock = NULL;
- pRes->iUserRights = usInternal;
- pRes->iGrab = 0;
-
- SICSLogWrite("Accepted dummy connection ",eInternal);
-
- return pRes;
- }
+SConnection *SCreateConnection(SicsInterp * pSics, int sockHandle,
+ int iUser)
+{
+ SConnection *pRes = NULL;
+ char pBueffel[253];
+ char pHost[132];
+
+ pRes = CreateConnection(pSics);
+
+ SetCommandStackMaxSize(pRes->pStack, MAXSTACK);
+
+ pRes->sockHandle = sockHandle;
+ pRes->iUserRights = iUser;
+ pRes->iGrab = TokenGrabActive();
+ return pRes;
+}
+
/*--------------------------------------------------------------------------*/
- static int VerifyConnection(SConnection *self)
- {
- if(!self)
- {
- SICSLogWrite("MAGICERROR: Invalid call to NULL connection",eError);
- return 0;
- }
- if(self->lMagic != CONMAGIC)
- {
- SICSLogWrite("MAGICERROR: corrupted connection object",eError);
- return 0;
- }
- return 1;
- }
+SConnection *SCCreateDummyConnection(SicsInterp * pSics)
+{
+ SConnection *pRes = NULL;
+
+ pRes = CreateConnection(pSics);
+ if(pRes == NULL){
+ return pServ->dummyCon;
+ }
+
+ pRes->sockHandle = -1;
+ pRes->iUserRights = usInternal;
+ pRes->iGrab = 0;
+
+ SICSLogWrite("Accepted dummy connection ", eInternal);
+
+ return pRes;
+}
+
+/*--------------------------------------------------------------------------*/
+int VerifyConnection(SConnection * self)
+{
+ if (!self) {
+ SICSLogWrite("MAGICERROR: Invalid call to NULL connection", eError);
+ return 0;
+ }
+ if (self->lMagic != CONMAGIC) {
+ SICSLogWrite("MAGICERROR: corrupted connection object", eError);
+ return 0;
+ }
+ return 1;
+}
+
/*----------------------------------------------------------------------------*/
- int SCAddLogFile(SConnection *self, char *name)
- {
- char pBueffel[256];
- int iNum, i;
-
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
-
- /* find an empty number */
- if(self->iFiles < MAXLOGFILES)
- {
- iNum = self->iFiles;
- self->iFiles++;
- }
- else /* scan for an empty slot */
- {
- iNum = -1;
- for(i = 0; i < self->iFiles; i++)
- {
- if(self->pFiles[i] == NULL)
- {
- iNum = i;
- break;
- }
- }
- }
- /* nothing found ? */
- if(iNum < 0)
- {
- SCWrite(self,"ERROR: maximum number of logfiles exhausted",eError);
- return -1;
- }
-
- /* do the job */
- self->pFiles[iNum] = fopen(name,"a+");
- if(self->pFiles[iNum] == NULL)
- {
- sprintf(pBueffel,"ERROR Could not open logfile - %s -",name);
- SCWrite(self,pBueffel, 10);
- return -1; /* false */
- }
- else
- {
- return iNum; /* success */
- }
- }
-/*--------------------------------------------------------------------------*/
- int SCDelLogFile(SConnection *self, int iNum)
- {
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- if( (iNum >= 0) && (iNum < MAXLOGFILES) )
- {
- if(self->pFiles[iNum])
- {
- fclose(self->pFiles[iNum]);
- self->pFiles[iNum] = NULL;
- return 1;
- }
- }
- return 0;
- }
-/*----------------------------------------------------------------------------*/
- void SCSetOutputClass(SConnection *self, int iClass)
- {
- if(!VerifyConnection(self))
- {
- return;
- }
- self->iOutput = iClass;
+void SCSetOutputClass(SConnection * self, int iClass)
+{
+ if (!VerifyConnection(self)) {
+ return;
}
+ self->iOutput = iClass;
+}
+
/*---------------------------------------------------------------------------*/
- int SCinMacro(SConnection *self)
- {
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- if(self->iMacro)
- {
+int SCinMacro(SConnection * self)
+{
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ if (self->iMacro) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+int SCsetMacro(SConnection * self, int iMode)
+{
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+ assert((iMode == 0) || (iMode == 1));
+ self->iMacro = iMode;
+/* SCPrintf(self,eError, "SCsetMacro = %lx, %d\n", (long int)self, iMode); */
+ return 1;
+}
+
+ /*--------------------------------------------------------------------------*/
+void SCDeleteMasterFields(SConnection * pVictim)
+{
+ int iRet;
+ Item sItem;
+ pHdb root = NULL;
+ char pBueffel[512];
+
+ if (pVictim->pDes == NULL) {
+ return;
+ }
+
+ if (SCActive(pVictim)) {
+ SCnoSock(pVictim);
+ ANETclose(pVictim->sockHandle);
+ WriteToCommandLog("SYS>",
+ "ERROR: Erraneous deletion of used Connection stopped");
+ pVictim->sockHandle = -1;
+ return;
+ }
+
+ /* remove the connection from the server log if it has captured
+ something
+ */
+ KillCapture(pVictim);
+
+ /*
+ * remove any callbacks which might still be active in the Hipadaba
+ */
+ root = GetHipadabaRoot();
+ if (root != NULL) {
+ RemoveConnectionCallbacks(root, pVictim);
+ }
+
+ /*
+ If we have a grab, release it !
+ */
+ if (!pVictim->iGrab) {
+ if (pServ->pTasker) {
+ TaskSignal(pServ->pTasker, TOKENRELEASE, NULL);
+ TokenRelease();
+ }
+ }
+
+ /* log the kill */
+ if (pVictim->sockHandle >= 0 && pVictim->iLogin == 1 &&
+ (pVictim->iUserRights < 3 || !CompactCommandLog())) {
+ sprintf(pBueffel, "Deleting connection %d", pVictim->sockHandle);
+ WriteToCommandLog("SYS>", pBueffel);
+ SICSLogWrite(pBueffel, eInternal);
+ }
+
+ /* close all open files and sockets */
+ if (pVictim->sockHandle > 0) {
+ ANETwrite(pVictim->sockHandle, "SICSCLOSE", sizeof("SICSCLOSE"));
+ ANETprocess();
+ ANETclose(pVictim->sockHandle);
+ }
+ RemoveCommand(pServ->pSics, ConName(pVictim->ident));
+ /* remove all callbacks on this connection */
+ iRet = LLDnodePtr2First(pVictim->iList);
+ while (iRet != 0) {
+ LLDnodeDataTo(pVictim->iList, &sItem);
+ RemoveCallback(sItem.pInterface, sItem.lID);
+ iRet = LLDnodePtr2Next(pVictim->iList);
+ }
+ LLDdelete(pVictim->iList);
+ LLDdelete(pVictim->contextStack);
+ DeleteDescriptor(pVictim->pDes);
+
+}
+
+/*---------------------------------------------------------------------------*/
+void SCDeleteConnection(void *pData)
+{
+ int i, iRet;
+ char pBueffel[132];
+ SConnection *pVictim = NULL;
+
+ pVictim = (SConnection *) pData;
+ if (!VerifyConnection(pVictim)) {
+ return;
+ }
+
+ SCDeleteMasterFields(pVictim);
+
+ /* remove command stack */
+ if (pVictim->pStack != NULL) {
+ DeleteCommandStack(pVictim->pStack);
+ }
+
+ /* remove possible buffers */
+ if (pVictim->data != NULL && pVictim->dataOwner == 1) {
+ DeleteDynString(pVictim->data);
+ }
+
+ pVictim->lMagic = 0; /* make a write to a freed connection harmless */
+ /* finally free pVictim */
+ FreeConnection(pVictim);
+}
+
+/*--------------------------------------------------------------------------*/
+SConnection *SCCopyConnection(SConnection * pCon)
+{
+ SConnection *result = NULL;
+
+ result = SCMakeConnection();
+ if (result == NULL) {
+ return NULL;
+ }
+ result->sockHandle = pCon->sockHandle;
+ result->lMagic = pCon->lMagic;
+ result->iUserRights = pCon->iUserRights;
+ result->ident = pCon->ident;
+ result->iMacro = pCon->iMacro;
+ result->iTelnet = pCon->iTelnet;
+ result->iOutput = pCon->iOutput;
+ result->write = pCon->write;
+ result->listening = pCon->listening;
+ result->eInterrupt = pCon->eInterrupt;
+ result->inUse = pCon->inUse;
+ result->sicsError = pCon->sicsError;
+ result->iCmdCtr = pCon->iCmdCtr;
+ result->conEventType = pCon->conEventType;
+ result->conStatus = pCon->conStatus;
+ result->iProtocolID = pCon->iProtocolID;
+ result->transID = pCon->transID;
+ strcpy(result->deviceID, pCon->deviceID);
+ result->conStart = pCon->conStart;
+ result->contextStack = -1;
+ result->iList = -1;
+ result->runLevel = pCon->runLevel;
+ result->data = pCon->data;
+ return result;
+}
+
+/*---------------------------------------------------------------------------*/
+SConnection *SCfindMaster(SConnection * pCon)
+{
+ SConnection *result = NULL;
+ result =
+ (SConnection *) FindCommandData(pServ->pSics, ConName(pCon->ident),
+ "Connection");
+ if (result == NULL) {
+ printf("VERY, Very, very serious programming error!\n");
+ printf("I continue but things may be wrong! Please debug ASAP!\n");
+ if (pServ->dummyCon == NULL) {
+ pServ->dummyCon = SCCreateDummyConnection(pServ->pSics);
+ }
+ result = pServ->dummyCon;
+ }
+ return result;
+}
+
+/*---------------------------------------------------------------------------*/
+int SCisConnected(SConnection * pCon)
+{
+ if (!VerifyConnection(pCon)) {
+ return 0;
+ }
+ return ANETvalidHandle(pCon->sockHandle);
+}
+
+/*---------------------------------------------------------------------------*/
+static int HasNL(char *buffer)
+{
+ int i;
+ for (i = strlen(buffer); i > 0; i--) {
+ if (isprint(buffer[i])) {
+ break;
+ }
+ if (buffer[i] == '\n') {
return 1;
}
- else
- {
- return 0;
- }
- }
-/*---------------------------------------------------------------------------*/
- int SCsetMacro(SConnection *self, int iMode)
- {
- if(!VerifyConnection(self))
- {
- return 0;
- }
- assert( (iMode == 0) || (iMode == 1));
- self->iMacro = iMode;
-/* SCPrintf(self,eError, "SCsetMacro = %lx, %d\n", (long int)self, iMode); */
- return 1;
- }
-/*---------------------------------------------------------------------------*/
- void SCDeleteConnection(void *pData)
- {
- int i, iRet;
- char pBueffel[132];
- SConnection *pVictim = NULL;
- Item sItem;
- pHdb root = NULL;
-
- pVictim = (SConnection *)pData;
- if(!VerifyConnection(pVictim))
- {
- return;
- }
-
- if(SCActive(pVictim))
- {
- SCnoSock(pVictim);
- if(pVictim->pSock)
- {
- NETClosePort(pVictim->pSock);
- free(pVictim->pSock);
- pVictim->pSock = NULL;
- }
- WriteToCommandLog("SYS>",
- "ERROR: Erraneous deletion of used Connection stopped");
- return;
- }
-
-
- /* remove the connection from the server log if it has captured
- something
- */
- KillCapture(pVictim);
-
- /*
- * remove any callbacks which might still be active in the Hipadaba
- */
- root = GetHipadabaRoot();
- if(root != NULL)
- {
- RemoveConnectionCallbacks(root,pVictim);
- }
-
- /*
- If we have a grab, release it !
- */
- if(!pVictim->iGrab)
- {
- if(pServ->pTasker)
- {
- TaskSignal(pServ->pTasker,TOKENRELEASE,NULL);
- TokenRelease();
- }
- }
-
- /* log the kill */
- if(pVictim->pSock && pVictim->iLogin == 1 &&
- (pVictim->iUserRights < 3 || !CompactCommandLog()) )
- {
- sprintf(pBueffel,"Deleting connection %d",pVictim->pSock->sockid);
- WriteToCommandLog("SYS>",pBueffel);
- SICSLogWrite(pBueffel,eInternal);
- }
-
- /* close all open files and sockets */
- if(pVictim->pSock)
- {
- NETWrite(pVictim->pSock,"SICSCLOSE",sizeof("SICSCLOSE"));
- NETClosePort(pVictim->pSock);
- free(pVictim->pSock);
- }
- for(i = 0; i < pVictim->iFiles; i++)
- {
- if(pVictim->pFiles[i] != NULL)
- {
- fclose(pVictim->pFiles[i]);
- }
- }
-
- RemoveCommand(pServ->pSics,ConName(pVictim->ident));
-
- if(pVictim->pDes)
- {
- DeleteDescriptor(pVictim->pDes);
- }
-
- /* remove all callbacks on this connection */
- iRet = LLDnodePtr2First(pVictim->iList);
- while(iRet != 0)
- {
- LLDnodeDataTo(pVictim->iList,&sItem);
- RemoveCallback(sItem.pInterface, sItem.lID);
- iRet = LLDnodePtr2Next(pVictim->iList);
- }
- LLDdelete(pVictim->iList);
-
- /* remove command stack */
- if(pVictim->pStack)
- {
- DeleteCommandStack(pVictim->pStack);
- }
-
- /* remove possible buffers */
- if(pVictim->data != NULL)
- {
- DeleteDynString(pVictim->data);
- }
-
- pVictim->lMagic=0; /* make a write to a freed connection harmless */
- /* finally free pVictim*/
- LLDdelete(pVictim->contextStack);
- FreeConnection(pVictim);
}
-/*---------------------------------------------------------------------------*/
- static int HasNL(char *buffer)
- {
- int i;
- for(i = strlen(buffer); i > 0; i--)
- {
- if(isprint(buffer[i]))
- {
- break;
- }
- if(buffer[i] == '\n')
- {
- return 1;
- }
- }
- return 0;
- }
+ return 0;
+}
+
/*-------------------------------------------------------------------------
TelnetWrite makes sure, that all lines are properly terminated with a
as required by the telnet protocoll.
There may be a problem here at long messages. 7.5.1998 MK
---------------------------------------------------------------------------*/
+--------------------------------------------------------------------------*/
#define TXT 0
#define LF 1
- int TelnetWrite(mkChannel *pSock, char *pBuffer)
- {
- char *pStart = NULL, *pPtr;
- int iCount, iState;
- int iRet = 1;
-
- pStart = pBuffer;
- pPtr = pStart;
- iState = TXT;
- iCount = 0;
- while(*pPtr != '\0')
- {
- switch(iState)
- {
- case TXT:
- if( (*pPtr == '\r') || (*pPtr == '\n') )
- {
- iState = LF;
- iRet = NETWrite(pSock,pStart,iCount);
- iRet = NETWrite(pSock,"\r\n",2);
- iCount = 0;
- }
- else
- {
- iCount++;
- }
- break;
- case LF:
- if( (*pPtr != '\r') && (*pPtr != '\n') )
- {
- pStart = pPtr;
- iCount = 1;
- iState = TXT;
- }
- else
- {
- /* do nothing */
- }
- break;
- }
- pPtr++;
- }
- if(iCount > 0)
- {
- iRet = NETWrite(pSock,pStart,iCount);
- iRet = NETWrite(pSock,"\r\n",2);
- }
- return iRet;
- }
-/*-------------------------------------------------------------------------*/
- int SCWrite(SConnection *self, char *pBuffer, int iOut)
- {
- if(!VerifyConnection(self))
- {
- return 0;
+int TelnetWrite(mkChannel * pSock, char *pBuffer)
+{
+ char *pStart = NULL, *pPtr;
+ int iCount, iState;
+ int iRet = 1;
+
+ pStart = pBuffer;
+ pPtr = pStart;
+ iState = TXT;
+ iCount = 0;
+ while (*pPtr != '\0') {
+ switch (iState) {
+ case TXT:
+ if ((*pPtr == '\r') || (*pPtr == '\n')) {
+ iState = LF;
+ iRet = NETWrite(pSock, pStart, iCount);
+ iRet = NETWrite(pSock, "\r\n", 2);
+ iCount = 0;
+ } else {
+ iCount++;
}
- /*
- Do not die if no data
- */
- if(pBuffer == NULL)
- {
- return 0;
+ break;
+ case LF:
+ if ((*pPtr != '\r') && (*pPtr != '\n')) {
+ pStart = pPtr;
+ iCount = 1;
+ iState = TXT;
+ } else {
+ /* do nothing */
}
- return self->write(self,pBuffer,iOut);
+ break;
+ }
+ pPtr++;
}
+ if (iCount > 0) {
+ iRet = NETWrite(pSock, pStart, iCount);
+ iRet = NETWrite(pSock, "\r\n", 2);
+ }
+ return iRet;
+}
+
+/*-----------------------------------------------------------*/
+int TelnetWriteANET(int sockHandle, char *pBuffer)
+{
+ char *pStart = NULL, *pPtr;
+ int iCount, iState;
+ int iRet = 1;
+
+ pStart = pBuffer;
+ pPtr = pStart;
+ iState = TXT;
+ iCount = 0;
+ while (*pPtr != '\0') {
+ switch (iState) {
+ case TXT:
+ if ((*pPtr == '\r') || (*pPtr == '\n')) {
+ iState = LF;
+ iRet = ANETwrite(sockHandle, pStart, iCount);
+ iRet = ANETwrite(sockHandle, "\r\n", 2);
+ iCount = 0;
+ } else {
+ iCount++;
+ }
+ break;
+ case LF:
+ if ((*pPtr != '\r') && (*pPtr != '\n')) {
+ pStart = pPtr;
+ iCount = 1;
+ iState = TXT;
+ } else {
+ /* do nothing */
+ }
+ break;
+ }
+ pPtr++;
+ }
+ if (iCount > 0) {
+ iRet = ANETwrite(sockHandle, pStart, iCount);
+ iRet = ANETwrite(sockHandle, "\r\n", 2);
+ }
+ return iRet;
+}
+
+/*-------------------------------------------------------------------------*/
+int SCWrite(SConnection * self, char *pBuffer, int iOut)
+{
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+ /*
+ Do not die if no data
+ */
+ if (pBuffer == NULL) {
+ return 0;
+ }
+ if(!SCinMacro(self)){
+ traceCommand(ConID(self),"out:%s", pBuffer);
+ }
+ return self->write(self, pBuffer, iOut);
+}
+
/*-----------------------------------------------------------------------*/
-int SCWriteInContext(SConnection *pCon, char *pBuffer, int out, commandContext cc)
+int SCWriteInContext(SConnection * pCon, char *pBuffer, int out,
+ commandContext cc)
{
- int status;
- SCPushContext2(pCon,cc);
- status = SCWrite(pCon,pBuffer,out);
- SCPopContext(pCon);
- return status;
+ int status;
+ int transID;
+ char oldDevice[256];
+
+ transID = pCon->transID;
+ strcpy(oldDevice, pCon->deviceID);
+ pCon->transID = cc.transID;
+ strlcpy(pCon->deviceID, cc.deviceID, SCDEVIDLEN);
+ status = SCWrite(pCon, pBuffer, out);
+ pCon->transID = transID;
+ strlcpy(pCon->deviceID, oldDevice, SCDEVIDLEN);
+ return status;
}
+
/*-------------------------------------------------------------------------*/
- int SCPrintf(SConnection *self, int iOut, char *fmt, ...)
- {
- va_list ap;
- char buf[256];
- char *dyn;
- unsigned int l;
- int res;
-
+int SCPrintf(SConnection * self, int iOut, char *fmt, ...)
+{
+ va_list ap;
+ char buf[256];
+ char *dyn;
+ int l;
+ int res;
+
+ va_start(ap, fmt);
+ l = vsnprintf(buf, sizeof buf, fmt, ap);
+ va_end(ap);
+ if (l >= sizeof buf) {
+ /* we have probably a C99 conforming snprintf and
+ need a larger buffer
+ */
+ dyn = malloc(l + 1);
+ if (dyn != NULL) {
va_start(ap, fmt);
- l = vsnprintf(buf, sizeof buf, fmt, ap);
+ vsnprintf(dyn, l + 1, fmt, ap);
va_end(ap);
- if (l >= sizeof buf) {
- /* 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);
- res = SCWrite(self, dyn, iOut);
- free(dyn);
- return res;
- }
- }
- return SCWrite(self, buf, iOut);
+ res = SCWrite(self, dyn, iOut);
+ free(dyn);
+ return res;
+ }
}
-/*-------------------------------------------------------------------------*/
-writeFunc SCGetWriteFunc(SConnection *self)
-{
- if(!VerifyConnection(self))
- {
- return 0;
- }
- return self->write;
+ return SCWrite(self, buf, iOut);
}
+
/*-------------------------------------------------------------------------*/
-void SCSetWriteFunc(SConnection *self, writeFunc x)
+writeFunc SCGetWriteFunc(SConnection * self)
{
- if(!VerifyConnection(self))
- {
- return;
- }
- self->write = x;
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+ return self->write;
}
+
+/*-------------------------------------------------------------------------*/
+void SCSetWriteFunc(SConnection * self, writeFunc x)
+{
+ if (!VerifyConnection(self)) {
+ return;
+ }
+ self->write = x;
+}
+
/*------------------------------------------------------------------------*/
-static int doSockWrite(SConnection *self, char *buffer)
+static int doSockWrite(SConnection * self, char *buffer)
{
int iRet = 1;
- if(self->pSock)
- {
- if(self->iTelnet)
- {
- iRet = TelnetWrite(self->pSock,buffer);
- }
- else
- {
- iRet = NETWrite(self->pSock,buffer,strlen(buffer));
- if(!HasNL(buffer))
- {
- iRet = NETWrite(self->pSock,"\n",strlen("\n"));
- }
- }
- if(!iRet)
- {
- SCnoSock(self);
- if(!self->listening && self->iLogin == 1 &&
- (self->iUserRights < 3 || !CompactCommandLog()) )
- {
- WriteToCommandLog("SYS>","Connection broken on send");
+ if (self->sockHandle >= 0) {
+ if (self->iTelnet) {
+ iRet = TelnetWriteANET(self->sockHandle, buffer);
+ } else {
+ iRet = ANETwrite(self->sockHandle, buffer, strlen(buffer));
+ if (!HasNL(buffer)) {
+ iRet = ANETwrite(self->sockHandle, "\n", strlen("\n"));
}
}
- }
- else
- {
+ if (!iRet) {
+ SCnoSock(self);
+ if (!self->listening && self->iLogin == 1 &&
+ (self->iUserRights < 3 || !CompactCommandLog())) {
+ WriteToCommandLog("SYS>", "Connection broken on send");
+ }
+ }
+ } else {
if (HasNL(buffer)) {
fputs(buffer, stdout);
} else {
@@ -668,957 +693,969 @@ static int doSockWrite(SConnection *self, char *buffer)
}
return iRet;
}
-/*-------------------------------------------------------------------------*/
-static void writeToLogFiles(SConnection *self, char *buffer)
+
+/*--------------------------------------------------------------------------*/
+static void testAndWriteCommandLog(SConnection * pCon, char *buffer,
+ int iOut)
{
- int i;
- for(i = 0; i < self->iFiles; i++)
- {
- if(self->pFiles[i])
- {
- fputs(buffer,self->pFiles[i]);
- if(! HasNL(buffer))
- {
- fputs("\n",self->pFiles[i]);
- fflush(self->pFiles[i]);
+ if (SCGetRights(pCon) <= usUser) {
+ if (SCinMacro(pCon) != 1) {
+ sendingConnection = pCon->sockHandle;
+ WriteToCommandLogId(NULL, pCon->sockHandle, buffer);
+ sendingConnection = 0;
+ } else {
+ if (iOut == eLog || iOut == eLogError) {
+ sendingConnection = pCon->sockHandle;
+ WriteToCommandLogId(NULL, pCon->sockHandle, buffer);
+ sendingConnection = 0;
}
- }
+ }
}
}
+
/*--------------------------------------------------------------------------*/
- int SCNormalWrite(SConnection *self, char *buffer, int iOut)
- {
- int i, iPtr, iRet;
- char pBueffel[80];
-
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
- return 1; /* do not write empty line */
- }
-
- /* log it for any case */
- if(self->pSock)
- {
- iRet = self->pSock->sockid;
- }
- else
- {
- iRet = 0;
- }
- if (/*iRet == 0 &&*/
- iOut == eInternal || (buffer[0] == 'O' && buffer[1] == 'K' &&
- (buffer[2] == '\0' || buffer[2] == '\r' || buffer[2] == '\n'))) {
- /* supress */ iRet = 0;
- }
- else {
- if (self->iMacro != 1) {
- sprintf(pBueffel,"Next line intended for socket(1): %d",iRet);
- SICSLogWrite(pBueffel,eInternal);
- SICSLogWrite(buffer,iOut);
- }
- }
-
- /* write to commandlog if user or manager privilege */
- if(SCGetRights(self) <= usUser)
- {
- if(self->iMacro != 1)
- {
- sendingConnection = self;
- WriteToCommandLogId(NULL,iRet,buffer);
- sendingConnection = NULL;
- }
- else
- {
- if(iOut == eError || iOut == eWarning)
- {
- sendingConnection = self;
- WriteToCommandLogId(NULL,iRet,buffer);
- sendingConnection = NULL;
- }
- }
- }
-
- /* put it into the interpreter if present */
- if(SCinMacro(self))
- {
- InterpWrite(pServ->pSics,buffer);
- /* print it to client if error message */
- if((iOut== eError) || (iOut == eWarning) )
- {
- iRet = doSockWrite(self,buffer);
- }
- }
- else /* not in interpreter, normal logic */
- {
- /* is this really to be printed ? */
- if(iOut < self->iOutput)
- return 0;
-
- /* first the socket */
- iRet = doSockWrite(self,buffer);
-
- writeToLogFiles(self,buffer);
- }
- return 1;
- }
-/*--------------------------------------------------------------------------*/
- int SCACTWrite(SConnection *self, char *buffer, int iOut)
- {
- int i, iPtr, iRet;
- char pBueffel[1024];
- char *pPtr = pBueffel;
- commandContext cx;
-
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
- return 1; /* do not write empty line */
- }
-
- /* log it for any case */
- if(self->pSock)
- {
- iRet = self->pSock->sockid;
- }
- else
- {
- iRet = 0;
- }
- sprintf(pBueffel,"Next line intended for socket: %d",iRet);
- SICSLogWrite(pBueffel,eInternal);
- SICSLogWrite(buffer,iOut);
-
- /* write to commandlog if user or manager privilege */
- if(SCGetRights(self) <= usUser)
- {
- if(self->iMacro != 1)
- {
- sendingConnection = self;
- WriteToCommandLogId(NULL,iRet,buffer);
- sendingConnection = NULL;
- }
- else
- {
- if(iOut == eError || iOut == eWarning)
- {
- sendingConnection = self;
- WriteToCommandLogId(NULL,iRet,buffer);
- sendingConnection = NULL;
- }
- }
- }
-
- /*
- * copy in ACT
- */
- if(strlen(buffer) + 30 > 1024){
- pPtr = (char *)malloc((strlen(buffer)+30)*sizeof(char));
- memset(pPtr,0,strlen(buffer)+20);
- }
- cx = SCGetContext(self);
- sprintf(pPtr,"%d::>%s<::", cx.transID, buffer);
-
- /* put it into the interpreter if present */
- if(SCinMacro(self))
- {
- InterpWrite(pServ->pSics,buffer);
- /* print it to client if error message */
- if((iOut== eError) || (iOut == eWarning) )
- {
- iRet = doSockWrite(self,pPtr);
- }
- }
- else /* not in interpreter, normal logic */
- {
- /* is this really to be printed ? */
- if(iOut < self->iOutput)
- return 0;
-
- /* first the socket */
- iRet = doSockWrite(self,pPtr);
-
- writeToLogFiles(self,buffer);
- }
- if(pPtr != pBueffel){
- free(pPtr);
- }
- return 1;
- }
-/*--------------------------------------------------------------------------*/
- int SCWriteWithOutcode(SConnection *self, char *buffer, int iOut)
- {
- int i, iPtr, iRet, length;
- char pBueffel[80];
- char *bufPtr = NULL;
-
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
- return 1; /* do not write empty line */
- }
-
- /* log it for any case */
- if(self->pSock)
- {
- iRet = self->pSock->sockid;
- }
- else
- {
- iRet = 0;
- }
- sprintf(pBueffel,"Next line intended for socket(2): %d",iRet);
- SICSLogWrite(pBueffel,eInternal);
- SICSLogWrite(buffer,iOut);
-
- /* write to commandlog if user or manager privilege */
- if(SCGetRights(self) <= usUser && self->iMacro != 1)
- {
- sendingConnection = self;
- WriteToCommandLogId(NULL,iRet,buffer);
- sendingConnection = NULL;
- }
-
- /*
- prepare the message with the outcode appended.
- */
- length = strlen(buffer) + strlen(pCode[iOut]) + 10;
- bufPtr = (char *)malloc(length * sizeof(char));
- if(!bufPtr)
- {
- SICSLogWrite("SYS>>ERROR: out of memory in SCWriteWithOutcode",eError);
- return 0;
- }
- memset(bufPtr,0,length*sizeof(char));
- strcpy(bufPtr,buffer);
- i = strlen(bufPtr);
- while(i-- > 0)
- {
- if(!isspace(bufPtr[i]))
- break;
- }
- i++;
- bufPtr[i] = '\0';
- strcat(bufPtr,"@@");
- strcat(bufPtr,pCode[iOut]);
- strcat(bufPtr,"\r\n");
-
-
- /* put it into the interpreter if present */
- if(SCinMacro(self))
- {
- InterpWrite(pServ->pSics,buffer);
- /* print it to client if error message */
- if((iOut== eError) || (iOut == eWarning) )
- {
- iRet = doSockWrite(self,bufPtr);
- }
- }
- else /* not in interpreter, normal logic */
- {
- /* is this really to be printed ? */
- if(iOut < self->iOutput)
- {
- free(bufPtr);
- return 0;
- }
-
- /* first the socket */
- iRet = doSockWrite(self,bufPtr);
-
- writeToLogFiles(self,buffer);
- }
- free(bufPtr);
- return 1;
- }
-/*-------------------------------------------------------------------------*/
-static int SCBufferWrite(SConnection *self, char *buffer, int iOut)
+static void testAndStoreInTcl(SConnection * pCon, char *buffer, int iOut)
{
- if(!VerifyConnection(self))
- {
- return 0;
+ if (SCinMacro(pCon)) {
+ if (iOut == eValue || iOut == eError) {
+ InterpWrite(pServ->pSics, buffer);
}
- assert(self->data != NULL);
- DynStringConcat(self->data,buffer);
- if(strchr(buffer,'\n') == NULL){
- DynStringConcat(self->data,"\n");
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+static int testAndWriteSocket(SConnection * pCon, char *buffer, int iOut)
+{
+ switch (iOut) {
+ case eStatus:
+ case eStart:
+ case eFinish:
+ case eEvent:
+ case eHdbValue:
+ case eHdbEvent:
+ case eLog:
+ case eLogError:
+ return doSockWrite(pCon, buffer);
+ break;
+ case eValue:
+ case eError:
+ case eWarning:
+ if (!SCinMacro(pCon) && iOut >= pCon->iOutput) {
+ return doSockWrite(pCon, buffer);
+ } else {
+ return 0;
}
- return 1;
+ break;
+ }
+ printf("Unrecognized ouput code %d in testAndWriteSocket: FIX!!!\n", iOut);
+ return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+int SCNormalWrite(SConnection * self, char *buffer, int iOut)
+{
+ int i, iPtr, iRet;
+
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
+ return 1; /* do not write empty line */
+ }
+
+ /* log it for any case */
+ SICSLogWrite(buffer, iOut);
+
+ testAndWriteCommandLog(self, buffer, iOut);
+
+ testAndStoreInTcl(self, buffer, iOut);
+
+ testAndWriteSocket(self, buffer, iOut);
+
+ return 1;
+}
+/*--------------------------------------------------------------------------*/
+int SCAllWrite(SConnection * self, char *buffer, int iOut)
+{
+ int i, iPtr, iRet;
+
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
+ return 1; /* do not write empty line */
+ }
+
+ /* log it for any case */
+ SICSLogWrite(buffer, iOut);
+
+ testAndWriteCommandLog(self, buffer, iOut);
+
+ testAndStoreInTcl(self, buffer, iOut);
+
+ doSockWrite(self, buffer);
+
+ return 1;
+}
+/*--------------------------------------------------------------------------*/
+int SCACTWrite(SConnection * self, char *buffer, int iOut)
+{
+ int i, iPtr, iRet;
+ char pBueffel[1024];
+ char *pPtr = pBueffel;
+ commandContext cx;
+
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
+ return 1; /* do not write empty line */
+ }
+
+ /* log it for any case */
+ sprintf(pBueffel, "Next line intended for socket: %d", self->sockHandle);
+ SICSLogWrite(buffer, iOut);
+
+ testAndWriteCommandLog(self, buffer, iOut);
+
+ testAndStoreInTcl(self, buffer, iOut);
+
+ /*
+ * copy in ACT
+ */
+ if (strlen(buffer) + 30 > 1024) {
+ pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char));
+ memset(pPtr, 0, strlen(buffer) + 20);
+ }
+ sprintf(pPtr, "%d::>%s<::", self->transID, buffer);
+
+ testAndWriteSocket(self, pPtr, iOut);
+
+ if (pPtr != pBueffel) {
+ free(pPtr);
+ }
+ return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+int SCWriteWithOutcode(SConnection * self, char *buffer, int iOut)
+{
+ int i, iPtr, iRet, length;
+ char pBueffel[80];
+ char *bufPtr = NULL;
+
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
+ return 1; /* do not write empty line */
+ }
+
+ /* log it for any case */
+ sprintf(pBueffel, "Next line intended for socket: %d", self->sockHandle);
+ SICSLogWrite(pBueffel, eInternal);
+ SICSLogWrite(buffer, iOut);
+
+ testAndWriteCommandLog(self, buffer, iOut);
+
+ testAndStoreInTcl(self, buffer, iOut);
+ /*
+ prepare the message with the outcode appended.
+ */
+ length = strlen(buffer) + strlen(pCode[iOut]) + 10;
+ bufPtr = (char *) malloc(length * sizeof(char));
+ if (!bufPtr) {
+ SICSLogWrite("SYS>>ERROR: out of memory in SCWriteWithOutcode",
+ eError);
+ return 0;
+ }
+ memset(bufPtr, 0, length * sizeof(char));
+ strcpy(bufPtr, buffer);
+ i = strlen(bufPtr);
+ while (i-- > 0) {
+ if (!isspace(bufPtr[i]))
+ break;
+ }
+ i++;
+ bufPtr[i] = '\0';
+ strcat(bufPtr, "@@");
+ strcat(bufPtr, pCode[iOut]);
+ strcat(bufPtr, "\r\n");
+
+ testAndWriteSocket(self, bufPtr, iOut);
+
+ free(bufPtr);
+ return 1;
}
/*-------------------------------------------------------------------------*/
-int SCStartBuffering(SConnection *pCon)
+static int SCBufferWrite(SConnection * self, char *buffer, int iOut)
{
- if(!VerifyConnection(pCon))
- {
- return 0;
- }
- if(pCon->data != NULL)
- {
- DeleteDynString(pCon->data);
- }
- pCon->data = CreateDynString(128,128);
- if(pCon->data == NULL)
- {
- return 0;
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+ assert(self->data != NULL);
+ DynStringConcat(self->data, buffer);
+ if (strchr(buffer, '\n') == NULL) {
+ DynStringConcat(self->data, "\n");
+ }
+ testAndStoreInTcl(self, buffer, iOut);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+int SCStartBuffering(SConnection * pCon)
+{
+ if (!VerifyConnection(pCon)) {
+ return 0;
+ }
+ if (pCon->data != NULL && pCon->dataOwner == 1) {
+ DeleteDynString(pCon->data);
+ }
+ pCon->data = CreateDynString(128, 128);
+ if (pCon->data == NULL) {
+ return 0;
+ }
+ pCon->oldWriteFunc = pCon->write;
+ pCon->write = SCBufferWrite;
+ pCon->dataOwner = 1;
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+pDynString SCEndBuffering(SConnection * pCon)
+{
+ if (!VerifyConnection(pCon)) {
+ return 0;
+ }
+ assert(pCon->oldWriteFunc != NULL);
+ pCon->write = pCon->oldWriteFunc;
+ pCon->oldWriteFunc = NULL;
+ return pCon->data;
+}
+
+/*--------------------------------------------------------------------------*/
+int SCOnlySockWrite(SConnection * self, char *buffer, int iOut)
+{
+ int i, iPtr, iRet;
+ char pBueffel[80];
+
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ /* log it for any case */
+ sprintf(pBueffel, "Next line intended for socket: %d", self->sockHandle);
+ SICSLogWrite(pBueffel, eInternal);
+ SICSLogWrite(buffer, iOut);
+
+ testAndStoreInTcl(self, buffer, iOut);
+
+ testAndWriteSocket(self, buffer, iOut);
+
+ return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+int SCPureSockWrite(SConnection * self, char *buffer, int iOut)
+{
+ char pBueffel[1024];
+ char *pPtr;
+
+ /* for commandlog tail */
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ if(self->iProtocolID == 5) {
+ if (strlen(buffer) + 30 > 1024) {
+ pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char));
+ memset(pPtr, 0, strlen(buffer) + 20);
+ } else {
+ pPtr = pBueffel;
}
- pCon->oldWriteFunc = pCon->write;
- pCon->write = SCBufferWrite;
- return 1;
-}
-/*-------------------------------------------------------------------------*/
-pDynString SCEndBuffering(SConnection *pCon)
-{
- if(!VerifyConnection(pCon))
- {
- return 0;
+ sprintf(pPtr, "%d::>%s<::", self->transID, buffer);
+ testAndWriteSocket(self, pPtr, iOut);
+ if(pPtr != pBueffel){
+ free(pPtr);
}
- assert(pCon->oldWriteFunc != NULL);
- pCon->write = pCon->oldWriteFunc;
- pCon->oldWriteFunc = NULL;
- return pCon->data;
+ } else {
+ testAndWriteSocket(self, buffer, iOut);
+ }
+
+ return 1;
}
-/*--------------------------------------------------------------------------*/
- int SCOnlySockWrite(SConnection *self, char *buffer, int iOut)
- {
- int i, iPtr, iRet;
- char pBueffel[80];
- if(!VerifyConnection(self))
- {
- return 0;
- }
+/*--------------------------------------------------------------------------
+ special for ClientLog. Do not use elsewhere without check
+ ----------------------------------------------------------------------------*/
+int SCLogWrite(SConnection * self, char *buffer, int iOut)
+{
+ char pBueffel[1024];
+ char *pPtr;
- /* log it for any case */
- if(self->pSock)
- {
- iRet = self->pSock->sockid;
- }
- else
- {
- iRet = 0;
- }
- sprintf(pBueffel,"Next line intended for socket(3): %d",iRet);
- SICSLogWrite(pBueffel,eInternal);
- SICSLogWrite(buffer,iOut);
-
- /* put it into the interpreter if present */
- if(SCinMacro(self))
- {
- InterpWrite(pServ->pSics,buffer);
- }
- else /* not in interpreter, normal logic */
- {
- /* is this really to be printed ? */
- if(iOut < self->iOutput)
- return 0;
-
- /* the socket */
- iRet = doSockWrite(self,buffer);
- }
- return 1;
+ if (!VerifyConnection(self)) {
+ return 0;
}
-/*--------------------------------------------------------------------------*/
- int SCNotWrite(SConnection *self, char *buffer, int iOut)
- {
- int i, iPtr, iRet;
- char pBueffel[80];
+ WriteToCommandLogId(NULL, self->sockHandle, buffer);
- if(!VerifyConnection(self))
- {
- return 0;
- }
- if (strcmp(buffer, "OK") == 0)
- return 1;
-
- /* log it for any case */
- if(self->pSock)
- {
- iRet = self->pSock->sockid;
- }
- else
- {
- iRet = 0;
- }
- sprintf(pBueffel,"Next line intended for socket(4): %d",iRet);
- SICSLogWrite(pBueffel,eInternal);
- SICSLogWrite(buffer,iOut);
-
- /* put it into the interpreter if present */
- if(SCinMacro(self))
- {
- InterpWrite(pServ->pSics,buffer);
- }
- return 1;
+ if(self->iProtocolID == 5) {
+ if (strlen(buffer) + 30 > 1024) {
+ pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char));
+ memset(pPtr, 0, strlen(buffer) + 20);
+ } else {
+ pPtr = pBueffel;
+ }
+ sprintf(pPtr, "%d::>%s<::", self->transID, buffer);
+ testAndWriteSocket(self, pPtr, iOut);
+ if(pPtr != pBueffel){
+ free(pPtr);
+ }
+ } else {
+ testAndWriteSocket(self, buffer, iOut);
}
+
+ return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+int SCNotWrite(SConnection * self, char *buffer, int iOut)
+{
+ int i, iPtr, iRet;
+ char pBueffel[80];
+
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ /* log it for any case
+ sprintf(pBueffel, "Next line intended for socket: %d", self->sockHandle);
+ SICSLogWrite(pBueffel, eInternal);
+ SICSLogWrite(buffer, iOut);
+ */
+
+ testAndStoreInTcl(self, buffer, iOut);
+ return 1;
+}
+
/*--------------------------------------------------------------------------
This version writes only to configured log files but not to sockets.
Used for automatic file execution for the WWW interface
*/
- int SCFileWrite(SConnection *self, char *buffer, int iOut)
- {
- int i, iPtr, iRet;
- char pBueffel[80];
+int SCFileWrite(SConnection * self, char *buffer, int iOut)
+{
+ int i, iPtr, iRet;
+ char pBueffel[80];
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- /* log it for any case */
- if(self->pSock)
- {
- iRet = self->pSock->sockid;
- }
- else
- {
- iRet = -10;
- }
-
- /* put into Serverlog */
- sprintf(pBueffel,"Next line intended for socket: %d",iRet);
- SICSLogWrite(pBueffel,eInternal);
-
- SICSLogWrite(buffer,iOut);
-
- /* write to commandlog if user or manager privilege */
- if(SCGetRights(self) <= usUser)
- {
- if(self->iMacro != 1)
- {
- sendingConnection = self;
- WriteToCommandLogId(NULL,iRet,buffer);
- sendingConnection = NULL;
- }
- else
- {
- if(iOut == eError || iOut == eWarning)
- {
- sendingConnection = self;
- WriteToCommandLogId(NULL,iRet,buffer);
- sendingConnection = NULL;
- }
- }
- }
-
- /* put it into the interpreter if present */
- if(SCinMacro(self))
- {
- InterpWrite(pServ->pSics,buffer);
- }
- else /* not in interpreter, normal logic */
- {
- /* is this really to be printed ? */
- if(iOut < self->iOutput)
- return 0;
-
- writeToLogFiles(self,buffer);
- }
- return 1;
+ if (!VerifyConnection(self)) {
+ return 0;
}
+
+ /* log it for any case */
+ sprintf(pBueffel, "Next line intended for socket: %d", self->sockHandle);
+ SICSLogWrite(pBueffel, eInternal);
+
+ SICSLogWrite(buffer, iOut);
+
+ testAndWriteCommandLog(self, buffer, iOut);
+
+ testAndStoreInTcl(self, buffer, iOut);
+
+ testAndWriteSocket(self, buffer, iOut);
+
+ return 1;
+}
+
/*-----------------------------------------------------------------------*/
- int SCnoSock(SConnection *self)
- {
- if(!VerifyConnection(self))
- {
- return 0;
- }
- self->write = SCFileWrite;
- return 0;
+int SCnoSock(SConnection * self)
+{
+ if (!VerifyConnection(self)) {
+ return 0;
}
-/*------------------------------------------------------------------------*/
- int SCWriteUUencoded(SConnection *pCon, char *pName, void *pData,
- int iDataLen)
- {
- void *pPtr = NULL;
- int iLength = 0;
- int iRet = 1;
- FILE *fd;
- char *pTest;
-
- iRet = UUencodeBuffer(pData,iDataLen,pName, &pPtr, &iLength);
- if(iRet != 1)
- {
- SCWrite(pCon,"ERROR: no memory for uuencoder",eError);
- return 0;
- }
- pTest = (char *)pPtr;
+ self->write = SCFileWrite;
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+int SCWriteUUencoded(SConnection * pCon, char *pName, void *pData,
+ int iDataLen)
+{
+ void *pPtr = NULL;
+ int iLength = 0;
+ int iRet = 1;
+ FILE *fd;
+ char *pTest;
+
+ iRet = UUencodeBuffer(pData, iDataLen, pName, &pPtr, &iLength);
+ if (iRet != 1) {
+ SCWrite(pCon, "ERROR: no memory for uuencoder", eError);
+ return 0;
+ }
+ pTest = (char *) pPtr;
+
+ /* the uuencoder ensures proper telnet */
+ if (pCon->iTelnet) {
+ ANETwrite(pCon->sockHandle, pPtr, iLength);
+ } else {
+ ANETwrite(pCon->sockHandle, pPtr, iLength);
+ }
+
+ traceCommand(ConID(pCon),"out:UUData %s %d", pName, iLength);
+
- /* the uuencoder ensures proper telnet */
- if(pCon->iTelnet)
- {
- NETWrite(pCon->pSock,pPtr,iLength);
- }
- else
- {
- NETWrite(pCon->pSock,pPtr,iLength);
- }
-
#ifdef UUDEB
- fd = fopen("uubuffer.uu","w");
- fputs(pPtr,fd);
- fclose(fd);
-#endif
-
- free(pPtr);
- return iRet;
- }
+ fd = fopen("uubuffer.uu", "w");
+ fputs(pPtr, fd);
+ fclose(fd);
+#endif
+
+ free(pPtr);
+ return iRet;
+}
+
/*------------------------------------------------------------------------*/
#define ZIPBUF 8192
- int SCWriteZipped(SConnection *self, char *pName, void *pData, int iDataLen)
- {
- char outBuf[65546], *pBuf = NULL, noutBuf[ZIPBUF], *pHeader = NULL;
- int compressedLength, iRet, iRet2, iCount, protocolID;
- z_stream compStream;
- commandContext cc;
-
- /* check for a valid connection */
- if(!VerifyConnection(self))
- {
- return 0;
- }
+int SCWriteZipped(SConnection * self, char *pName, void *pData,
+ int iDataLen)
+{
+ char outBuf[65536], *pBuf = NULL, noutBuf[ZIPBUF], *pHeader = NULL;
+ int compressedLength, iRet, iRet2, iCount, protocolID;
+ z_stream compStream;
+ commandContext cc;
- /* a telnet connection will corrupt the compressed stream, so
- stop it!
- */
- if(self->iTelnet)
- {
- SCWrite(self,
- "ERROR: the telnet protocoll will currupt compressed data!",
- eError);
- return 0;
- }
-
- /*
- do nothing if no data
- */
- if(pName == NULL || pData == NULL)
- {
- SCWrite(self,"ERROR: no data to write in SCWriteZiped",eError);
- return 0;
- }
-
- /* initialize the compression stuff */
- compStream.zalloc = (alloc_func)NULL;
- compStream.zfree = (free_func)NULL;
- compStream.opaque = (voidpf)NULL;
-
- iRet = deflateInit(&compStream,Z_DEFAULT_COMPRESSION);
- if(iRet != Z_OK)
- {
- sprintf(outBuf,"ERROR: zlib error: %d",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
-
- /* first pass: find out how the long the compressed buffer will be */
- compressedLength = 0;
- compStream.next_in = (Bytef *)pData;
- compStream.next_out = (Bytef *)outBuf;
- compStream.avail_in = iDataLen;
- compStream.avail_out = 65536;
- while(compStream.total_in < (unsigned) iDataLen)
- {
- iRet = deflate(&compStream,Z_NO_FLUSH);
- if(iRet != Z_OK)
- {
- sprintf(outBuf,"ERROR: zlib error: %d",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
- compStream.next_out = (Bytef *)outBuf;
- compStream.avail_out = 65536;
- }
- for(;;)
- {
- iRet = deflate(&compStream,Z_FINISH);
- if(iRet == Z_STREAM_END) break;
- if(iRet != Z_OK)
- {
- sprintf(outBuf,"ERROR: zlib error: %d",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
- }
- compressedLength = compStream.total_out;
- deflateEnd(&compStream);
-
- /* write header line */
- memset(outBuf,0,65536);
-
- protocolID = GetProtocolID(self);
- if(protocolID == 5){
- cc = SCGetContext(self);
- sprintf(outBuf,"SICSBIN ZIP %s %d %d\r\n",pName,
- compressedLength, cc.transID);
- } else {
- sprintf(outBuf,"SICSBIN ZIP %s %d \r\n",pName,compressedLength);
- }
- pHeader = strdup(outBuf);
- if(pHeader == NULL)
- {
- SCWrite(self,"ERROR: out of memory in SCWriteZipped",eError);
- return 0;
- }
-
- /* now reset the deflater and do the same with writing data */
- compStream.zalloc = (alloc_func)NULL;
- compStream.zfree = (free_func)NULL;
- compStream.opaque = (voidpf)NULL;
-
-
- /*
- This is writing everything in one go as I found that writing in
- several chunks did not ensure that all the data arrived at the
- Java side.
- */
-
- iRet = deflateInit(&compStream,Z_DEFAULT_COMPRESSION);
- if(iRet != Z_OK)
- {
- sprintf(outBuf,"ERROR: zlib error: %d",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
-
- pBuf = (char *)malloc((iDataLen + iDataLen/10 + 50)*sizeof(char));
- memset(pBuf,0,(iDataLen + iDataLen/10 + 50)*sizeof(char) );
- compStream.next_in = (Bytef *)pData;
- compStream.next_out = (Bytef *)pBuf;
- compStream.avail_in = iDataLen;
- compStream.avail_out = iDataLen + iDataLen/10 + 50;
- iRet = deflate(&compStream,Z_FINISH);
- if(iRet != Z_STREAM_END)
- {
- sprintf(outBuf,"ERROR: zlib error: %d",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
- iRet = NETWrite(self->pSock,pHeader,strlen(pHeader));
- iRet = NETWrite(self->pSock,pBuf,compStream.total_out);
- if(iRet != 1)
- {
- sprintf(outBuf,"ERROR: network error %d on zipped send",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
- deflateEnd(&compStream);
- free(pHeader);
- free(pBuf);
-
-
- /*
- Writing smaller buffers. Seems not to be working properly
- with Java.
- */
- /*
- compStream.next_in = (Bytef *)pData;
- compStream.avail_in = iDataLen;
- compStream.avail_out = ZIPBUF;
- compStream.next_out = (Bytef *)noutBuf;
- iCount = 0;
- while(compStream.total_in < iDataLen)
- {
- iRet = deflate(&compStream,Z_NO_FLUSH);
- if(iRet != Z_OK)
- {
- sprintf(outBuf,"ERROR: zlib error: %d",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
- iRet = NETWrite(self->pSock,noutBuf,ZIPBUF - compStream.avail_out);
- if(iRet != 1)
- {
- sprintf(outBuf,"ERROR: network error %d on zipped send",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
- iCount += ZIPBUF - compStream.avail_out;
- compStream.next_out = (Bytef *)noutBuf;
- compStream.avail_out = ZIPBUF;
- }
- for(;;)
- {
- iRet = deflate(&compStream,Z_FINISH);
- iRet2 = NETWrite(self->pSock,noutBuf,ZIPBUF - compStream.avail_out);
- if(iRet2 != 1)
- {
- sprintf(outBuf,"ERROR: network error %d on zipped send",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
- iCount += ZIPBUF - compStream.avail_out;
- if(iRet == Z_STREAM_END) break;
- if(iRet != Z_OK)
- {
- sprintf(outBuf,"ERROR: zlib error: %d",iRet);
- SCWrite(self,outBuf,eError);
- return 0;
- }
- compStream.next_out = (Bytef *)noutBuf;
- compStream.avail_out = ZIPBUF;
- }
- deflateEnd(&compStream);
- */
-
- return 1;
+ /* check for a valid connection */
+ if (!VerifyConnection(self)) {
+ return 0;
}
-/*-------------------------------------------------------------------------*/
- int SCSendOK(SConnection *self)
- {
- return SCWrite(self,"OK",eStatus);
- }
-/*--------------------------------------------------------------------------*/
- int SCRead(SConnection *self, char *buffer, int iLen)
- {
-
- int iRet;
- if(!VerifyConnection(self))
- {
- return 0;
+ /* a telnet connection will corrupt the compressed stream, so
+ stop it!
+ */
+ if (self->iTelnet) {
+ SCWrite(self,
+ "ERROR: the telnet protocol will corrupt compressed data!",
+ eError);
+ return 0;
+ }
+
+ /*
+ do nothing if no data
+ */
+ if (pName == NULL || pData == NULL) {
+ SCWrite(self, "ERROR: no data to write in SCWriteZiped", eError);
+ return 0;
+ }
+ pBuf = malloc(iDataLen*sizeof(char));
+ memset(pBuf,0,iDataLen*sizeof(char));
+
+ compStream.zalloc = (alloc_func) NULL;
+ compStream.zfree = (free_func) NULL;
+ compStream.opaque = (voidpf) NULL;
+/* iRet = deflateInit(&compStream, Z_DEFAULT_COMPRESSION); */
+ iRet = deflateInit(&compStream, 1);
+ if (iRet != Z_OK) {
+ sprintf(outBuf, "ERROR: zlib error: %d", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
+ }
+
+ compStream.next_in = (Bytef *) pData;
+ compStream.next_out = (Bytef *) pBuf;
+ compStream.avail_in = iDataLen;
+ compStream.avail_out = iDataLen;
+ iRet = deflate(&compStream, Z_FINISH);
+ if (iRet != Z_STREAM_END) {
+ sprintf(outBuf, "ERROR: zlib error: %d", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
+ }
+ compressedLength = compStream.total_out;
+
+
+ /* write header line */
+ memset(outBuf, 0, 65536);
+
+ protocolID = GetProtocolID(self);
+ if (protocolID == 5) {
+ cc = SCGetContext(self);
+ sprintf(outBuf, "SICSBIN ZIP %s %d %d\r\n", pName,
+ compressedLength, cc.transID);
+ } else {
+ sprintf(outBuf, "SICSBIN ZIP %s %d\r\n", pName, compressedLength);
+ }
+ pHeader = strdup(outBuf);
+ if (pHeader == NULL) {
+ SCWrite(self, "ERROR: out of memory in SCWriteZipped", eError);
+ return 0;
+ }
+ traceCommand(ConID(self),"out:SICSBIN ZIP %s %d", pName, compressedLength);
+
+
+ iRet = ANETwrite(self->sockHandle, pHeader, strlen(pHeader));
+ iRet = ANETwrite(self->sockHandle, pBuf, compStream.total_out);
+ if (iRet != 1) {
+ sprintf(outBuf, "ERROR: network error %d on zipped send", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
+ }
+ /* printf("Sent zipped data: %s with %d\n", pHeader, iRet); */
+
+ deflateEnd(&compStream);
+ free(pHeader);
+ free(pBuf);
+
+ return 1;
+}
+/*------------------------------------------------------------------*/
+int SCWriteBinary(SConnection * self, char *pName, void *pData,
+ int iDataLen)
+{
+ char outBuf[65536], *pHeader = NULL;
+ int iRet, iRet2, iCount, protocolID;
+ commandContext cc;
+
+ /* check for a valid connection */
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ /* a telnet connection will corrupt the compressed stream, so
+ stop it!
+ */
+ if (self->iTelnet) {
+ SCWrite(self,
+ "ERROR: the telnet protocol will corrupt compressed data!",
+ eError);
+ return 0;
+ }
+
+ /*
+ do nothing if no data
+ */
+ if (pName == NULL || pData == NULL) {
+ SCWrite(self, "ERROR: no data to write in SCWriteZiped", eError);
+ return 0;
+ }
+
+ /* write header line */
+ memset(outBuf, 0, 65536);
+
+ protocolID = GetProtocolID(self);
+ if (protocolID == 5) {
+ cc = SCGetContext(self);
+ sprintf(outBuf, "SICSBIN BIN %s %d %d\r\n", pName,
+ iDataLen, cc.transID);
+ } else {
+ sprintf(outBuf, "SICSBIN BIN %s %d\r\n", pName, iDataLen);
+ }
+ pHeader = strdup(outBuf);
+ if (pHeader == NULL) {
+ SCWrite(self, "ERROR: out of memory in SCWriteBinary", eError);
+ return 0;
+ }
+ traceCommand(ConID(self),"out:SICSBIN BIN %s %d", pName, iDataLen);
+
+ iRet = ANETwrite(self->sockHandle, pHeader, strlen(pHeader));
+ iRet = ANETwrite(self->sockHandle, pData, iDataLen);
+ if (iRet != 1) {
+ sprintf(outBuf, "ERROR: network error %d on zipped send", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
+ }
+ /* printf("Sent zipped data: %s with %d\n", pHeader, iRet); */
+
+ free(pHeader);
+
+ return 1;
+}
+/*--------------------------------------------------------------
+ * left in for documentation............
+ */
+int SCWriteZippedOld(SConnection * self, char *pName, void *pData,
+ int iDataLen)
+{
+ char outBuf[65546], *pBuf = NULL, noutBuf[ZIPBUF], *pHeader = NULL;
+ int compressedLength, iRet, iRet2, iCount, protocolID;
+ z_stream compStream;
+ commandContext cc;
+
+ /* check for a valid connection */
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ /* a telnet connection will corrupt the compressed stream, so
+ stop it!
+ */
+ if (self->iTelnet) {
+ SCWrite(self,
+ "ERROR: the telnet protocoll will corrupt compressed data!",
+ eError);
+ return 0;
+ }
+
+ /*
+ do nothing if no data
+ */
+ if (pName == NULL || pData == NULL) {
+ SCWrite(self, "ERROR: no data to write in SCWriteZiped", eError);
+ return 0;
+ }
+
+ /* initialize the compression stuff */
+ compStream.zalloc = (alloc_func) NULL;
+ compStream.zfree = (free_func) NULL;
+ compStream.opaque = (voidpf) NULL;
+
+ iRet = deflateInit(&compStream, Z_DEFAULT_COMPRESSION);
+ if (iRet != Z_OK) {
+ sprintf(outBuf, "ERROR: zlib error: %d", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
+ }
+
+ /* first pass: find out how the long the compressed buffer will be */
+ compressedLength = 0;
+ compStream.next_in = (Bytef *) pData;
+ compStream.next_out = (Bytef *) outBuf;
+ compStream.avail_in = iDataLen;
+ compStream.avail_out = 65536;
+ while (compStream.total_in < iDataLen) {
+ iRet = deflate(&compStream, Z_NO_FLUSH);
+ if (iRet != Z_OK) {
+ sprintf(outBuf, "ERROR: zlib error: %d", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
}
-
- if(self->pSock == NULL)
- {
- printf("SICS>> ");
- fgets(buffer,iLen-1,stdin);
+ compStream.next_out = (Bytef *) outBuf;
+ compStream.avail_out = 65536;
+ }
+ for (;;) {
+ iRet = deflate(&compStream, Z_FINISH);
+ if (iRet == Z_STREAM_END)
+ break;
+ if (iRet != Z_OK) {
+ sprintf(outBuf, "ERROR: zlib error: %d", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
+ }
+ }
+ compressedLength = compStream.total_out;
+ deflateEnd(&compStream);
+
+ /* write header line */
+ memset(outBuf, 0, 65536);
+
+ protocolID = GetProtocolID(self);
+ if (protocolID == 5) {
+ cc = SCGetContext(self);
+ sprintf(outBuf, "SICSBIN ZIP %s %d %d\r\n", pName,
+ compressedLength, cc.transID);
+ } else {
+ sprintf(outBuf, "SICSBIN ZIP %s %d \r\n", pName, compressedLength);
+ }
+ pHeader = strdup(outBuf);
+ if (pHeader == NULL) {
+ SCWrite(self, "ERROR: out of memory in SCWriteZipped", eError);
+ return 0;
+ }
+ traceCommand(ConID(self),"out:SICSBIN ZIP %s %d", pName, compressedLength);
+
+
+ /* now reset the deflater and do the same with writing data */
+ compStream.zalloc = (alloc_func) NULL;
+ compStream.zfree = (free_func) NULL;
+ compStream.opaque = (voidpf) NULL;
+
+
+ /*
+ This is writing everything in one go as I found that writing in
+ several chunks did not ensure that all the data arrived at the
+ Java side.
+ */
+
+ iRet = deflateInit(&compStream, Z_DEFAULT_COMPRESSION);
+ if (iRet != Z_OK) {
+ sprintf(outBuf, "ERROR: zlib error: %d", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
+ }
+
+ pBuf = (char *) malloc((iDataLen + iDataLen / 10 + 50) * sizeof(char));
+ memset(pBuf, 0, (iDataLen + iDataLen / 10 + 50) * sizeof(char));
+ compStream.next_in = (Bytef *) pData;
+ compStream.next_out = (Bytef *) pBuf;
+ compStream.avail_in = iDataLen;
+ compStream.avail_out = iDataLen + iDataLen / 10 + 50;
+ iRet = deflate(&compStream, Z_FINISH);
+ if (iRet != Z_STREAM_END) {
+ sprintf(outBuf, "ERROR: zlib error: %d", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
+ }
+ iRet = ANETwrite(self->sockHandle, pHeader, strlen(pHeader));
+ iRet = ANETwrite(self->sockHandle, pBuf, compStream.total_out);
+ if (iRet != 1) {
+ sprintf(outBuf, "ERROR: network error %d on zipped send", iRet);
+ SCWrite(self, outBuf, eError);
+ return 0;
+ }
+ /* printf("Sent zipped data: %s with %d\n", pHeader, iRet); */
+
+ deflateEnd(&compStream);
+ free(pHeader);
+ free(pBuf);
+
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+int SCSendOK(SConnection * self)
+{
+ return SCWrite(self, "OK", eValue);
+}
+
+/*--------------------------------------------------------------------------*/
+int SCRead(SConnection * self, char *buffer, int iLen)
+{
+
+ int iRet;
+
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ if (self->sockHandle < 0) {
+ printf("SICS>> ");
+ fgets(buffer, iLen - 1, stdin);
+ return 1;
+ }
+
+ if (self->sockHandle >= 0) {
+ iRet = ANETread(self->sockHandle, buffer, iLen);
+ if (iRet == 0) { /* no data */
+ return 0;
+ } else if (iRet < 0) { /* eof */
+ return EOF;
+ } else { /* data */
+
return 1;
}
-
- if(self->pSock)
- {
- iRet = NETRead(self->pSock,buffer,iLen,10);
- if(iRet == 0) /* no data */
- {
- return 0;
- }
- else if(iRet < 0) /* eof */
- {
- return EOF;
- }
- else /* data */
- {
- return 1;
- }
- }
- else
- {
- return EOF;
- /* fgets(buffer,iLen,stdin); */
- }
- return 1;
+ } else {
+ return EOF;
+ /* fgets(buffer,iLen,stdin); */
}
-/*----------------------------------------------------------------------------*/
- int SCMatchRights(SConnection *pCon, int iCode)
- {
- char pBueffel[132];
-
- if(!VerifyConnection(pCon))
- {
- return 0;
- }
-
- if(iCode < SCGetRights(pCon))
- {
- sprintf(pBueffel,"ERROR: you are not authorised for this operation");
- SCWrite(pCon, pBueffel, eError);
- return 0;
- }
- if(pCon->iGrab)
- {
- sprintf(pBueffel,
- "ERROR: Request refused, control has been grabbed by somebody else");
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- return 1;
- }
+ return 1;
+}
/*----------------------------------------------------------------------------*/
- int SCPrompt(SConnection *pCon, char *pPrompt, char *pResult, int iLen)
- {
-
- int iRet, i;
- char *pPtr = NULL;
- char pFrom[50];
- Status eOld;
- int oldMode;
+int SCMatchRights(SConnection * pCon, int iCode)
+{
+ char pBueffel[132];
- if(!VerifyConnection(pCon))
- {
- return 0;
- }
+ if (!VerifyConnection(pCon)) {
+ return 0;
+ }
- SCWrite(pCon,pPrompt,eWarning);
- eOld = GetStatus();
- SetStatus(eInput);
- CostaUnlock(pCon->pStack);
- while(1)
- {
- /*
- wait a second. We want to wait even in a simulation, otherwise
- we go into an endless loop. This is why there is the hack with
- oldMode and pServ->simMode.
- */
- oldMode = pServ->simMode;
- pServ->simMode = 0;
- SicsWait(1);
- pServ->simMode = oldMode;
+ if (iCode < SCGetRights(pCon)) {
+ sprintf(pBueffel, "ERROR: you are not authorised for this operation");
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ if (pCon->iGrab) {
+ sprintf(pBueffel,
+ "ERROR: Request refused, control has been grabbed by somebody else");
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ return 1;
+}
- /* is there an interrupt pending ? */
- if(SCGetInterrupt(pCon) != eContinue)
- {
- break;
- }
- /* do we have data ? */
- iRet = CostaPop(pCon->pStack,&pPtr);
- if(iRet == 1)
- {
- SetStatus(eOld);
- CostaLock(pCon->pStack);
- strncpy(pResult,pPtr,iLen);
- WriteToCommandLogId(" prompted>", pCon->pSock->sockid, pPtr);
- return 1;
- }
- }
- SetStatus(eOld);
- CostaLock(pCon->pStack);
- return 0;
- }
-/*---------------------------------------------------------------------------*/
- int SCGetRights(SConnection *self)
- {
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- return self->iUserRights;
+/*----------------------------------------------------------------------------*/
+int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen)
+{
+
+ int iRet, i;
+ char *pPtr = NULL;
+ char pFrom[50];
+ Status eOld;
+ int oldMode;
+ SConnection *master = NULL;
+
+ if (!VerifyConnection(pCon)) {
+ return 0;
}
-/*---------------------------------------------------------------------------*/
- int SCGetGrab(SConnection *self)
- {
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- return self->iGrab;
- }
-/*--------------------------------------------------------------------------*/
- int SCSetRights(SConnection *self, int iNew)
- {
- if(!VerifyConnection(self))
- {
- return 0;
- }
- assert(iNew >= usInternal);
- assert(iNew <= usSpy);
-
- self->iUserRights = iNew;
- return 1;
- }
-/*---------------------------------------------------------------------------*/
- int SCGetOutClass(SConnection *self)
- {
- if(!VerifyConnection(self))
- {
- return 0;
- }
- return self->iOutput;
- }
-/*--------------------------------------------------------------------------*/
- void SCSetInterrupt(SConnection *self, int eCode)
- {
- if(!VerifyConnection(self))
- {
- return;
- }
-
- self->eInterrupt = eCode;
- }
-/*---------------------------------------------------------------------------*/
- int SCGetInterrupt(SConnection *self)
- {
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- return self->eInterrupt;
- }
- /*----------------------------------------------------------------*/
- extern char *trim(char *in);
-/* --------------------------------------------------------------------------*/
- int SCInvoke(SConnection *self, SicsInterp *pInter, char *pCommand)
- {
- int iRet;
- long lLen;
- const char *pResult = NULL;
- char *pBuffer = NULL, *pFile = NULL;
- char pBueffel[80];
- int i, iSpace;
-
- if(!VerifyConnection(self))
- {
- return 0;
- }
- assert(pInter);
-
- /* print command to log files */
- for( i = 0; i < self->iFiles; i++)
- {
- if(self->pFiles[i])
- {
- fprintf(self->pFiles[i],"SICS>> %s\n",pCommand);
- }
- }
-
- /* print to command log if user or manager */
- if(SCGetRights(self) <= usUser)
- {
- /*
- * This is a fix to suppress cron messages in the success
- * case
- */
- if(SCGetWriteFunc(self) != SCNotWrite)
- {
- sendingConnection = self;
- if(self->pSock != NULL)
- {
- WriteToCommandLogCmd(self->pSock->sockid, pCommand);
- } else {
- WriteToCommandLog("CRON>>",pCommand);
- }
- sendingConnection = NULL;
- }
- }
-
- /* invoke */
- self->inUse++;
- self->eInterrupt = eContinue;
- /*
- get first word of command
+
+ SCWrite(pCon, pPrompt, eWarning);
+ master = SCfindMaster(pCon);
+ eOld = GetStatus();
+ SetStatus(eInput);
+ CostaUnlock(master->pStack);
+ while (1) {
+ /*
+ wait a second. We want to wait even in a simulation, otherwise
+ we go into an endless loop. This is why there is the hack with
+ oldMode and pServ->simMode.
*/
- memset(pBueffel,0,80);
- stptok(trim(pCommand),pBueffel,79," ");
- SCAdvanceContext(self,pBueffel);
- iRet = InterpExecute(pInter,self,pCommand);
- SCPopContext(self);
- StatusFileTask(NULL); /* save changed parameters */
+ oldMode = pServ->simMode;
+ pServ->simMode = 0;
+ SicsWait(1);
+ pServ->simMode = oldMode;
- self->inUse--;
- return iRet;
+ /* is there an interrupt pending ? */
+ if (SCGetInterrupt(pCon) != eContinue) {
+ break;
+ }
+ /* do we have data ? */
+ iRet = CostaPop(master->pStack, &pPtr);
+ if (iRet == 1) {
+ SetStatus(eOld);
+ CostaLock(master->pStack);
+ strlcpy(pResult, pPtr, iLen);
+ WriteToCommandLogId(" prompted>", pCon->sockHandle, pPtr);
+ return 1;
+ }
}
+ SetStatus(eOld);
+ CostaLock(master->pStack);
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+int SCGetRights(SConnection * self)
+{
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ return self->iUserRights;
+}
+
+/*---------------------------------------------------------------------------*/
+int SCGetGrab(SConnection * self)
+{
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ return self->iGrab;
+}
+
+/*--------------------------------------------------------------------------*/
+int SCSetRights(SConnection * self, int iNew)
+{
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+ assert(iNew >= usInternal);
+ assert(iNew <= usSpy);
+
+ self->iUserRights = iNew;
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+int SCGetOutClass(SConnection * self)
+{
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+ return self->iOutput;
+}
+
+/*--------------------------------------------------------------------------*/
+void SCSetInterrupt(SConnection * self, int eCode)
+{
+ SConnection *pCon = NULL;
+ if (!VerifyConnection(self)) {
+ return;
+ }
+ pCon = SCfindMaster(self);
+ pCon->eInterrupt = eCode;
+}
+
+/*---------------------------------------------------------------------------*/
+int SCGetInterrupt(SConnection * self)
+{
+ SConnection *pCon = NULL;
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+ pCon = SCfindMaster(self);
+ return pCon->eInterrupt;
+}
+
+ /*----------------------------------------------------------------*/
+extern char *trim(char *in);
+/* --------------------------------------------------------------------------*/
+int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand)
+{
+ int iRet;
+ long lLen;
+ const char *pResult = NULL;
+ char *pBuffer = NULL, *pFile = NULL;
+ char pBueffel[80];
+ int i, iSpace;
+ SConnection *pCopy = NULL;
+
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+ assert(pInter);
+
+
+ /* print to command log if user or manager */
+ if (SCGetRights(self) <= usUser) {
+ /*
+ * This is a fix to suppress cron messages in the success
+ * case
+ */
+ if (SCGetWriteFunc(self) != SCNotWrite) {
+ sendingConnection = self->sockHandle;
+ if (self->sockHandle >= 0) {
+ if(strstr(pCommand,"Poch") == NULL){
+ WriteToCommandLogCmd(self->sockHandle, pCommand);
+ }
+ } else {
+ WriteToCommandLog("CRON>>", pCommand);
+ }
+ sendingConnection = 0;
+ }
+ }
+
+ /* invoke */
+ self->inUse++;
+ self->eInterrupt = eContinue;
+ /*
+ get first word of command
+ */
+ memset(pBueffel, 0, 80);
+ stptok(trim(pCommand), pBueffel, 79, " ");
+ self->iCmdCtr++;
+ if (999999 < self->iCmdCtr) {
+ self->iCmdCtr = 0;
+ }
+ self->transID = self->iCmdCtr;
+ pCopy = SCCopyConnection(self);
+ if (pCopy == NULL) {
+ SCWrite(self, "ERROR: out of memory in SCInvoke", eError);
+ return 0;
+ }
+ strlcpy(pCopy->deviceID, pBueffel, SCDEVIDLEN);
+ /* SCAdvanceContext(self,pBueffel); */
+ traceCommand(ConID(self),"in:%s", pCommand);
+ iRet = InterpExecute(pInter, pCopy, pCommand);
+ /* SCPopContext(self); */
+ SCDeleteConnection(pCopy);
+ StatusFileTask(NULL); /* save changed parameters */
+
+ self->inUse--;
+ return iRet;
+}
+
/*---------------------------------------------------------------------------
For configuring connections. Syntax:
config OutCode val sets an new output code
@@ -1627,625 +1664,547 @@ pDynString SCEndBuffering(SConnection *pCon)
config output normal | withcode | ACT Sets output mode
config listen 0 | 1 enables commandlog listen mode
---------------------------------------------------------------------------*/
-
- int ConfigCon(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- char pBueffel[512];
- char pHost[132];
- int i, iRet;
- int iNum;
-
- if(!VerifyConnection(pCon))
- {
- return 0;
- }
- assert(pSics);
-
- /* check no of args */
- if(argc < 2)
- {
- sprintf(pBueffel,"Insufficient number of args to %s",argv[0]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
- /* handle list*/
- strtolower(argv[1]);
- if(strcmp(argv[1],"list") == 0)
- {
- sprintf(pBueffel,"OutCode = %s\nUserRights = %d",
- pCode[pCon->iOutput], SCGetRights(pCon));
- SCWrite(pCon,pBueffel,eStatus);
- return 1;
- }
- else if(strcmp(argv[1],"myname") == 0)
- {
- sprintf(pBueffel,"MyName = %s",ConName(pCon->ident));
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- else if(strcmp(argv[1],"myrights") == 0)
- {
- sprintf(pBueffel,"UserRights = %d",SCGetRights(pCon));
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- else if(strcmp(argv[1],"listen") == 0)
- {
- if(argc < 3)
- {
- snprintf(pBueffel,511,"listen = %d", pCon->listening);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- else
- {
- pCon->listening = atoi(argv[2]);
- if(pCon->listening != 0 && pCon->listening != 1)
- {
- pCon->listening = 0;
- SCWrite(pCon,"ERROR: config listen only accepts 0 or 1 as arguments",eError);
- return 0;
- }
- SCSendOK(pCon);
- return 1;
- }
- }
- /* check no or args */
- if(argc < 3)
- {
- sprintf(pBueffel,"Insufficient number of args to %s",argv[0]);
- SCWrite(pCon,pBueffel,eInError);
- return 0;
- }
-
- /* decide what to do */
- if(strcmp(argv[1],"file") == 0)
- {
- iRet = SCAddLogFile(pCon,argv[2]);
- if(iRet >= 0 )
- {
- sprintf(pBueffel,"File = %d",iRet);
- SCWrite(pCon,pBueffel,eStatus);
- return 1;
- }
- }
- if(strcmp(argv[1],"close") == 0) /* close file */
- {
- iNum = atoi(argv[2]);
- if( (iNum >= 0) && (iNum < MAXLOGFILES))
- {
- if(pCon->pFiles[iNum])
- {
- fclose(pCon->pFiles[iNum]);
- pCon->pFiles[iNum] = NULL;
- SCSendOK(pCon);
- return 1;
- }
- }
- else
- {
- SCWrite(pCon, "Invalid file number specified ",eError);
- return 0;
- }
- }
- else if(strcmp(argv[1],"outcode") == 0)
- {
- i = 0;
- strtolower(argv[2]);
- while(pCode[i] != NULL)
- {
- if(strcmp(pCode[i],argv[2]) == 0)
- {
- break;
- }
- i++;
- }
- if( i > iNoCodes)
- {
- sprintf(pBueffel,"OutCode %s not recognized",argv[2]);
- SCWrite(pCon,pBueffel,eInError);
- return 0;
- }
- pCon->iOutput = i;
- SCSendOK(pCon);
- return 1;
- }
- else if(strcmp(argv[1],"output") == 0)
- {
- strtolower(argv[2]);
- if(strcmp(argv[2],"normal") == 0)
- {
- SCSetWriteFunc(pCon,SCNormalWrite);
- }
- else if(strcmp(argv[2],"withcode") == 0)
- {
- SCSetWriteFunc(pCon,SCWriteWithOutcode);
- }
- else if(strcmp(argv[2],"act") == 0)
- {
- SCSetWriteFunc(pCon,SCACTWrite);
- }
- else
- {
- SCWrite(pCon,"ERROT: output mode not recognised",eError);
- return 0;
- }
- SCSendOK(pCon);
- return 1;
- }
- else if(strcmp(argv[1],"rights") == 0)
- {
- if(argc < 4)
- {
- sprintf(pBueffel,"Insufficient number of args to %s",argv[0]);
- SCWrite(pCon,pBueffel,eInError);
- return 0;
- }
- i = IsValidUser(argv[2],argv[3]);
- if(i < 0)
- {
- sprintf(pBueffel," %s with password ****** is NO valid User on SICS",
- argv[2]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- if (CompactCommandLog()) {
- if (pCon->iUserRights < 3 || i < 3) {
- NETInfo(pCon->pSock,pHost,sizeof pHost);
- sprintf(pBueffel,"User %s from %s switched to %d privilege",
- argv[2],pHost,i);
- WriteToCommandLogId("SYS>",pCon->pSock->sockid,pBueffel);
- }
- } else {
- sprintf(pBueffel,"User %s socket %d switched to %d privilege",
- argv[2],pCon->pSock->sockid,i);
- WriteToCommandLog("SYS>",pBueffel);
- }
- pCon->iUserRights = i;
- SCWrite(pCon,"Change of Authorisation Acknowledged",eWarning);
- return 1;
- }
- SCWrite(pCon,"Command not recognized",eError);
- return 0;
- }
+int ConfigCon(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ char pBueffel[512];
+ char pHost[132];
+ int i, iRet;
+ int iNum;
+ SConnection *pMaster = NULL;
+
+ if (!VerifyConnection(pCon)) {
+ return 0;
+ }
+ assert(pSics);
+
+ /* check no of args */
+ if (argc < 2) {
+ snprintf(pBueffel,511, "Insufficient number of args to %s", argv[0]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ pMaster = SCfindMaster(pCon);
+
+ /* handle list */
+ strtolower(argv[1]);
+ if (strcmp(argv[1], "list") == 0) {
+ sprintf(pBueffel, "OutCode = %s\nUserRights = %d",
+ pCode[pCon->iOutput], SCGetRights(pCon));
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else if (strcmp(argv[1], "myname") == 0) {
+ snprintf(pBueffel,511, "MyName = %s", ConName(pCon->ident));
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else if (strcmp(argv[1], "myrights") == 0) {
+ sprintf(pBueffel, "UserRights = %d", SCGetRights(pCon));
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else if (strcmp(argv[1], "listen") == 0) {
+ if (argc < 3) {
+ snprintf(pBueffel, 511, "listen = %d", pCon->listening);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else {
+ pCon->listening = atoi(argv[2]);
+ if (pCon->listening != 0 && pCon->listening != 1) {
+ pCon->listening = 0;
+ SCWrite(pCon,
+ "ERROR: config listen only accepts 0 or 1 as arguments",
+ eError);
+ return 0;
+ }
+ pMaster->listening = pCon->listening;
+ SCSendOK(pCon);
+ return 1;
+ }
+ }
+
+ /* check no or args */
+ if (argc < 3) {
+ snprintf(pBueffel,511, "Insufficient number of args to %s", argv[0]);
+ SCWrite(pCon, pBueffel, eInError);
+ return 0;
+ }
+
+ if (strcmp(argv[1], "outcode") == 0) {
+ i = 0;
+ strtolower(argv[2]);
+ while (pCode[i] != NULL) {
+ if (strcmp(pCode[i], argv[2]) == 0) {
+ break;
+ }
+ i++;
+ }
+ if (i > iNoCodes) {
+ snprintf(pBueffel,511, "OutCode %s not recognized", argv[2]);
+ SCWrite(pCon, pBueffel, eInError);
+ return 0;
+ }
+ pCon->iOutput = i;
+ pMaster->iOutput = i;
+ SCSendOK(pCon);
+ return 1;
+ } else if (strcmp(argv[1], "output") == 0) {
+ strtolower(argv[2]);
+ if (strcmp(argv[2], "normal") == 0) {
+ SCSetWriteFunc(pCon, SCNormalWrite);
+ SCSetWriteFunc(pMaster, SCNormalWrite);
+ } else if (strcmp(argv[2], "withcode") == 0) {
+ SCSetWriteFunc(pCon, SCWriteWithOutcode);
+ SCSetWriteFunc(pMaster, SCWriteWithOutcode);
+ } else if (strcmp(argv[2], "act") == 0) {
+ SCSetWriteFunc(pCon, SCACTWrite);
+ SCSetWriteFunc(pMaster, SCACTWrite);
+ } else {
+ SCWrite(pCon, "ERROT: output mode not recognised", eError);
+ return 0;
+ }
+ SCSendOK(pCon);
+ return 1;
+ } else if (strcmp(argv[1], "rights") == 0) {
+ if (argc < 4) {
+ snprintf(pBueffel,511, "Insufficient number of args to %s", argv[0]);
+ SCWrite(pCon, pBueffel, eInError);
+ return 0;
+ }
+ i = IsValidUser(argv[2], argv[3]);
+ if (i < 0) {
+ snprintf(pBueffel,511,
+ " %s with password ****** is NO valid User on SICS",
+ argv[2]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ if (CompactCommandLog()) {
+ if (pCon->iUserRights < 3 || i < 3) {
+ ANETinfo(pCon->sockHandle, pHost, sizeof pHost);
+ snprintf(pBueffel, sizeof pBueffel,
+ "User %s from %s switched to %d privilege",
+ argv[2], pHost, i);
+ WriteToCommandLogId("SYS>", pCon->sockHandle, pBueffel);
+ }
+ } else {
+ snprintf(pBueffel, 511, "User %s handle %d switched to %d privilege",
+ argv[2], pCon->sockHandle, i);
+ WriteToCommandLog("SYS>", pBueffel);
+ }
+ pCon->iUserRights = i;
+ pMaster->iUserRights = i;
+ SCWrite(pCon, "Change of Authorisation Acknowledged", eWarning);
+ return 1;
+ }
+ SCWrite(pCon, "Command not recognized", eError);
+ return 0;
+}
+
/*----------------------------------------------------------------------*/
- int SCRegister(SConnection *pCon, SicsInterp *pSics,
- void *pData, long lID)
- {
- pICallBack pInter = NULL;
- Item sItem;
-
- pInter = (pICallBack)pData;
- if(!VerifyConnection(pCon))
- {
- return 0;
- }
- assert(pSics);
- assert(pInter);
-
- sItem.lID = lID;
- sItem.pInterface = pInter;
- LLDnodeAppendFrom(pCon->iList,&sItem);
- return 1;
+int SCRegister(SConnection * pCon, SicsInterp * pSics,
+ void *pData, long lID)
+{
+ pICallBack pInter = NULL;
+ Item sItem;
+ SConnection *pMaster = NULL;
+
+ pInter = (pICallBack) pData;
+ if (!VerifyConnection(pCon)) {
+ return 0;
}
-/*----------------------------------------------------------------------*/
- int SCUnregister(SConnection *pCon, void *pData)
- {
- int iRet;
- Item sItem;
- pICallBack pInter;
-
- if(!VerifyConnection(pCon))
- {
- return 0;
- }
- pInter = (pICallBack)pData;
- iRet = LLDnodePtr2First(pCon->iList);
- while(iRet != 0)
- {
- LLDnodeDataTo(pCon->iList,&sItem);
- if(sItem.pInterface == pInter)
- {
- LLDnodeDelete(pCon->iList);
- LLDnodePtr2Prev(pCon->iList);
- }
- iRet = LLDnodePtr2Next(pCon->iList);
- }
- return 1;
+ assert(pSics);
+ assert(pInter);
+
+ sItem.lID = lID;
+ sItem.pInterface = pInter;
+ pMaster = SCfindMaster(pCon);
+ LLDnodeAppendFrom(pMaster->iList, &sItem);
+ return 1;
+}
+
+/*----------------------------------------------------------------------*/
+int SCUnregister(SConnection * pCon, void *pData)
+{
+ int iRet;
+ Item sItem;
+ pICallBack pInter;
+ SConnection *pMaster = NULL;
+
+ if (!VerifyConnection(pCon)) {
+ return 0;
}
-/*----------------------------------------------------------------------*/
- int SCUnregisterID(SConnection *pCon, long ID)
- {
- int iRet;
- Item sItem;
-
- if(!VerifyConnection(pCon))
- {
- return 0;
+ pInter = (pICallBack) pData;
+ pMaster = SCfindMaster(pCon);
+
+ iRet = LLDnodePtr2First(pMaster->iList);
+ while (iRet != 0) {
+ LLDnodeDataTo(pMaster->iList, &sItem);
+ if (sItem.pInterface == pInter) {
+ LLDnodeDelete(pMaster->iList);
+ LLDnodePtr2Prev(pMaster->iList);
}
- iRet = LLDnodePtr2First(pCon->iList);
- while(iRet != 0)
- {
- LLDnodeDataTo(pCon->iList,&sItem);
- if(sItem.lID == ID )
- {
- LLDnodeDelete(pCon->iList);
- LLDnodePtr2Prev(pCon->iList);
- }
- iRet = LLDnodePtr2Next(pCon->iList);
- }
- return 1;
+ iRet = LLDnodePtr2Next(pMaster->iList);
}
-/*----------------------------------------------------------------------*/
- long SCgetCallbackID(SConnection *pCon, void *pData)
- {
- int iRet;
- Item sItem;
- pICallBack pInter;
-
- if(!VerifyConnection(pCon))
- {
- return 0;
- }
- pInter = (pICallBack)pData;
- iRet = LLDnodePtr2First(pCon->iList);
- while(iRet != 0)
- {
- LLDnodeDataTo(pCon->iList,&sItem);
- if(sItem.pInterface == pInter)
- {
- return sItem.lID;
- }
- iRet = LLDnodePtr2Next(pCon->iList);
- }
- return -1;
+ return 1;
+}
+
+/*----------------------------------------------------------------------*/
+int SCUnregisterID(SConnection * pCon, long ID)
+{
+ int iRet;
+ Item sItem;
+ SConnection *pMaster = NULL;
+
+ if (!VerifyConnection(pCon)) {
+ return 0;
}
+ pMaster = SCfindMaster(pCon);
+ iRet = LLDnodePtr2First(pMaster->iList);
+ while (iRet != 0) {
+ LLDnodeDataTo(pMaster->iList, &sItem);
+ if (sItem.lID == ID) {
+ LLDnodeDelete(pMaster->iList);
+ LLDnodePtr2Prev(pMaster->iList);
+ }
+ iRet = LLDnodePtr2Next(pMaster->iList);
+ }
+ return 1;
+}
+
+/*----------------------------------------------------------------------*/
+long SCgetCallbackID(SConnection * pCon, void *pData)
+{
+ int iRet;
+ Item sItem;
+ pICallBack pInter;
+ SConnection *pMaster = NULL;
+
+ if (!VerifyConnection(pCon)) {
+ return 0;
+ }
+ pMaster = SCfindMaster(pCon);
+ pInter = (pICallBack) pData;
+ iRet = LLDnodePtr2First(pMaster->iList);
+ while (iRet != 0) {
+ LLDnodeDataTo(pMaster->iList, &sItem);
+ if (sItem.pInterface == pInter) {
+ return sItem.lID;
+ }
+ iRet = LLDnodePtr2Next(pMaster->iList);
+ }
+ return -1;
+}
/*---------------------- The callback data structure --------------------*/
- typedef struct {
- SConnection *pCon;
- SicsInterp *pSics;
- char *pAction;
- } CBAction, *pCBAction;
+typedef struct {
+ SConnection *pCon;
+ SicsInterp *pSics;
+ char *pAction;
+} CBAction, *pCBAction;
/*---------------------- CBKill -----------------------------------------*/
- static void CBKill(void *pData)
- {
- pCBAction self = NULL;
- self = (pCBAction)pData;
-
- if(self == NULL)
- {
- return;
- }
-
- if(self->pAction)
- {
- free(self->pAction);
- }
- free(self);
- }
+static void CBKill(void *pData)
+{
+ pCBAction self = NULL;
+ self = (pCBAction) pData;
+
+ if (self == NULL) {
+ return;
+ }
+
+ if (self->pCon) {
+ SCDeleteConnection(self->pCon);
+ }
+ if (self->pAction) {
+ free(self->pAction);
+ }
+ free(self);
+}
/*-------------------------------------------------------------------------
The callback function for connection callbacks. Invokes command
given at registration time.
*/
- static int ConCallBack(int iEvent, void *pEventData, void *pUserData,
- commandContext cc)
- {
- pCBAction self = NULL;
-
- self = (pCBAction)pUserData;
- assert(self);
-
- if(self->pAction)
- {
- SCPushContext2(self->pCon,cc);
- InterpExecute(pServ->pSics,self->pCon,self->pAction);
- SCPopContext(self->pCon);
- }
- return 1;
- }
-/*--------------------------------------------------------------------------*/
- int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- SConnection *self = NULL;
- pICallBack pInterface = NULL;
- char pBueffel[1024];
- pDummy pDum;
- int iEvent;
- Item sItem;
- pCBAction pCB = NULL;
- CommandList *pCom = NULL;
- int iMacro;
- char *script;
-
- self = (SConnection *)pData;
- if(!VerifyConnection(self))
- {
- return 0;
- }
-
- if(argc > 1)
- {
- /* put */
- if(strcmp(argv[1],"put") == 0)
- {
- Arg2Text(argc-2,&argv[2],pBueffel,1023);
- iMacro = SCinMacro(pCon);
- SCsetMacro(pCon,0);
- SCWrite(self,pBueffel,eWarning);
- SCsetMacro(pCon,iMacro);
- return 1;
- }
- /* register object event action */
- if(strcmp(argv[1],"register") == 0)
- {
- if(argc < 5)
- {
- SCWrite(pCon,"ERROR: Insufficient arguments to register",eError);
- return 0;
- }
-
- /* get object */
- pCom = FindCommand(pSics,argv[2]);
- if(!pCom)
- {
- sprintf(pBueffel,"ERROR: object %s NOT found",argv[2]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
- /* get CallBack interface */
- pDum = (pDummy)pCom->pData;
- assert(pDum);
- pInterface = (pICallBack)pDum->pDescriptor->GetInterface(pDum,
- CALLBACKINTERFACE);
- if(!pInterface)
- {
- sprintf(pBueffel,"ERROR: %s does not support CallBacks",
- argv[2]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
- /* get Event */
- iEvent = Text2Event(argv[3]);
- if(iEvent < 0)
- {
- sprintf(pBueffel,"ERROR: Unknown event code %s",argv[3]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
- script = Arg2Tcl(argc-4, &argv[4], NULL, 0);
-
- /* now we can install the callback */
- pCB = (pCBAction)malloc(sizeof(CBAction));
- if(!pCB || !script)
- {
- SCWrite(pCon,"ERROR: memory exhausted in SConnection",eError);
- return 0;
- }
- pCB->pCon = pCon;
- pCB->pSics = pSics;
- pCB->pAction = script;
- sItem.pInterface = pInterface;
- sItem.lID = RegisterCallback(pInterface, SCGetContext(pCB->pCon), iEvent, ConCallBack,
- pCB, CBKill);
- LLDnodeAppendFrom(self->iList,&sItem);
- SCSendOK(pCon);
- return 1;
- }
- }
- return 0;
- }
-/*--------------------------------------------------------------------------*/
- int SCTaskFunction(void *pData)
- {
- SConnection *self = NULL;
- char *pPtr = NULL;
- int iRet;
- char *pUser = NULL, *pPassword = NULL;
- char pHost[132], pBueffel[512];
-
- self = (SConnection *)pData;
- if(!VerifyConnection(self))
- {
- return 0;
- }
- if(self->pSock->iType == 0)
- {
- NetReadRemove(pServ->pReader,self->pSock);
- self->iEnd = 1;
- }
-
- if(self->iEnd)
- {
- if(SCActive(self))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- /* a timeout check on logins */
- if(!self->iLogin && time(NULL) > self->conStart + 120)
- {
- NetReadRemove(pServ->pReader,self->pSock);
- SCWrite(self, "No valid login in two minutes, closing..",eError);
- self->iEnd = 1;
- return 1;
- }
-
- /* pop and execute */
- iRet = CostaPop(self->pStack,&pPtr);
- if(iRet)
- {
- if(pPtr)
- {
- if(self->iLogin)
- {
- /*
- normal processing, logged in
- but check for logoff
- */
- if(strstr(pPtr,"logoff") != NULL)
- {
- NetReadRemove(pServ->pReader,self->pSock);
- self->iEnd = 1;
- free(pPtr);
- return 1;
- }
- /* invoke command */
- CostaLock(self->pStack);
- SCInvoke(self,pServ->pSics,pPtr);
- CostaUnlock(self->pStack);
- }
- else
- {
- /* response for monit check */
- if (strstr(pPtr,"How are you") == pPtr)
- {
- SCWrite(self,"I am fine",eError);
- NetReadRemove(pServ->pReader,self->pSock);
- self->iEnd = 1;
- free(pPtr);
- return 1;
- }
- /* check for username and password */
- pUser = strtok(pPtr," \t");
- pPassword = strtok(NULL," \t\r\n");
- iRet = IsValidUser(pUser,pPassword);
- if(iRet >= 0)
- {
- SCWrite(self,"Login OK",eError);
- self->iLogin = 1;
- SCSetRights(self,iRet);
- pHost[0] = '\0';
- if (CompactCommandLog()) {
- if (iRet < 3) {
- NETInfo(self->pSock,pHost,131);
- sprintf(pBueffel,"Accepted connection %s from %s as %s",
- ConName(self->ident), pHost, pUser);
- SICSLogWrite(pBueffel,eInternal);
- WriteToCommandLogId("SYS>", self->pSock->sockid, pBueffel);
- }
- } else {
- NETInfo(self->pSock,pHost,131);
- sprintf(pBueffel,"Accepted connection %s on socket %d from %s",
- ConName(self->ident), self->pSock->sockid, pHost);
- SICSLogWrite(pBueffel,eInternal);
- WriteToCommandLog("SYS >", pBueffel);
- }
- free(pPtr);
- return 1;
- }
- else
- {
- SCWrite(self,"ERROR: Bad login",eError);
- printf("Bad login string %s\n", pPtr);
- }
- }
- free(pPtr);
- }
- }
-
-
- if(self->iEnd)
- {
- if(SCActive(self))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- return 1;
- }
-/*---------------------------------------------------------------------------*/
- void SCSignalFunction(void *pData, int iSignal, void *pSigData)
- {
- SConnection *self = NULL;
- int *iInt;
- char *pPtr;
-
- self = (SConnection *)pData;
- if(!VerifyConnection(self))
- {
- return;
- }
-
- if(iSignal == SICSINT)
- {
- iInt = (int *)pSigData;
- SCSetInterrupt(self,*iInt);
- if(*iInt == eEndServer)
- {
- self->iEnd = 1;
- }
- }
- else if(iSignal == SICSBROADCAST)
- {
- pPtr = (char *)pSigData;
- if(pPtr != NULL)
- {
- SCWrite(self,pPtr,eWarning);
- }
- }
- else if(iSignal == COMLOG && self->listening == 1)
- {
- pPtr = (char *)pSigData;
- if(pPtr != NULL && self != sendingConnection)
- {
- doSockWrite(self,pPtr);
- }
- }
- else if(iSignal == TOKENRELEASE)
- {
- self->iGrab = 0;
- }
- else if(iSignal == TOKENGRAB)
- {
- self->iGrab = 1;
- }
- }
-/*-----------------------------------------------------------------------*/
-void SCparChange(SConnection *self)
+static int ConCallBack(int iEvent, void *pEventData, void *pUserData)
{
- StatusFileDirty();
-}
-/*------------------------------------------------------------------------*/
-int SCActive(SConnection *self)
-{
- if(self->inUse != 0 )
- {
- return 1;
+ pCBAction self = NULL;
+
+ self = (pCBAction) pUserData;
+ assert(self);
+
+ /* check kill condition */
+ if (self->pCon == NULL) {
+ return -1;
}
- if(pServ->pExecutor != NULL)
- {
- if(GetExeOwner(pServ->pExecutor) == self)
- {
+
+ if (self->pAction) {
+ InterpExecute(pServ->pSics, self->pCon, self->pAction);
+ }
+ return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+int ConSicsAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ SConnection *self = NULL;
+ pICallBack pInterface = NULL;
+ char pBueffel[1024];
+ pDummy pDum;
+ int iEvent;
+ Item sItem;
+ pCBAction pCB = NULL;
+ CommandList *pCom = NULL;
+ int iMacro;
+ char *script;
+
+ self = (SConnection *) pData;
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ if (argc > 1) {
+ /* put */
+ if (strcmp(argv[1], "put") == 0) {
+ Arg2Text(argc - 2, &argv[2], pBueffel, 1023);
+ iMacro = SCinMacro(pCon);
+ SCsetMacro(pCon, 0);
+ SCWrite(self, pBueffel, eWarning);
+ SCsetMacro(pCon, iMacro);
+ return 1;
+ }
+ /* register object event action */
+ if (strcmp(argv[1], "register") == 0) {
+ if (argc < 5) {
+ SCWrite(pCon, "ERROR: Insufficient arguments to register", eError);
+ return 0;
+ }
+
+ /* get object */
+ pCom = FindCommand(pSics, argv[2]);
+ if (!pCom) {
+ snprintf(pBueffel,1024, "ERROR: object %s NOT found", argv[2]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+ /* get CallBack interface */
+ pDum = (pDummy) pCom->pData;
+ assert(pDum);
+ pInterface = (pICallBack) pDum->pDescriptor->GetInterface(pDum,
+ CALLBACKINTERFACE);
+ if (!pInterface) {
+ snprintf(pBueffel,1023, "ERROR: %s does not support CallBacks", argv[2]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+ /* get Event */
+ iEvent = Text2Event(argv[3]);
+ if (iEvent < 0) {
+ snprintf(pBueffel,1023, "ERROR: Unknown event code %s", argv[3]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+ script = Arg2Tcl(argc - 4, &argv[4], NULL, 0);
+
+ /* now we can install the callback */
+ pCB = (pCBAction) malloc(sizeof(CBAction));
+ if (!pCB || !script) {
+ SCWrite(pCon, "ERROR: memory exhausted in SConnection", eError);
+ return 0;
+ }
+ pCB->pCon = SCCopyConnection(pCon);
+ if (!pCB->pCon) {
+ SCWrite(pCon, "ERROR: memory exhausted in SConnection", eError);
+ return 0;
+ }
+ pCB->pSics = pSics;
+ pCB->pAction = script;
+ sItem.pInterface = pInterface;
+ sItem.lID = RegisterCallback(pInterface, iEvent, ConCallBack,
+ pCB, CBKill);
+ LLDnodeAppendFrom(self->iList, &sItem);
+ SCSendOK(pCon);
return 1;
}
}
return 0;
}
+
/*--------------------------------------------------------------------------*/
-SCStore *SCSave(SConnection *pCon, SCStore *oldStore) {
+int SCTaskFunction(void *pData)
+{
+ SConnection *self = NULL;
+ char *pPtr = NULL;
+ int iRet;
+ char *pUser = NULL, *pPassword = NULL;
+ char pHost[132], pBueffel[512];
+
+ self = (SConnection *) pData;
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
+
+ if (self->iEnd) {
+ if (SCActive(self)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ if (!SCisConnected(self)) {
+ self->iEnd = 1;
+ return 1;
+ }
+
+
+ /* a timeout check on logins */
+ if (!self->iLogin && time(NULL) > self->conStart + 120) {
+ ANETclose(self->sockHandle);
+ SCWrite(self, "No valid login in two minutes, closing..", eError);
+ self->iEnd = 1;
+ return 1;
+ }
+
+ /* pop and execute */
+ iRet = CostaPop(self->pStack, &pPtr);
+ if (iRet) {
+ if (pPtr) {
+ if (self->iLogin) {
+ /*
+ normal processing, logged in
+ but check for logoff
+ */
+ if (strstr(pPtr, "logoff") != NULL) {
+ ANETclose(self->sockHandle);
+ self->iEnd = 1;
+ free(pPtr);
+ return 1;
+ }
+ /* invoke command */
+ CostaLock(self->pStack);
+ SCInvoke(self, pServ->pSics, pPtr);
+ CostaUnlock(self->pStack);
+ } else {
+ /* response for monit check */
+ if (strstr(pPtr, "How are you") == pPtr) {
+ SCWrite(self, "I am fine", eError);
+ ANETclose(self->sockHandle);
+ self->iEnd = 1;
+ free(pPtr);
+ return 1;
+ }
+ /* check for username and password */
+ pUser = strtok(pPtr, " \t");
+ pPassword = strtok(NULL, " \t\r\n");
+ iRet = IsValidUser(pUser, pPassword);
+ if (iRet >= 0) {
+ SCWrite(self, "Login OK", eError);
+ self->iLogin = 1;
+ SCSetRights(self, iRet);
+ pHost[0] = '\0';
+ if (CompactCommandLog()) {
+ if (iRet < 3) {
+ ANETinfo(self->sockHandle, pHost, 131);
+ sprintf(pBueffel, "Accepted connection %s from %s as %s",
+ ConName(self->ident), pHost, pUser);
+ SICSLogWrite(pBueffel, eInternal);
+ WriteToCommandLogId("SYS>", self->sockHandle, pBueffel);
+ }
+ } else {
+ ANETinfo(self->sockHandle, pHost, 131);
+ snprintf(pBueffel, 511,
+ "Accepted connection %s on socket %d from %s",
+ ConName(self->ident), self->sockHandle, pHost);
+ SICSLogWrite(pBueffel, eInternal);
+ WriteToCommandLog("SYS >", pBueffel);
+ }
+ free(pPtr);
+ return 1;
+ } else {
+ SCWrite(self, "ERROR: Bad login", eError);
+ printf("Bad login string %s\n", pPtr);
+ }
+ }
+ free(pPtr);
+ }
+ }
+
+ if (self->iEnd) {
+ if (SCActive(self)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+void SCSignalFunction(void *pData, int iSignal, void *pSigData)
+{
+ SConnection *self = NULL;
+ int *iInt;
+ char *pPtr;
+
+ self = (SConnection *) pData;
+ if (!VerifyConnection(self)) {
+ return;
+ }
+
+ if (iSignal == SICSINT) {
+ iInt = (int *) pSigData;
+ SCSetInterrupt(self, *iInt);
+ if (*iInt == eEndServer) {
+ self->iEnd = 1;
+ }
+ } else if (iSignal == SICSBROADCAST) {
+ pPtr = (char *) pSigData;
+ if (pPtr != NULL) {
+ SCWrite(self, pPtr, eWarning);
+ }
+ } else if (iSignal == COMLOG && self->listening == 1) {
+ pPtr = (char *) pSigData;
+ if (pPtr != NULL && self->sockHandle != sendingConnection) {
+ doSockWrite(self, pPtr);
+ }
+ } else if (iSignal == TOKENRELEASE) {
+ self->iGrab = 0;
+ } else if (iSignal == TOKENGRAB) {
+ self->iGrab = 1;
+ }
+}
+
+/*-----------------------------------------------------------------------*/
+void SCparChange(SConnection * self)
+{
+ StatusFileDirty();
+}
+
+/*------------------------------------------------------------------------*/
+int SCActive(SConnection * self)
+{
+ if (self->inUse != 0) {
+ return 1;
+ }
+ if (pServ->pExecutor != NULL) {
+ if (GetExeOwner(pServ->pExecutor) == self) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+SCStore *SCSave(SConnection * pCon, SCStore * oldStore)
+{
commandContext cc;
-
+
if (oldStore == NULL) {
- oldStore = calloc(1,sizeof(*oldStore));
+ oldStore = calloc(1, sizeof(*oldStore));
assert(oldStore);
}
oldStore->pCon = pCon;
@@ -2257,17 +2216,19 @@ SCStore *SCSave(SConnection *pCon, SCStore *oldStore) {
}
return oldStore;
}
+
/*--------------------------------------------------------------------------*/
-SConnection *SCLoad(SCStore *conStore) {
+SConnection *SCLoad(SCStore * conStore)
+{
SConnection *pCon = NULL;
commandContext old;
-
+
if (conStore) {
pCon = conStore->pCon;
}
if (pCon) {
if (conStore->ident != pCon->ident) {
- conStore->pCon = NULL; /* connection is dead */
+ conStore->pCon = NULL; /* connection is dead */
pCon = NULL;
}
}
@@ -2276,8 +2237,10 @@ SConnection *SCLoad(SCStore *conStore) {
}
return pServ->dummyCon;
}
+
/*--------------------------------------------------------------------------*/
-SConnection *SCStorePush(SCStore *conStore) {
+SConnection *SCStorePush(SCStore * conStore)
+{
SConnection *pCon;
pCon = SCLoad(conStore);
@@ -2288,124 +2251,119 @@ SConnection *SCStorePush(SCStore *conStore) {
SCPushContext2(pCon, conStore->cc);
return pCon;
}
+
/*--------------------------------------------------------------------------*/
-void SCStorePop(SCStore *conStore) {
+void SCStorePop(SCStore * conStore)
+{
SConnection *pCon;
-
+
pCon = SCLoad(conStore);
SCPopContext(pCon);
/* pop macro flag from stack
- SCsetMacro(pCon,conStore->macroStack);
- */
+ SCsetMacro(pCon,conStore->macroStack);
+ */
SCsetMacro(pCon, (conStore->macroStack & 1));
conStore->macroStack >>= 1;
}
+
/*--------------------------------------------------------------------------*/
-int SCStoreConnected(SCStore *conStore) {
+int SCStoreConnected(SCStore * conStore)
+{
return (conStore &&
- conStore->pCon &&
- conStore->pCon->ident == conStore->ident);
+ conStore->pCon && conStore->pCon->ident == conStore->ident);
}
+
/*--------------------------------------------------------------------------*/
-void SCStoreFree(SCStore *conStore) {
+void SCStoreFree(SCStore * conStore)
+{
free(conStore);
}
-/* --------------------------------------------------------------------------*/
-long SCTagContext(SConnection *self, char *tagName)
-{
- commandContext a;
- if(NULL==self) return -1;
- a = SCGetContext(self);
- strncpy(a.deviceID,tagName,SCDEVIDLEN);
- /*
- SCGetContext will already have advanced the stack pointer to the
- last position
- */
- LLDnodeDataTo(self->contextStack, &a);
- return 1;
-}
/* --------------------------------------------------------------------------*/
-long SCAdvanceContext(SConnection *self, char *tagName)
+long SCTagContext(SConnection * self, char *tagName)
{
- if(NULL==self) return -1;
- self->iCmdCtr++;
- if(999999iCmdCtr)
- {
- self->iCmdCtr = 0;
- }
- return SCPushContext(self, self->iCmdCtr, tagName);
+ commandContext a;
+ if (NULL == self)
+ return -1;
+
+ a = SCGetContext(self);
+ strlcpy(a.deviceID, tagName, SCDEVIDLEN);
+ /*
+ SCGetContext will already have advanced the stack pointer to the
+ last position
+ */
+ LLDnodeDataTo(self->contextStack, &a);
+ return 1;
}
-/*------------------------------------------------------------------------*/
-int SCVerifyConnection(SConnection *self)
+
+/* --------------------------------------------------------------------------*/
+long SCAdvanceContext(SConnection * self, char *tagName)
{
- return VerifyConnection(self);
-}
-/*------------------------------------------------------------------------*/
-void SCWriteToLogFiles(SConnection *self, char *buffer)
-{
- writeToLogFiles(self,buffer);
-}
-/*------------------------------------------------------------------------*/
-int SCDoSockWrite(SConnection *self, char *buffer)
-{
- return doSockWrite(self,buffer);
-}
-/*--------------------------------------------------------------------------*/
-void KillFreeConnections(void) {
- SConnection *next;
- while (freeConnections) {
- next = freeConnections->next;
- free(freeConnections);
- freeConnections = next;
+ if (NULL == self)
+ return -1;
+ self->iCmdCtr++;
+ if (999999 < self->iCmdCtr) {
+ self->iCmdCtr = 0;
}
+ return SCPushContext(self, self->iCmdCtr, tagName);
}
+
+/*------------------------------------------------------------------------*/
+int SCVerifyConnection(SConnection * self)
+{
+ return VerifyConnection(self);
+}
+
+/*------------------------------------------------------------------------*/
+int SCDoSockWrite(SConnection * self, char *buffer)
+{
+ return doSockWrite(self, buffer);
+}
+
/*-------------------------------------------------------------------------*/
-int SCPushContext(SConnection *self, int ID, char *deviceID)
+int SCPushContext(SConnection * self, int ID, char *deviceID)
{
- commandContext neu;
+ commandContext neu;
- if(!VerifyConnection(self))
- {
- return 0;
- }
+ if (!VerifyConnection(self)) {
+ return 0;
+ }
- neu.transID = ID;
- strncpy(neu.deviceID,deviceID,SCDEVIDLEN);
- LLDnodeAppendFrom(self->contextStack,&neu);
- return 1;
+ neu.transID = ID;
+ strlcpy(neu.deviceID, deviceID, SCDEVIDLEN);
+ LLDnodeAppendFrom(self->contextStack, &neu);
+ return 1;
}
-/*------------------------------------------------------*/
-int SCPushContext2(SConnection *self, commandContext cc)
-{
- return SCPushContext(self,cc.transID, cc.deviceID);
-}
-/*------------------------------------------------------*/
-commandContext SCGetContext(SConnection *pCon)
-{
- commandContext neu;
- neu.transID = 0;
- strcpy(neu.deviceID,"Undefined");
- if(!VerifyConnection(pCon))
- {
- return neu;
- }
- if(LLDnodePtr2Last(pCon->contextStack) == 1){
- LLDnodeDataTo(pCon->contextStack, &neu);
- }
+/*------------------------------------------------------*/
+int SCPushContext2(SConnection * self, commandContext cc)
+{
+ return SCPushContext(self, cc.transID, cc.deviceID);
+}
+
+/*------------------------------------------------------*/
+commandContext SCGetContext(SConnection * pCon)
+{
+ commandContext neu;
+ neu.transID = 0;
+ strcpy(neu.deviceID, "Undefined");
+
+ if (!VerifyConnection(pCon)) {
return neu;
+ }
+ neu.transID = pCon->transID;
+ strlcpy(neu.deviceID, pCon->deviceID, SCDEVIDLEN);
+ return neu;
}
+
/*-----------------------------------------------------*/
-int SCPopContext(SConnection *pCon)
+int SCPopContext(SConnection * pCon)
{
- if(!VerifyConnection(pCon))
- {
- return 0;
- }
- if(LLDnodePtr2Last(pCon->contextStack) != 0)
- {
- LLDnodeDelete(pCon->contextStack);
- }
- return 1;
+ if (!VerifyConnection(pCon)) {
+ return 0;
+ }
+ if (LLDnodePtr2Last(pCon->contextStack) != 0) {
+ LLDnodeDelete(pCon->contextStack);
+ }
+ return 1;
}
diff --git a/conman.h b/conman.h
index aaf0e006..8f085332 100644
--- a/conman.h
+++ b/conman.h
@@ -1,4 +1,3 @@
-
/*--------------------------------------------------------------------------
C O N N E C T I O N O B J E C T
@@ -15,6 +14,10 @@
Mark Koennecke, December 2004
copyright: see copyright.h
+
+ substantially revised for the new asynchronous I/O system
+
+ Mark Koennecke, January 2009
----------------------------------------------------------------------------*/
#ifndef SICSCONNECT
#define SICSCONNECT
@@ -22,185 +25,172 @@
#include "costa.h"
#include "SCinter.h"
#include "network.h"
+#include "asynnet.h"
#include "obdes.h"
#include "commandcontext.h"
#include "dynstring.h"
#define MAXLOGFILES 10
-typedef int (*writeFunc)(struct __SConnection *pCon,
- char *pMessage, int iCode);
+typedef int (*writeFunc) (struct __SConnection * pCon,
+ char *pMessage, int iCode);
- typedef struct __SConnection {
- /* object basics */
- pObjectDescriptor pDes;
- long lMagic;
- long ident;
- struct __SConnection *next;
-
- /* I/O control */
- /* our socket */
- mkChannel *pSock;
-
- /* per connection log files */
- FILE *pFiles[MAXLOGFILES];
- int iFiles;
+typedef struct __SConnection {
+ /* Copy Object Fields */
+ pObjectDescriptor pDes; /* must be here */
+ long lMagic; /* connection object ID */
+ long ident; /* connection idetification */
+ struct __SConnection *next; /* pointer for freeConnection managenment */
+ int sockHandle; /* socket handle */
+ int iTelnet; /* telnet flag */
+ int iMacro; /* suppress I/O in macro */
+ writeFunc write; /* function doing writing */
+ int sicsError; /* Tcl interpreter requirement */
+ pDynString data; /* for I/O buffering */
+ int dataOwner; /* marking a connection owning an I/O buffer */
+ writeFunc oldWriteFunc; /* saved write function used in I/O buffering */
+ long iCmdCtr; /* sycamore protocol used */
+ int conEventType; /* sycamore protocol support */
+ int conStatus; /* should use status enum ffr */
+ int transID; /* transaction ID */
+ char deviceID[256]; /* transaction device ID */
+ int iUserRights; /* user rights of the connection */
+ int runLevel; /* run level, either RUNRUN for asynchronous or RUNDRIVE for synchronous */
- int iMacro; /* suppress I/O in macro*/
- int iTelnet; /* telnet flag */
- int iOutput;
- writeFunc write; /* function doing
- writing */
- int listening; /* for listening to commandlog or other data */
-
- /* execution context */
- int eInterrupt;
- int iUserRights;
- int inUse;
- int iGrab; /* grab flag for token*/
- int sicsError;
-
- /*
- * for I/O Buffering
- */
- pDynString data;
- writeFunc oldWriteFunc;
-
- /*
- stuff supporting the sycamore protocol and a
- command context
- */
- long iCmdCtr;
- int conEventType;
- int conStatus; /* should use status enum ffr */
- int iProtocolID;
- int contextStack;
-
- /* a FIFO */
- pCosta pStack;
-
- /* callback registry */
- int iList;
-
- /* Tasking Stuff */
- int iEnd;
- /* for keeping track of the login
- process on a non telnet connection.
- Should only be used in SCTaskFunction
- */
- int iLogin;
- time_t conStart;
- } SConnection;
+ /* master connection object fields */
+ int iList; /* callback registry, may go? */
+ int iEnd; /* flag to end connection task */
+ int iLogin; /* flag for successful login process */
+ time_t conStart; /* time when connection was built: used during login */
+ int iOutput; /* output filter flag */
+ int listening; /* for listening to commandlog or other data */
+ int eInterrupt; /* interrupts */
+ int inUse; /* usage counter for the connection */
+ int iGrab; /* grab flag for token */
+ int iProtocolID; /* ID of the protocol on this connection */
+ pCosta pStack; /* stack of pending commands */
+ int contextStack; /* context stack: may go? */
+ mkChannel *pSock; /* for temporary backwards compatability */
+} SConnection;
#include "nserver.h"
/*------------------------------ live & death ----------------------------*/
- SConnection *SCreateConnection(SicsInterp *pSics, mkChannel *pSock,
- int iUserRights);
- SConnection *SCCreateDummyConnection(SicsInterp *pSics);
- void SCDeleteConnection(void *pVictim);
-
+SConnection *SCreateConnection(SicsInterp * pSics, int sockHandle,
+ int iUserRights);
+SConnection *SCCreateDummyConnection(SicsInterp * pSics);
+void SCDeleteConnection(void *pVictim);
+SConnection *SCCopyConnection(SConnection * pCon);
+SConnection *SCfindMaster(SConnection * pCon);
+int SCisConnected(SConnection * pCon);
+int VerifyConnection(SConnection * pCon);
+int SCVerifyConnection(SConnection * self);
/*------------------------------- tasking --------------------------------*/
- int SCTaskFunction(void *pCon);
- void SCSignalFunction(void *pCon, int iSignal, void *pSigData);
+int SCTaskFunction(void *pCon);
+void SCSignalFunction(void *pCon, int iSignal, void *pSigData);
/* ***************************** I/O ************************************** */
- int SCAddLogFile(SConnection *self, char *name);
- int SCDelLogFile(SConnection *pCon, int iFile);
- void SCSetOutputClass(SConnection *self, int iClass);
- int SCWrite(SConnection *self, char *pBuffer, int iOut);
- int SCPrintf(SConnection *self, int iOut, char *fmt, ...);
- int SCRead(SConnection *self, char *pBuffer, int iBufLen);
- int SCPrompt(SConnection *pCon, char *pPrompt, char *pResult, int iLen);
- int SCSendOK(SConnection *self);
- int SCnoSock(SConnection *pCon);
- int SCWriteUUencoded(SConnection *pCon, char *pName, void *iData, int iLen);
- int SCWriteZipped(SConnection *pCon, char *pName, void *pData, int iDataLen);
- writeFunc SCGetWriteFunc(SConnection *pCon);
- void SCSetWriteFunc(SConnection *pCon, writeFunc x);
- int SCOnlySockWrite(SConnection *self, char *buffer, int iOut);
- int SCFileWrite(SConnection *self, char *buffer, int iOut);
- int SCNotWrite(SConnection *self, char *buffer, int iOut);
- int SCNormalWrite(SConnection *self, char *buffer, int iOut);
- int SCWriteWithOutcode(SConnection *self, char *buffer, int iOut);
- int SCACTWrite(SConnection *self, char *buffer, int iOut);
+void SCSetOutputClass(SConnection * self, int iClass);
+int SCWrite(SConnection * self, char *pBuffer, int iOut);
+int SCPrintf(SConnection * self, int iOut, char *fmt, ...);
+int SCRead(SConnection * self, char *pBuffer, int iBufLen);
+int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen);
+int SCSendOK(SConnection * self);
+int SCnoSock(SConnection * pCon);
+int SCWriteUUencoded(SConnection * pCon, char *pName, void *iData,
+ int iLen);
+int SCWriteZipped(SConnection * pCon, char *pName, void *pData,
+ int iDataLen);
+int SCWriteBinary(SConnection * pCon, char *pName, void *pData,
+ int iDataLen);
+writeFunc SCGetWriteFunc(SConnection * pCon);
+void SCSetWriteFunc(SConnection * pCon, writeFunc x);
+int SCOnlySockWrite(SConnection * self, char *buffer, int iOut);
+int SCPureSockWrite(SConnection * self, char *buffer, int iOut);
+int SCLogWrite(SConnection * self, char *buffer, int iOut);
+int SCFileWrite(SConnection * self, char *buffer, int iOut);
+int SCNotWrite(SConnection * self, char *buffer, int iOut);
+int SCNormalWrite(SConnection * self, char *buffer, int iOut);
+int SCWriteWithOutcode(SConnection * self, char *buffer, int iOut);
+int SCACTWrite(SConnection * self, char *buffer, int iOut);
/*********************** I/O Buffering ***********************************/
- int SCStartBuffering(SConnection *pCon);
- pDynString SCEndBuffering(SConnection *pCon);
+int SCStartBuffering(SConnection * pCon);
+pDynString SCEndBuffering(SConnection * pCon);
+/******************************* Error **************************************/
+void SCSetInterrupt(SConnection * self, int eCode);
+int SCGetInterrupt(SConnection * self);
+/****************************** Macro ***************************************/
+int SCinMacro(SConnection * pCon);
+int SCsetMacro(SConnection * pCon, int iMode);
+/************************** parameters changed ? **************************/
+void SCparChange(SConnection * pCon);
+/* *************************** Info *************************************** */
+int SCGetRights(SConnection * self);
+int SCSetRights(SConnection * pCon, int iNew);
+int SCMatchRights(SConnection * pCon, int iCode);
+int SCGetOutClass(SConnection * self);
+int SCGetGrab(SConnection * pCon);
+int SCActive(SConnection * pCon);
+/* **************************** Invocation ******************************** */
+int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand);
+
+/*************************** User Command **********************************/
+int ConfigCon(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+int ConSicsAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+
+/*------------------------------------------------------------------------*/
+int SCDoSockWrite(SConnection * self, char *buffer);
+int SCWriteInContext(SConnection * pCon, char *buffer, int code,
+ commandContext cc);
+
+
+/* ================== =====================================================
+ * These routines are obsolete and may not even work anymore.
+ * Mark Koennecke, January 2009
+ * ==========================================================================*/
+void SCWriteToLogFiles(SConnection * self, char *buffer);
+long SCTagContext(SConnection * self, char *tagName);
+long SCAdvanceContext(SConnection * self, char *tagName);
+int SCPushContext(SConnection * pCon, int ID, char *deviceID);
+int SCPushContext2(SConnection * pCon, commandContext cc);
+int SCPopContext(SConnection * pCon);
+commandContext SCGetContext(SConnection * pCon);
+/******************************** Store ************************************/
+typedef struct SCStore SCStore;
+
+SCStore *SCSave(SConnection * pCon, SCStore * oldStore);
+/* save a connection and its context for later use. */
+
+SConnection *SCLoad(SCStore * conStore);
+/* check con and return SConnection if still valid or a dummy connection otherwise. */
+
+SConnection *SCStorePush(SCStore * conStore);
+/* load connection and push stored context. Must be paired with an SCStorePop command */
+
+void SCStorePop(SCStore * conStore);
+/* pop context */
+
+int SCStoreConnected(SCStore * conStore);
+/* check if a stored connection is not closed */
+
+void SCStoreFree(SCStore * conStore);
+/* free an SCStore */
+
+void KillFreeConnections(void);
/************************* CallBack *********************************** */
- int SCRegister(SConnection *pCon, SicsInterp *pSics,
- void *pInter, long lID);
- int SCUnregister(SConnection *pCon, void *pInter);
+int SCRegister(SConnection * pCon, SicsInterp * pSics,
+ void *pInter, long lID);
+int SCUnregister(SConnection * pCon, void *pInter);
/**
* delete a callback with the given ID
*/
- int SCUnregisterID(SConnection *pCon, long ID);
+int SCUnregisterID(SConnection * pCon, long ID);
/**
* retrieve the ID of a callback on the callback interface
* given in pData. This, together with SCUnregisterID allows to
* ceanly remove all callbacks on a connection
* returns -1 if no ID can be found.
*/
- long SCgetCallbackID(SConnection *pCon, void *pData);
-/******************************* Error **************************************/
- void SCSetInterrupt(SConnection *self, int eCode);
- int SCGetInterrupt(SConnection *self);
-/****************************** Macro ***************************************/
- int SCinMacro(SConnection *pCon);
- int SCsetMacro(SConnection *pCon, int iMode);
-/************************** parameters changed ? **************************/
- void SCparChange(SConnection *pCon);
-/* *************************** Info *************************************** */
- int SCGetRights(SConnection *self);
- int SCSetRights(SConnection *pCon, int iNew);
- int SCMatchRights(SConnection *pCon, int iCode);
- int SCGetOutClass(SConnection *self);
- int SCGetGrab(SConnection *pCon);
- int SCActive(SConnection *pCon);
-/********************* simulation mode ************************************/
- void SCSetSimMode(SConnection *pCon, int value);
- int SCinSimMode(SConnection *pCon);
-/* **************************** Invocation ******************************** */
- int SCInvoke(SConnection *self,SicsInterp *pInter,char *pCommand);
-
-/*************************** User Command **********************************/
- int ConfigCon(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
- int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
-/******************************** Store ************************************/
-typedef struct SCStore SCStore;
-
-SCStore *SCSave(SConnection *pCon, SCStore *oldStore);
-/* save a connection and its context for later use. */
-
-SConnection *SCLoad(SCStore *conStore);
-/* check con and return SConnection if still valid or a dummy connection otherwise. */
-
-SConnection *SCStorePush(SCStore *conStore);
-/* load connection and push stored context. Must be paired with an SCStorePop command */
-
-void SCStorePop(SCStore *conStore);
-/* pop context */
-
-int SCStoreConnected(SCStore *conStore);
-/* check if a stored connection is not closed */
-
-void SCStoreFree(SCStore *conStore);
-/* free an SCStore */
-
-void KillFreeConnections(void);
-
-/*------------------------------------------------------------------------*/
-int SCVerifyConnection(SConnection *self);
-void SCWriteToLogFiles(SConnection *self, char *buffer);
-int SCDoSockWrite(SConnection *self, char *buffer);
-int SCWriteInContext(SConnection *pCon, char *buffer, int code, commandContext cc);
-
-long SCTagContext(SConnection *self, char *tagName);
-long SCAdvanceContext(SConnection *self, char *tagName);
-int SCPushContext(SConnection *pCon, int ID, char *deviceID);
-int SCPushContext2(SConnection *pCon, commandContext cc);
-int SCPopContext(SConnection *pCon);
-commandContext SCGetContext(SConnection *pCon);
-#endif
-
+long SCgetCallbackID(SConnection * pCon, void *pData);
+#endif
diff --git a/costa.c b/costa.c
index 3153f066..875d80d5 100644
--- a/costa.c
+++ b/costa.c
@@ -45,148 +45,145 @@
#include "costa.h"
#include "costa.i"
-
+
/*-------------------------------------------------------------------------*/
- pCosta CreateCommandStack(void)
- {
- pCosta pNew = NULL;
-
- pNew = (pCosta)malloc(sizeof(Costa));
- if(!pNew)
- {
- return NULL;
- }
- memset(pNew,0,sizeof(Costa));
- pNew->iList = LLDcreate(sizeof(char *));
- if(pNew->iList < 0)
- {
- free(pNew);
- return NULL;
- }
- pNew->iCount = 0;
- pNew->iMaxSize = INT_MAX;
- return pNew;
- }
-/*-------------------------------------------------------------------------*/
- void DeleteCommandStack(pCosta self)
- {
- int iRet;
- char *pPtr;
-
- assert(self);
-
- iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- pPtr = NULL;
- LLDnodeDataTo(self->iList,&pPtr);
- if(pPtr)
- {
- free(pPtr);
- }
- iRet = LLDnodePtr2Next(self->iList);
- }
- LLDdelete(self->iList);
- free(self);
+pCosta CreateCommandStack(void)
+{
+ pCosta pNew = NULL;
+
+ pNew = (pCosta) malloc(sizeof(Costa));
+ if (!pNew) {
+ return NULL;
}
-/*--------------------------------------------------------------------------*/
- int SetCommandStackMaxSize(pCosta self, int iNew)
- {
- assert(self);
-
- if(iNew > 0)
- {
- self->iMaxSize = iNew;
- return 1;
+ memset(pNew, 0, sizeof(Costa));
+ pNew->iList = LLDcreate(sizeof(char *));
+ if (pNew->iList < 0) {
+ free(pNew);
+ return NULL;
+ }
+ pNew->iCount = 0;
+ pNew->iMaxSize = INT_MAX;
+ return pNew;
+}
+
+/*-------------------------------------------------------------------------*/
+void DeleteCommandStack(pCosta self)
+{
+ int iRet;
+ char *pPtr;
+
+ assert(self);
+
+ iRet = LLDnodePtr2First(self->iList);
+ while (iRet != 0) {
+ pPtr = NULL;
+ LLDnodeDataTo(self->iList, &pPtr);
+ if (pPtr) {
+ free(pPtr);
}
- else
- {
- return 0;
- }
- }
-/*--------------------------------------------------------------------------*/
- int CostaTop(pCosta self, char *pCommand)
- {
- char *pPtr = NULL;
- int iRet, iRes = 1;
-
- assert(self);
-
- /* check Size */
- if(self->iCount >= self->iMaxSize)
- {
- return 0;
- }
-
- /* do not want 0 commands */
- if(strlen(pCommand) < 1)
- {
- return 1;
- }
-
- pPtr = strdup(pCommand);
- iRet = LLDnodeAppendFrom(self->iList,&pPtr);
- if(iRet < 0)
- {
- iRes = 0;
- }
- self->iCount++;
- return iRes;
- }
-/*--------------------------------------------------------------------------*/
- int CostaBottom(pCosta self, char *pCommand)
- {
- char *pPtr = NULL;
- int iRet, iRes = 1;
- assert(self);
+ iRet = LLDnodePtr2Next(self->iList);
+ }
+ LLDdelete(self->iList);
+ free(self);
+}
- /* do not want 0 commands */
- if(strlen(pCommand) < 1)
- {
- return 1;
- }
-
- pPtr = strdup(pCommand);
- iRet = LLDnodePrependFrom(self->iList,&pPtr);
- if(iRet < 0)
- {
- iRes = 0;
- }
- self->iCount++;
- return iRes;
- }
/*--------------------------------------------------------------------------*/
- int CostaPop(pCosta self, char **pBuf)
- {
- char *pPtr = NULL;
- int iRet;
+int SetCommandStackMaxSize(pCosta self, int iNew)
+{
+ assert(self);
- assert(self);
- iRet = LLDnodePtr2First(self->iList);
- if(iRet != 0)
- {
- LLDnodeDataTo(self->iList,&pPtr);
- *pBuf = pPtr;
- LLDnodeDelete(self->iList);
- self->iCount--;
- return 1;
- }
- *pBuf = NULL;
+ if (iNew > 0) {
+ self->iMaxSize = iNew;
+ return 1;
+ } else {
return 0;
- }
-/*--------------------------------------------------------------------------*/
- void CostaLock(pCosta self)
- {
- self->iLock = 1;
}
+}
+
/*--------------------------------------------------------------------------*/
- void CostaUnlock(pCosta self)
- {
- self->iLock = 0;
+int CostaTop(pCosta self, char *pCommand)
+{
+ char *pPtr = NULL;
+ int iRet, iRes = 1;
+
+ assert(self);
+
+ /* check for lock */
+ if (self->iLock) {
+ return 0;
}
-/*--------------------------------------------------------------------------*/
- int CostaLocked(pCosta self)
- {
- return self->iLock;
+ /* check Size */
+ if (self->iCount >= self->iMaxSize) {
+ return 0;
}
+ /* do not want 0 commands */
+ if (strlen(pCommand) < 1) {
+ return 1;
+ }
+
+ pPtr = strdup(pCommand);
+ iRet = LLDnodeAppendFrom(self->iList, &pPtr);
+ if (iRet < 0) {
+ iRes = 0;
+ }
+ self->iCount++;
+ return iRes;
+}
+
+/*--------------------------------------------------------------------------*/
+int CostaBottom(pCosta self, char *pCommand)
+{
+ char *pPtr = NULL;
+ int iRet, iRes = 1;
+ assert(self);
+
+ /* check for lock */
+ if (self->iLock) {
+ return 0;
+ }
+
+ /* do not want 0 commands */
+ if (strlen(pCommand) < 1) {
+ return 1;
+ }
+
+ pPtr = strdup(pCommand);
+ iRet = LLDnodePrependFrom(self->iList, &pPtr);
+ if (iRet < 0) {
+ iRes = 0;
+ }
+ self->iCount++;
+ return iRes;
+}
+
+/*--------------------------------------------------------------------------*/
+int CostaPop(pCosta self, char **pBuf)
+{
+ char *pPtr = NULL;
+ int iRet;
+
+ assert(self);
+ iRet = LLDnodePtr2First(self->iList);
+ if (iRet != 0) {
+ LLDnodeDataTo(self->iList, &pPtr);
+ *pBuf = pPtr;
+ LLDnodeDelete(self->iList);
+ self->iCount--;
+ return 1;
+ }
+ *pBuf = NULL;
+ return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+void CostaLock(pCosta self)
+{
+ self->iLock = 1;
+}
+
+/*--------------------------------------------------------------------------*/
+void CostaUnlock(pCosta self)
+{
+ self->iLock = 0;
+}
diff --git a/costa.h b/costa.h
index 114d86b4..5703b210 100644
--- a/costa.h
+++ b/costa.h
@@ -12,19 +12,18 @@
#ifndef SICSCOSTA
#define SICSCOSTA
- typedef struct __costa *pCosta;
+typedef struct __costa *pCosta;
/*----------------------------- live & death ----------------------------*/
- pCosta CreateCommandStack(void);
- void DeleteCommandStack(pCosta self);
- int SetCommandStackMaxSize(pCosta self, int iNewSize);
+pCosta CreateCommandStack(void);
+void DeleteCommandStack(pCosta self);
+int SetCommandStackMaxSize(pCosta self, int iNewSize);
/*----------------------------------------------------------------------*/
- int CostaTop(pCosta self, char *pCommand);
- int CostaBottom(pCosta self, char *pCommand);
- int CostaPop(pCosta self,char **pPtr);
+int CostaTop(pCosta self, char *pCommand);
+int CostaBottom(pCosta self, char *pCommand);
+int CostaPop(pCosta self, char **pPtr);
/*----------------------------------------------------------------------*/
- void CostaLock(pCosta self);
- void CostaUnlock(pCosta self);
- int CostaLocked(pCosta self);
+void CostaLock(pCosta self);
+void CostaUnlock(pCosta self);
#endif
diff --git a/countdriv.c b/countdriv.c
index 43c8b8be..e9a3d6fa 100644
--- a/countdriv.c
+++ b/countdriv.c
@@ -45,56 +45,50 @@
#include "countdriv.h"
/*-------------------------------------------------------------------------*/
- pCounterDriver CreateCounterDriver(char *name, char *type)
- {
- pCounterDriver pRes = NULL;
-
- pRes = (pCounterDriver)malloc(sizeof(CounterDriver));
- if(!pRes)
- {
- return NULL;
- }
- memset(pRes,0,sizeof(CounterDriver));
-
- pRes->name = strdup(name);
- pRes->type = strdup(type);
- pRes->eMode = eTimer;
- pRes->fPreset = 1000.;
- pRes->fTime = 0.;
- pRes->iNoOfMonitors = 0;
- pRes->iControlMonitor = 0;
- pRes->iPause = 0;
- pRes->Start = NULL;
- pRes->GetStatus = NULL;
- pRes->ReadValues = NULL;
- pRes->GetError = NULL;
- pRes->TryAndFixIt = NULL;
- pRes->Halt = NULL;
- pRes->pData = NULL;
- pRes->Pause = NULL;
- pRes->Continue = NULL;
-
- return pRes;
- }
-/*-------------------------------------------------------------------------*/
- void DeleteCounterDriver(pCounterDriver self)
- {
- assert(self);
- if(self->name)
- {
- free(self->name);
- }
- if(self->type)
- {
- free(self->type);
- }
- if(self->pData)
- {
- if(self->KillPrivate != NULL)
- {
- self->KillPrivate(self);
- }
- }
- free(self);
- }
+pCounterDriver CreateCounterDriver(char *name, char *type)
+{
+ pCounterDriver pRes = NULL;
+ pRes = (pCounterDriver) malloc(sizeof(CounterDriver));
+ if (!pRes) {
+ return NULL;
+ }
+ memset(pRes, 0, sizeof(CounterDriver));
+
+ pRes->name = strdup(name);
+ pRes->type = strdup(type);
+ pRes->eMode = eTimer;
+ pRes->fPreset = 1000.;
+ pRes->fTime = 0.;
+ pRes->iNoOfMonitors = 0;
+ pRes->iPause = 0;
+ pRes->Start = NULL;
+ pRes->GetStatus = NULL;
+ pRes->ReadValues = NULL;
+ pRes->GetError = NULL;
+ pRes->TryAndFixIt = NULL;
+ pRes->Halt = NULL;
+ pRes->pData = NULL;
+ pRes->Pause = NULL;
+ pRes->Continue = NULL;
+
+ return pRes;
+}
+
+/*-------------------------------------------------------------------------*/
+void DeleteCounterDriver(pCounterDriver self)
+{
+ assert(self);
+ if (self->name) {
+ free(self->name);
+ }
+ if (self->type) {
+ free(self->type);
+ }
+ if (self->pData) {
+ if (self->KillPrivate != NULL) {
+ self->KillPrivate(self);
+ }
+ }
+ free(self);
+}
diff --git a/countdriv.h b/countdriv.h
index e87b27a6..adf4344b 100644
--- a/countdriv.h
+++ b/countdriv.h
@@ -22,77 +22,74 @@
#define COTERM 0
#define COREDO 1
-#define MAXCOUNT 9 /* No of monitors + actual counter */
-
+#define MAXCOUNT 9 /* No of monitors + actual counter */
-/* Parameter codes for the Set/Get pair of routines */
+
+/* Parameter codes for the Set/Get pair of routines */
/*-------- threshold */
-#define PARTHRESHOLD 1
+#define PARTHRESHOLD 1
/* counter driver additional error codes*/
#define UNKNOWNPAR -5000
#define BADCOUNTER -5001
- typedef struct __COUNTER {
- /* variables */
- char *name;
- char *type;
- CounterMode eMode;
- float fPreset;
- float fLastCurrent;
- float fTime;
- int iNoOfMonitors;
- int iControlMonitor;
- long lCounts[MAXCOUNT];
- int iPause;
- int iErrorCode;
- /* functions */
- int (*GetStatus)(struct __COUNTER *self, float *fControl);
- int (*Start)(struct __COUNTER *self);
- int (*Pause)(struct __COUNTER *self);
- int (*Continue)(struct __COUNTER *self);
- int (*Halt)(struct __COUNTER *self);
- int (*ReadValues)(struct __COUNTER *self);
- int (*GetError)(struct __COUNTER *self, int *iCode,
- char *error, int iErrLen);
- int (*TryAndFixIt)(struct __COUNTER *self, int iCode);
- int (*Set)(struct __COUNTER *self,char *name,
- int iCter, float fVal);
- int (*Get)(struct __COUNTER *self,char *name,
- int iCter, float *fVal);
- int (*Send)(struct __COUNTER *self, char *pText,
- char *pReply, int iReplyLen);
- void (*KillPrivate)(struct __COUNTER *self);
- void *pData; /* counter specific data goes here, ONLY for
- internal driver use!
+typedef struct __COUNTER {
+ /* variables */
+ char *name;
+ char *type;
+ CounterMode eMode;
+ float fPreset;
+ float fLastCurrent;
+ float fTime;
+ int iNoOfMonitors;
+ long lCounts[MAXCOUNT];
+ int iPause;
+ int iErrorCode;
+ /* functions */
+ int (*GetStatus) (struct __COUNTER * self, float *fControl);
+ int (*Start) (struct __COUNTER * self);
+ int (*Pause) (struct __COUNTER * self);
+ int (*Continue) (struct __COUNTER * self);
+ int (*Halt) (struct __COUNTER * self);
+ int (*ReadValues) (struct __COUNTER * self);
+ int (*GetError) (struct __COUNTER * self, int *iCode,
+ char *error, int iErrLen);
+ int (*TryAndFixIt) (struct __COUNTER * self, int iCode);
+ int (*Set) (struct __COUNTER * self, char *name, int iCter, float fVal);
+ int (*Get) (struct __COUNTER * self, char *name, int iCter, float *fVal);
+ int (*Send) (struct __COUNTER * self, char *pText,
+ char *pReply, int iReplyLen);
+ void (*KillPrivate) (struct __COUNTER * self);
+ void *pData; /* counter specific data goes here, ONLY for
+ internal driver use!
*/
- } CounterDriver, *pCounterDriver;
-
+} CounterDriver, *pCounterDriver;
+
/*------------------------------------------------------------------------*/
/* countdriv.c */
- pCounterDriver CreateCounterDriver(char *name, char *type);
- void DeleteCounterDriver(pCounterDriver self);
-
+pCounterDriver CreateCounterDriver(char *name, char *type);
+void DeleteCounterDriver(pCounterDriver self);
+
/* PSI EL737 Counter */
- pCounterDriver NewEL737Counter(char *name, char *host, int iPort,
- int iChannel);
- void KillEL737Counter(pCounterDriver self);
-
+pCounterDriver NewEL737Counter(char *name, char *host, int iPort,
+ int iChannel);
+void KillEL737Counter(pCounterDriver self);
+
/* PSI Simulation counter, if you have no hardware */
/* simcter.c */
- pCounterDriver NewSIMCounter(char *name, float fVal);
- void KillSIMCounter(pCounterDriver self);
-
+pCounterDriver NewSIMCounter(char *name, float fVal);
+void KillSIMCounter(pCounterDriver self);
+
/*
* McStas simulation counter driver
* file: mcstascounter.c
*/
- pCounterDriver NewMcStasCounter(char *name);
+pCounterDriver NewMcStasCounter(char *name);
/*
* for regression testing
* file: regresscter.c
*/
- pCounterDriver NewRegressCounter(char *name);
+pCounterDriver NewRegressCounter(char *name);
#endif
diff --git a/counter.c b/counter.c
index 4b0dfb0b..c6b6ab5b 100644
--- a/counter.c
+++ b/counter.c
@@ -53,1123 +53,1094 @@
#include "site.h"
/*-------------------------------------------------------------------------*/
/*
- The monitor callback data structure
- */
- typedef struct {
- float fPreset;
- float fCurrent;
- char *pName;
- } MonEvent, *pMonEvent;
+ The monitor callback data structure
+ */
+typedef struct {
+ float fPreset;
+ float fCurrent;
+ char *pName;
+} MonEvent, *pMonEvent;
/*--------------------------------------------------------------------------*/
- static int Halt(void *pData)
- {
- pCounter self = NULL;
-
- assert(pData);
- self = (pCounter)pData;
-
- return self->pDriv->Halt(self->pDriv);
- }
+static int Halt(void *pData)
+{
+ pCounter self = NULL;
+
+ assert(pData);
+ self = (pCounter) pData;
+
+ return self->pDriv->Halt(self->pDriv);
+}
+
/*--------------------------------------------------------------------------*/
- static void SetCountParameters(void *pData, float fPreset, CounterMode eMode)
- {
- pCounter self = NULL;
-
- assert(pData);
- self = (pCounter)pData;
-
- self->pDriv->fPreset = fPreset;
- self->pDriv->eMode = eMode;
- }
+static void SetCountParameters(void *pData, float fPreset,
+ CounterMode eMode)
+{
+ pCounter self = NULL;
+
+ assert(pData);
+ self = (pCounter) pData;
+
+ SetCounterPreset(self, fPreset);
+ SetCounterMode(self, eMode);
+}
+
/*-----------------------------------------------------------------------*/
- static int StartCount(void *pData, SConnection *pCon)
- {
- pCounter self;
- char pBueffel[132];
- char pError[80];
- int iRet;
- int i;
- int iErr;
- time_t tX;
-
- self = (pCounter)pData;
- assert(self);
+static int StartCount(void *pData, SConnection * pCon)
+{
+ pCounter self;
+ char pBueffel[132];
+ char pError[80];
+ int iRet;
+ int i;
+ int iErr;
+ time_t tX;
- /* try at least three times to do it */
- for(i = 0; i < 3; i++)
- {
- iRet = self->pDriv->Start(self->pDriv);
- if(iRet == OKOK)
- {
- self->isUpToDate = 0;
- self->badStatusCount = 0;
- self->tStart = time(&tX);
- InvokeCallBack(self->pCall,COUNTSTART,pCon);
- return iRet;
- }
- else
- {
- iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
- sprintf(pBueffel,"WARNING: %s ",pError);
- SCWrite(pCon,pBueffel,eError);
- iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
- if(iRet == COTERM)
- {
- SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
- SCSetInterrupt(pCon,eAbortBatch);
- return HWFault;
- }
- }
+ self = (pCounter) pData;
+ assert(self);
+
+ if (!GetCountLock(self->pCountInt, pCon)) {
+ return 0;
+ }
+
+ /* try at least three times to do it */
+ for (i = 0; i < 3; i++) {
+ iRet = self->pDriv->Start(self->pDriv);
+ if (iRet == OKOK) {
+ self->isUpToDate = 0;
+ self->badStatusCount = 0;
+ self->tStart = time(&tX);
+ InvokeCallBack(self->pCall, COUNTSTART, pCon);
+ return iRet;
+ } else {
+ iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
+ sprintf(pBueffel, "WARNING: %s ", pError);
+ SCWrite(pCon, pBueffel, eLog);
+ iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
+ if (iRet == COTERM) {
+ SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting",
+ eError);
+ SCSetInterrupt(pCon, eAbortBatch);
+ ReleaseCountLock(self->pCountInt);
+ return HWFault;
}
- SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
- SCSetInterrupt(pCon,eAbortBatch);
- return HWFault;
- }
+ }
+ }
+ SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting", eError);
+ SCSetInterrupt(pCon, eAbortBatch);
+ ReleaseCountLock(self->pCountInt);
+ return HWFault;
+}
+
/*-----------------------------------------------------------------------*/
- static int PauseCount(void *pData, SConnection *pCon)
- {
- pCounter self;
- char pBueffel[132];
- char pError[80];
- int iRet;
- int i;
- int iErr;
-
- self = (pCounter)pData;
- assert(self);
+static int PauseCount(void *pData, SConnection * pCon)
+{
+ pCounter self;
+ char pBueffel[132];
+ char pError[80];
+ int iRet;
+ int i;
+ int iErr;
- /* try at least three times to do it */
- for(i = 0; i < 3; i++)
- {
- iRet = self->pDriv->Pause(self->pDriv);
- if(iRet == OKOK)
- {
- self->isUpToDate = 0;
- return iRet;
- }
- else
- {
- iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
- sprintf(pBueffel,"WARNING: %s ",pError);
- SCWrite(pCon,pBueffel,eError);
- iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
- if(iRet == COTERM)
- {
- SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",
- eError);
- SCSetInterrupt(pCon,eAbortBatch);
- return HWFault;
- }
- }
+ self = (pCounter) pData;
+ assert(self);
+
+ /* try at least three times to do it */
+ for (i = 0; i < 3; i++) {
+ iRet = self->pDriv->Pause(self->pDriv);
+ if (iRet == OKOK) {
+ self->isUpToDate = 0;
+ return iRet;
+ } else {
+ iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
+ sprintf(pBueffel, "WARNING: %s ", pError);
+ SCWrite(pCon, pBueffel, eError);
+ iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
+ if (iRet == COTERM) {
+ SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting",
+ eError);
+ SCSetInterrupt(pCon, eAbortBatch);
+ return HWFault;
}
- SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
- SCSetInterrupt(pCon,eAbortBatch);
- return HWFault;
- }
+ }
+ }
+ SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting", eError);
+ SCSetInterrupt(pCon, eAbortBatch);
+ return HWFault;
+}
+
/*-----------------------------------------------------------------------*/
- static int ContinueCount(void *pData, SConnection *pCon)
- {
- pCounter self;
- char pBueffel[132];
- char pError[80];
- int iRet;
- int i;
- int iErr;
-
- self = (pCounter)pData;
- assert(self);
+static int ContinueCount(void *pData, SConnection * pCon)
+{
+ pCounter self;
+ char pBueffel[132];
+ char pError[80];
+ int iRet;
+ int i;
+ int iErr;
- /* try at least three times to do it */
- for(i = 0; i < 3; i++)
- {
- iRet = self->pDriv->Continue(self->pDriv);
- if(iRet == OKOK)
- {
- self->isUpToDate = 0;
- return iRet;
- }
- else
- {
- iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
- sprintf(pBueffel,"WARNING: %s ",pError);
- SCWrite(pCon,pBueffel,eError);
- iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
- if(iRet == COTERM)
- {
- SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
- SCSetInterrupt(pCon,eAbortBatch);
- return HWFault;
- }
- }
- }
- SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
- SCSetInterrupt(pCon,eAbortBatch);
- return HWFault;
- }
-/*--------------------------------------------------------------------------*/
- static int CheckCountStatus(void *pData, SConnection *pCon)
- {
- pCounter self = NULL;
- int i, iRet;
- int eCt;
- char pError[80], pBueffel[132];
- int iErr;
- float fControl;
- MonEvent sMon;
-
- self = (pCounter)pData;
- assert(self);
- assert(pCon);
-
- eCt = self->pDriv->GetStatus(self->pDriv,&fControl);
- if(eCt == HWFault)
- {
- self->badStatusCount++;
- iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
- sprintf(pBueffel,"WARNING: %s ",pError);
- SCWrite(pCon,pBueffel,eError);
- iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
- if(iRet == COTERM || self->badStatusCount > 3)
- {
- SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
- SCSetInterrupt(pCon,eAbortBatch);
- InvokeCallBack(self->pCall,COUNTEND,NULL);
- return eCt;
- }
- else
- {
- return HWBusy;
- }
- }
+ self = (pCounter) pData;
+ assert(self);
- /*
- handle count parameters and notify listeners on progress
- */
- sMon.fCurrent = fControl;
- sMon.fPreset = self->pDriv->fPreset;
- sMon.pName = self->name;
- self->badStatusCount = 0; /* clear: we managed to read OK */
- if(self->iCallbackCounter > 20)
- {
- InvokeCallBack(self->pCall,MONITOR,&sMon);
- self->iCallbackCounter = 0;
- }
- else
- {
- self->iCallbackCounter++;
+ /* try at least three times to do it */
+ for (i = 0; i < 3; i++) {
+ iRet = self->pDriv->Continue(self->pDriv);
+ if (iRet == OKOK) {
+ self->isUpToDate = 0;
+ return iRet;
+ } else {
+ iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
+ sprintf(pBueffel, "WARNING: %s ", pError);
+ SCWrite(pCon, pBueffel, eError);
+ iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
+ if (iRet == COTERM) {
+ SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting",
+ eError);
+ SCSetInterrupt(pCon, eAbortBatch);
+ return HWFault;
}
- self->pDriv->fLastCurrent = fControl;
+ }
+ }
+ SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting", eError);
+ SCSetInterrupt(pCon, eAbortBatch);
+ return HWFault;
+}
- /*
- notification on finish
- */
- if(eCt == HWIdle)
- {
- InvokeCallBack(self->pCall,COUNTEND,NULL);
- }
+/*--------------------------------------------------------------------------*/
+static int CheckCountStatus(void *pData, SConnection * pCon)
+{
+ pCounter self = NULL;
+ int i, iRet;
+ int eCt;
+ char pError[80], pBueffel[132];
+ int iErr;
+ float fControl, rate;
+ MonEvent sMon;
+
+ self = (pCounter) pData;
+ assert(self);
+ assert(pCon);
+
+ eCt = self->pDriv->GetStatus(self->pDriv, &fControl);
+ if (eCt == HWFault) {
+ self->badStatusCount++;
+ iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
+ sprintf(pBueffel, "WARNING: %s ", pError);
+ SCWrite(pCon, pBueffel, eLog);
+ iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
+ if (iRet == COTERM || self->badStatusCount > 3) {
+ SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting", eError);
+ SCSetInterrupt(pCon, eAbortBatch);
+ InvokeCallBack(self->pCall, COUNTEND, NULL);
+ ReleaseCountLock(self->pCountInt);
return eCt;
- }
-/*------------------------------------------------------------------------*/
- static int SaveCounterStatus(void *pData, char *name, FILE *fd)
- {
- pCounter self = NULL;
- char pBueffel[512];
-
- assert(pData);
- assert(fd);
-
- self = (pCounter)pData;
-
- sprintf(pBueffel,"# Counter %s\n",name);
- fputs(pBueffel,fd);
- sprintf(pBueffel,"%s SetPreset %f\n",name, self->pDriv->fPreset);
- fputs(pBueffel,fd);
- if(self->pDriv->eMode == eTimer)
- {
- sprintf(pBueffel,"%s SetMode Timer\n",name);
+ } else {
+ return HWBusy;
}
- else
- {
- sprintf(pBueffel,"%s SetMode Monitor\n",name);
- }
- fputs(pBueffel,fd);
-
- return 1;
- }
-/*------------------------------------------------------------------------*/
- static int TransferData(void *pData, SConnection *pCon)
- {
- pCounter self = NULL;
- int i, iRet;
- char pError[80];
- char pBueffel[132];
- int iCode;
-
- self = (pCounter)pData;
- assert(self);
- assert(pCon);
+ }
- /* try three times */
- for(i = 0; i < 3; i++)
- {
- iRet = self->pDriv->ReadValues(self->pDriv);
- if(iRet == OKOK)
- {
- self->isUpToDate = 1;
- return OKOK;
- }
- else
- {
- self->pDriv->GetError(self->pDriv,&iCode,pError,79);
- sprintf(pBueffel,"WARNING: %s",pError);
- SCWrite(pCon,pBueffel,eError);
- iRet = self->pDriv->TryAndFixIt(self->pDriv,iCode);
- if(iRet == COTERM)
- {
- SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
- SCSetInterrupt(pCon,eAbortBatch);
- return HWFault;
- }
- }
- }
- SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
- SCSetInterrupt(pCon,eAbortBatch);
- return HWFault;
+ if(self->pDriv->fTime > .0){
+ rate = (float)(self->pDriv->lCounts[1])/self->pDriv->fTime;
+ if(rate > 10000){
+ SCWrite(pCon,"WARNING: Your control monitor is running into dead time",
+ eWarning);
+ }
}
-/*------------------------------------------------------------------------*/
- static void *CounterGetInterface(void *pData, int iID)
- {
- pCounter self = NULL;
-
- self = (pCounter)pData;
- assert(self);
- if(iID == COUNTID)
- {
- return self->pCountInt;
- }
- else if(iID == CALLBACKINTERFACE)
- {
- return self->pCall;
- }
- return NULL;
+ /*
+ handle count parameters and notify listeners on progress
+ */
+ sMon.fCurrent = fControl;
+ sMon.fPreset = self->pDriv->fPreset;
+ sMon.pName = self->name;
+ self->badStatusCount = 0; /* clear: we managed to read OK */
+ if (self->iCallbackCounter > 20) {
+ InvokeCallBack(self->pCall, MONITOR, &sMon);
+ tracePar(self->name,"control:%f", fControl);
+ self->iCallbackCounter = 0;
+ } else {
+ self->iCallbackCounter++;
}
-/*------------------------------------------------------------------------*/
- pCounter CreateCounter(char *name, pCounterDriver pDriv)
- {
- pCounter pRes = NULL;
-
- assert(pDriv);
-
- pRes = (pCounter)malloc(sizeof(Counter));
- if(!pRes)
- {
- return NULL;
- }
- pRes->pDes = CreateDescriptor("SingleCounter");
- if(!pRes->pDes)
- {
- free(pRes);
- return NULL;
- }
- /* initialize Descriptor functions */
- pRes->pDes->GetInterface = CounterGetInterface;
- pRes->pDes->SaveStatus = SaveCounterStatus;
+ self->pDriv->fLastCurrent = fControl;
- /* initialise countable interface */
- pRes->pCountInt = CreateCountableInterface();
- if(!pRes->pCountInt)
- {
- DeleteDescriptor(pRes->pDes);
- free(pRes);
- return NULL;
- }
- pRes->pCountInt->SetCountParameters = SetCountParameters;
- pRes->pCountInt->StartCount = StartCount;
- pRes->pCountInt->CheckCountStatus = CheckCountStatus;
- pRes->pCountInt->TransferData = TransferData;
- pRes->pCountInt->Halt = Halt;
- pRes->pCountInt->Pause = PauseCount;
- pRes->pCountInt->Continue = ContinueCount;
- pRes->iCallbackCounter = 20;
-
- pRes->pCall = CreateCallBackInterface();
-
- pRes->pDriv = pDriv;
- pRes->isUpToDate = 1;
- pRes->iExponent = 0;
- pRes->name = strdup(name);
- return pRes;
+ /*
+ notification on finish
+ */
+ if (eCt == HWIdle) {
+ self->isUpToDate = 0;
+ InvokeCallBack(self->pCall, COUNTEND, NULL);
+ ReleaseCountLock(self->pCountInt);
}
+ return eCt;
+}
+
+/*------------------------------------------------------------------------*/
+static int SaveCounterStatus(void *pData, char *name, FILE * fd)
+{
+ pCounter self = NULL;
+
+ assert(pData);
+ assert(fd);
+
+ self = (pCounter) pData;
+
+ fprintf(fd, "# Counter %s\n", name);
+ fprintf(fd, "%s SetPreset %f\n", name, self->pDriv->fPreset);
+ if (self->pDriv->eMode == eTimer) {
+ fprintf(fd, "%s SetMode Timer\n", name);
+ } else {
+ fprintf(fd, "%s SetMode Monitor\n", name);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------------*/
+static int TransferData(void *pData, SConnection * pCon)
+{
+ pCounter self = NULL;
+ int i, iRet;
+ char pError[80];
+ char pBueffel[132];
+ int iCode;
+
+ self = (pCounter) pData;
+ assert(self);
+ assert(pCon);
+
+ /* try three times */
+ for (i = 0; i < 3; i++) {
+ iRet = self->pDriv->ReadValues(self->pDriv);
+ if (iRet == OKOK) {
+ self->isUpToDate = 1;
+ return OKOK;
+ } else {
+ self->pDriv->GetError(self->pDriv, &iCode, pError, 79);
+ sprintf(pBueffel, "WARNING: %s", pError);
+ SCWrite(pCon, pBueffel, eError);
+ iRet = self->pDriv->TryAndFixIt(self->pDriv, iCode);
+ if (iRet == COTERM) {
+ SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting",
+ eError);
+ SCSetInterrupt(pCon, eAbortBatch);
+ return HWFault;
+ }
+ }
+ }
+ SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting", eError);
+ SCSetInterrupt(pCon, eAbortBatch);
+ return HWFault;
+}
+
+/*------------------------------------------------------------------------*/
+static void *CounterGetInterface(void *pData, int iID)
+{
+ pCounter self = NULL;
+
+ self = (pCounter) pData;
+ assert(self);
+ if (iID == COUNTID) {
+ return self->pCountInt;
+ } else if (iID == CALLBACKINTERFACE) {
+ return self->pCall;
+ }
+ return NULL;
+}
+
+
/*---------------------------------------------------------------------------*/
- void DeleteCounter(void *pData)
- {
- pCounter self = NULL;
-
- assert(pData);
- self = (pCounter)pData;
-
- if(self->pDes)
- {
- DeleteDescriptor(self->pDes);
- }
-
- if(self->pCountInt)
- {
- free(self->pCountInt);
- }
- if(self->pCall)
- {
- DeleteCallBackInterface(self->pCall);
- }
-
- if(self->name)
- {
- free(self->name);
- }
- if(self->pDriv)
- {
- DeleteCounterDriver(self->pDriv);
- }
- free(self);
+void DeleteCounter(void *pData)
+{
+ pCounter self = NULL;
+
+ assert(pData);
+ self = (pCounter) pData;
+
+ if (self->pDes) {
+ DeleteDescriptor(self->pDes);
}
+
+ if (self->pCountInt) {
+ free(self->pCountInt);
+ }
+ if (self->pCall) {
+ DeleteCallBackInterface(self->pCall);
+ }
+
+ if (self->name) {
+ free(self->name);
+ }
+ if (self->pDriv) {
+ DeleteCounterDriver(self->pDriv);
+ }
+ free(self);
+}
+
/*-------------------------------------------------------------------------*/
- int DoCount(pCounter self, float fPreset, SConnection *pCon,
- int iBlock)
- {
- int iRet;
- char pBueffel[132];
- Status eOld;
-
- assert(self);
-
- /* check authorisation */
- if(!SCMatchRights(pCon,usUser))
- {
- sprintf(pBueffel,"ERROR: you are not authorised to count");
- SCWrite(pCon, pBueffel, eError);
- return 0;
- }
-
- eOld = GetStatus();
- SetStatus(eCounting);
-
- /* set Preset */
- SetCounterPreset(self,fPreset);
-
- iRet = StartDevice(GetExecutor(),self->name,self->pDes,self,pCon,
- self->pDriv->fPreset);
- if(!iRet)
- {
- SetStatus(eOld);
- SCWrite(pCon,"Counting aborted",eStatus);
- return 0;
- }
-
- /* continue only if in blocking mode */
- if(!iBlock)
- {
- return 1;
- }
-
- /* wait forever until done or interrupted */
- iRet = Wait4Success(GetExecutor());
- if(iRet == DEVINT)
- {
- SCWrite(pCon,"Counting aborted due to Interrupt",eStatus);
- }
- else if(iRet == DEVERROR)
- {
- SCWrite(pCon,"Counting finished with Problems",eStatus);
- iRet = 1;
- }
- else
- {
- SCWrite(pCon,"Counting finished",eStatus);
- iRet = 1;
- }
- SetStatus(eOld);
- return iRet;
- }
-/*-----------------------------------------------------------------------*/
-
-/*-------------------------------------------------------------------------*/
+int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock)
+{
+ int iRet, level;
+ char pBueffel[132];
+ Status eOld;
- int MakeCounter(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pCounter pNew = NULL;
- pCounterDriver pDriv = NULL;
- float fFail = -1;
- int iRet;
- char pBueffel[256];
- pSite site = NULL;
+ assert(self);
- assert(pCon);
- assert(pSics);
+ /* check authorisation */
+ if (!SCMatchRights(pCon, usUser)) {
+ sprintf(pBueffel, "ERROR: you are not authorised to count");
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
- argtolower(argc,argv);
- if(argc < 3){
- SCWrite(pCon,"ERROR: insuficient number of arguments to MakeCounter",
- eError);
- return 0;
- }
- site = getSite();
- if(site != NULL){
- pDriv = site->CreateCounterDriver(pCon,argc,argv);
- }
+ eOld = GetStatus();
+ SetStatus(eCounting);
- /*
- test for simulation driver, which is for everybody
- */
- if(strcmp(argv[2],"sim") == 0){
- if(argc > 3){
- fFail = atof(argv[3]);
- pDriv = NewSIMCounter(argv[1],fFail);
- }
- }
+ /* set Preset */
+ SetCounterPreset(self, fPreset);
- /*
- * test for regression testing counter
- */
- if(strcmp(argv[2],"regress") == 0){
- pDriv = NewRegressCounter(argv[1]);
- }
+ if (iBlock == 0) {
+ level = RUNRUN;
+ } else {
+ level = RUNDRIVE;
+ }
+ iRet = StartDevice(GetExecutor(), self->name, self->pDes, self, pCon,
+ level, fPreset);
+ if (!iRet) {
+ SetStatus(eOld);
+ SCWrite(pCon, "Counting aborted", eError);
+ return 0;
+ }
- /*
- * test for McStas simulation counter driver
- */
- if(strcmp(argv[2],"mcstas") == 0){
- pDriv = NewMcStasCounter(argv[1]);
- }
-
- if(!pDriv)
- {
- sprintf(pBueffel,"ERROR: cannot create requested driver %s",
- argv[2]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
- /* create Counter and command */
- pNew = CreateCounter(argv[1],pDriv);
- if(!pNew)
- {
- sprintf(pBueffel,"ERROR: cannot create counter %s",
- argv[1]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- iRet = AddCommand(pSics,argv[1],CountAction,DeleteCounter,(void *)pNew);
- if(!iRet)
- {
- sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
+ /* continue only if in blocking mode, or from tas scan (iBlock == 2) */
+ if (iBlock != 1) {
return 1;
- }
+ }
+
+ /* wait forever until done or interrupted */
+ iRet = Wait4Success(GetExecutor());
+ if (iRet == DEVINT) {
+ SCWrite(pCon, "Counting aborted due to Interrupt", eError);
+ } else if (iRet == DEVERROR) {
+ SCWrite(pCon, "Counting finished with Problems", eError);
+ iRet = 1;
+ } else {
+ SCWrite(pCon, "Counting finished", eValue);
+ iRet = 1;
+ }
+ SetStatus(eOld);
+ return iRet;
+}
+/*-------------------------------------------------------------------------*/
+
+int MakeCounter(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pCounter pNew = NULL;
+ pCounterDriver pDriv = NULL;
+ float fFail = -1;
+ int iRet;
+ char pBueffel[256];
+ pSite site = NULL;
+
+ assert(pCon);
+ assert(pSics);
+
+ argtolower(argc, argv);
+ if (argc < 3) {
+ SCWrite(pCon, "ERROR: insuficient number of arguments to MakeCounter",
+ eError);
+ return 0;
+ }
+ site = getSite();
+ if (site != NULL) {
+ pDriv = site->CreateCounterDriver(pCon, argc, argv);
+ }
+
+ /*
+ test for simulation driver, which is for everybody
+ */
+ if (strcmp(argv[2], "sim") == 0) {
+ if (argc > 3) {
+ fFail = atof(argv[3]);
+ pDriv = NewSIMCounter(argv[1], fFail);
+ }
+ }
+
+ /*
+ * test for regression testing counter
+ */
+ if (strcmp(argv[2], "regress") == 0) {
+ pDriv = NewRegressCounter(argv[1]);
+ }
+
+ /*
+ * test for McStas simulation counter driver
+ */
+ if (strcmp(argv[2], "mcstas") == 0) {
+ pDriv = NewMcStasCounter(argv[1]);
+ }
+
+ if (!pDriv) {
+ snprintf(pBueffel,255, "ERROR: cannot create requested driver %s", argv[2]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+ /* create Counter and command */
+ pNew = CreateCounter(argv[1], pDriv);
+ if (!pNew) {
+ snprintf(pBueffel, 255,"ERROR: cannot create counter %s", argv[1]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ iRet =
+ AddCommand(pSics, argv[1], CountAction, DeleteCounter,
+ (void *) pNew);
+ if (!iRet) {
+ snprintf(pBueffel,255, "ERROR: duplicate command %s not created", argv[1]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ return 1;
+}
+
/* --------------------------------------------------------------------------*/
- int SetCounterMode(pCounter self, CounterMode eNew)
- {
- int i;
-
- assert(self);
- if(eNew == self->pDriv->eMode)
- {
- return 1;
- }
-
- if(eNew == eTimer)
- {
- for(i = 0; i < self->iExponent; i++)
- {
- self->pDriv->fPreset /= 10.;
- }
- }
- if(eNew == ePreset)
- {
- for(i = 0; i < self->iExponent; i++)
- {
- self->pDriv->fPreset *= 10.;
- }
- }
- self->pDriv->eMode = eNew;
+int SetCounterMode(pCounter self, CounterMode eNew)
+{
+ return self->setMode(self,eNew);
+}
+/*---------------------------------------------------------------------------*/
+static int SetCounterModeImpl(pCounter self, CounterMode eNew)
+{
+ int i;
+
+ assert(self);
+ if (eNew == self->pDriv->eMode) {
return 1;
}
-/*--------------------------------------------------------------------------*/
- CounterMode GetCounterMode(pCounter self)
- {
- assert(self);
- return self->pDriv->eMode;
+
+ if (eNew == eTimer) {
+ for (i = 0; i < self->iExponent; i++) {
+ self->pDriv->fPreset /= 10.;
+ }
+ tracePar(self->name,"mode:timer");
}
+ if (eNew == ePreset) {
+ for (i = 0; i < self->iExponent; i++) {
+ self->pDriv->fPreset *= 10.;
+ }
+ tracePar(self->name,"mode:monitor");
+ }
+ self->pDriv->eMode = eNew;
+ return 1;
+}
+/*-------------------------------------------------------------------------*/
+CounterMode GetCounterMode(pCounter self)
+{
+ return self->getMode(self);
+}
+/*--------------------------------------------------------------------------*/
+static CounterMode GetCounterModeImpl(pCounter self)
+{
+ assert(self);
+ return self->pDriv->eMode;
+}
/*------------------------------------------------------------------------*/
- int GetNMonitor(pCounter self)
- {
- assert(self);
- return self->pDriv->iNoOfMonitors;
- }
- int GetControlMonitor(pCounter self) {
- return self->pDriv->iControlMonitor;
- }
- int SetControlMonitor(pCounter self, int channel) {
- int maxchan = self->pDriv->iNoOfMonitors - 1;
- if (channel < 0 || channel > maxchan) {
- return 0;
- }
- self->pDriv->iControlMonitor = channel;
- return 1;
- }
+int GetNMonitor(pCounter self)
+{
+ return self->getNMonitor(self);
+}
+/*------------------------------------------------------------------------*/
+static int GetNMonitorImpl(pCounter self)
+{
+ assert(self);
+ return self->pDriv->iNoOfMonitors;
+}
+
#ifdef NONINTF
- extern float nintf(float f);
-#endif
-/*------------------------------------------------------------------------*/
- int SetCounterPreset(pCounter self, float fVal)
- {
- int i;
-
- assert(self);
-
- if(fVal < .0)
- {
- return 0;
- }
- if(GetCounterMode(self) == ePreset)
- {
- for(i = 0; i < self->iExponent;i++)
- {
- fVal *= 10.;
- }
- fVal = nintf(fVal);
- }
- self->pDriv->fPreset = fVal;
- return 1;
- }
+extern float nintf(float f);
+#endif
/*------------------------------------------------------------------------*/
- float GetCounterPreset(pCounter self)
- {
- int i;
- float fVal;
-
- assert(self);
-
- fVal = self->pDriv->fPreset;
- if(self->pDriv->eMode == ePreset)
- {
- for(i = 0; i < self->iExponent; i++)
- {
- fVal /= 10.;
- }
- }
- return fVal;
- }
-/*-----------------------------------------------------------------------*/
- long GetCounts(pCounter self, SConnection *pCon)
- {
- assert(self);
- if(!self->isUpToDate)
- {
- self->pCountInt->TransferData(self,pCon);
- }
- return self->pDriv->lCounts[self->pDriv->iControlMonitor];
- }
-/*------------------------------------------------------------------------*/
- long GetMonitor(pCounter self, int iNum, SConnection *pCon)
- {
- assert(self);
+int SetCounterPreset(pCounter self, float fVal)
+{
+ return self->setPreset(self,fVal);
+}
+/*------------------------------------------------------------------------*/
+static int SetCounterPresetImpl(pCounter self, float fVal)
+{
+ int i;
- if(!self->isUpToDate)
- {
- self->pCountInt->TransferData(self,pCon);
- }
- if( (iNum < 0) || (iNum >= self->pDriv->iNoOfMonitors) )
- {
- return -1L;
- }
- else
- {
- return self->pDriv->lCounts[iNum];
- }
- }
- /*-----------------------------------------------------------------------*/
- void SetMonitorValue(pCounter self, int index, long value)
- {
- assert(self);
-
- if(index >= 0 && index < self->pDriv->iNoOfMonitors)
- {
- self->pDriv->lCounts[index] = value;
- }
- }
-/*------------------------------------------------------------------------*/
- float GetCountTime(pCounter self,SConnection *pCon)
- {
- assert(self);
+ assert(self);
- if(!self->isUpToDate)
- {
- self->pCountInt->TransferData(self,pCon);
- }
- return self->pDriv->fTime;
+ if (fVal < .0) {
+ return 0;
}
-/*----------------------------------------------------------------------*/
- static int isAuthorised(SConnection *pCon, int iCode)
- {
- char pBueffel[132];
-
- if(!SCMatchRights(pCon,iCode))
- {
- sprintf(pBueffel,"ERROR: you are not authorised to count");
- SCWrite(pCon, pBueffel, eError);
- return 0;
+ if (GetCounterMode(self) == ePreset) {
+ for (i = 0; i < self->iExponent; i++) {
+ fVal *= 10.;
}
- return 1;
- }
+ fVal = nintf(fVal);
+ }
+ self->pDriv->fPreset = fVal;
+ tracePar(self->name,"preset:%f", fVal);
+
+ return 1;
+}
+/*------------------------------------------------------------------------*/
+float GetCounterPreset(pCounter self)
+{
+ return self->getPreset(self);
+}
+/*------------------------------------------------------------------------*/
+float GetControlValue(pCounter self)
+{
+ return self->getControlValue(self);
+}
+/*------------------------------------------------------------------------*/
+static float GetControlValueImpl(pCounter self)
+{
+ return self->pDriv->fLastCurrent;
+}
+/*------------------------------------------------------------------------*/
+static float GetCounterPresetImpl(pCounter self)
+{
+ int i;
+ float fVal;
+
+ assert(self);
+
+ fVal = self->pDriv->fPreset;
+ if (self->pDriv->eMode == ePreset) {
+ for (i = 0; i < self->iExponent; i++) {
+ fVal /= 10.;
+ }
+ }
+ return fVal;
+}
/*-----------------------------------------------------------------------*/
- static int CounterInterest(int iEvent, void *pEvent, void *pUser,
- commandContext cc)
- {
- SConnection *pCon = NULL;
- pMonEvent pMon = NULL;
- char pBueffel[512];
- int rights;
-
- if(iEvent != MONITOR)
- {
- return 0;
- }
-
- pCon = (SConnection *)pUser;
- pMon = (pMonEvent)pEvent;
- assert(pCon);
- assert(pMon);
- sprintf(pBueffel,"%s.CountStatus = %f %d",pMon->pName,pMon->fPreset,
- (int)nintf(pMon->fCurrent));
+long GetCounts(pCounter self, SConnection * pCon)
+{
+ return self->getCounts(self, pCon);
+}
+/*-----------------------------------------------------------------------*/
+static long GetCountsImpl(pCounter self, SConnection * pCon)
+{
+ assert(self);
+ if (!self->isUpToDate) {
+ self->pCountInt->TransferData(self, pCon);
+ }
+ return self->pDriv->lCounts[0];
+}
+/*------------------------------------------------------------------------*/
+long GetMonitor(pCounter self, int iNum, SConnection * pCon)
+{
+ return self->getMonitor(self, iNum, pCon);
+}
+/*------------------------------------------------------------------------*/
+static long GetMonitorImpl(pCounter self, int iNum, SConnection * pCon)
+{
+ assert(self);
+
+ if (!self->isUpToDate) {
+ self->pCountInt->TransferData(self, pCon);
+ }
+ if ((iNum < 0) || (iNum > self->pDriv->iNoOfMonitors)) {
+ return -1L;
+ } else {
+ return self->pDriv->lCounts[iNum];
+ }
+}
+/*-----------------------------------------------------------------------*/
+void SetMonitorValue(pCounter self, int index, long value)
+{
+ return self->setMonitor(self, index, value);
+}
+ /*-----------------------------------------------------------------------*/
+static void SetMonitorValueImpl(pCounter self, int index, long value)
+{
+ assert(self);
+
+ if (index >= 0 && index < self->pDriv->iNoOfMonitors) {
+ self->pDriv->lCounts[index] = value;
+ }
+}
+/*------------------------------------------------------------------------*/
+float GetCountTime(pCounter self, SConnection * pCon)
+{
+ return self->getTime(self, pCon);
+}
+/*------------------------------------------------------------------------*/
+static float GetCountTimeImpl(pCounter self, SConnection * pCon)
+{
+ assert(self);
+
+ if (!self->isUpToDate) {
+ self->pCountInt->TransferData(self, pCon);
+ }
+ return self->pDriv->fTime;
+}
+
+/*----------------------------------------------------------------------*/
+static int isAuthorised(SConnection * pCon, int iCode)
+{
+ char pBueffel[132];
+
+ if (!SCMatchRights(pCon, iCode)) {
+ sprintf(pBueffel, "ERROR: you are not authorised to count");
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ return 1;
+}
+
+/*-----------------------------------------------------------------------*/
+static int CounterInterest(int iEvent, void *pEvent, void *pUser)
+{
+ SConnection *pCon = NULL;
+ pMonEvent pMon = NULL;
+ char pBueffel[512];
+ int rights;
+
+ if (pCon == NULL || !SCisConnected(pCon)) {
+ return -1;
+ }
+
+ if (iEvent != MONITOR || pCon == NULL) {
+ return 0;
+ }
+
+ pCon = (SConnection *) pUser;
+ pMon = (pMonEvent) pEvent;
+ assert(pCon);
+ assert(pMon);
+ snprintf(pBueffel,511, "%s.CountStatus = %f %d", pMon->pName, pMon->fPreset,
+ (int) nintf(pMon->fCurrent));
/**
* prevent this to be written to log files
*/
- rights = SCGetRights(pCon);
- SCSetRights(pCon,usSpy);
- SCWriteInContext(pCon,pBueffel,eWarning,cc);
- SCSetRights(pCon,rights);
- return 1;
- }
-/*-----------------------------------------------------------------------*/
-
- int CountAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pCounter self = NULL;
- int iRet, iRet2;
- FuPaResult PaRes;
- char pBueffel[256], pError[80];
- char **argx;
- float fVal;
- long lVal;
- long lID;
- CounterMode eMode;
- FuncTemplate ActionTemplate[] = {
- {"count",1,{FUPAFLOAT} },
- {"getpreset",0,{0.0} },
- {"setpreset",1,{FUPAFLOAT}},
- {"getmode",0,{0,0}},
- {"setmode",1,{FUPATEXT}},
- {"getcounts",0,{0,0}},
- {"getmonitor",1,{FUPAINT,0}},
- {"setexponent",1,{FUPAINT,0}},
- {"getexponent",0,{0,0}},
- {"interest",0,{0,0}},
- {"uninterest",0,{0,0}},
- {"status",0,{0,0}},
- {"gettime",0,{0,0}},
- {"countnb",1,{FUPAFLOAT} },
- {"getthreshold",1,{FUPAINT}},
- {"setthreshold",2,{FUPAINT,FUPAFLOAT}},
- {"stop",0,{0,0}},
- {"mode",1,{FUPAOPT}},
- {"preset",1,{FUPAOPT}},
- {"send",0,{0,0}},
- {"setpar",3,{FUPATEXT,FUPAINT,FUPAFLOAT}},
- {"getpar",2,{FUPATEXT,FUPAOPT}},
- {"getnmon",0,{0,0}},
- {"getchannel",0,{0}},
- {"setchannel",1,{FUPAINT}}
- };
- char *pMode[] = {
- "timer",
- "monitor",
- NULL
- };
-
- self = (pCounter)pData;
- assert(self);
- assert(pCon);
- assert(pSics);
-
- /* parse function args */
- argtolower(argc,argv);
- argx = &argv[1];
- iRet = EvaluateFuPa((pFuncTemplate)&ActionTemplate,25,argc-1,argx,&PaRes);
- if(iRet < 0)
- {
- sprintf(pBueffel,"%s",PaRes.pError);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
- /* do something! */
- switch(iRet)
- {
- case 0: /* Count */
- return DoCount(self,PaRes.Arg[0].fVal,pCon,1);
- break;
- case 1: /* GetPreset */
- fVal = GetCounterPreset(self);
- sprintf(pBueffel,"%s.Preset = %f",argv[0],fVal);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- break;
- case 2: /* Set Preset */
- if(isAuthorised(pCon,usUser))
- {
- iRet2 = SetCounterPreset(self,PaRes.Arg[0].fVal);
- SCparChange(pCon);
- if(iRet2)
- SCSendOK(pCon);
- return iRet2;
- }
- else
- {
- return 0;
- }
- break;
- case 3: /* GetMode */
- eMode = GetCounterMode(self);
- if(eMode == eTimer)
- {
- sprintf(pBueffel,"%s.Mode = Timer",argv[0]);
- }
- else
- {
- sprintf(pBueffel,"%s.Mode = Monitor",argv[0]);
- }
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- break;
- case 4: /* Set Mode */
- if(isAuthorised(pCon,usUser))
- {
- if(strcmp(PaRes.Arg[0].text,"timer") == 0)
- {
- SetCounterMode(self,eTimer);
- SCparChange(pCon);
- SCSendOK(pCon);
- return 1;
- }
- else if(strcmp(PaRes.Arg[0].text,"monitor") == 0)
- {
- SetCounterMode(self,ePreset);
- SCparChange(pCon);
- SCSendOK(pCon);
- return 1;
- }
- else
- {
- sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode",
- PaRes.Arg[0].text);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- }
- else
- {
- return 0;
- }
- case 5: /* GetCounts */
- lVal = GetCounts(self,pCon);
- sprintf(pBueffel,"%s.Counts = %ld",argv[0],lVal);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
-
- case 6: /* GetMonitor */
- lVal = GetMonitor(self,PaRes.Arg[0].iVal,pCon);
- if(lVal < 0)
- {
- sprintf(pBueffel,"ERROR: %d out of range for monitors",
- PaRes.Arg[0].iVal);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- sprintf(pBueffel,"%s.Monitor %d = %ld",argv[0],PaRes.Arg[0].iVal,
- lVal);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- case 7: /* SetExponent */
- if(!SCMatchRights(pCon,usMugger))
- {
- return 0;
- }
- self->iExponent = PaRes.Arg[0].iVal;
- SCparChange(pCon);
- SCSendOK(pCon);
- return 1;
- case 8: /* GetExponent */
- sprintf(pBueffel,"%s.Exponent = %d",argv[0], self->iExponent);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- case 9: /* interest */
- lID = RegisterCallback(self->pCall, SCGetContext(pCon), MONITOR, CounterInterest,
- pCon, NULL);
- SCRegister(pCon,pSics, self->pCall,lID);
- SCSendOK(pCon);
- return 1;
- case 10: /* uninterest */
- RemoveCallback2(self->pCall,pCon);
- SCSendOK(pCon);
- return 1;
- case 11: /* status */
- self->pCountInt->TransferData(self,pCon);
- if(GetCounterMode(self) == ePreset)
- {
- sprintf(pBueffel,"%s.CountStatus = %d %d Beam: %ld E6",
- argv[0],
- (int)nintf(self->pDriv->fPreset),
- (int)nintf(self->pDriv->fLastCurrent),
- GetMonitor(self,4,pCon)/100000);
- }
- else
- {
- sprintf(pBueffel,"%s.CountStatus = %8.2f %8.2f Beam %ld E6",
- argv[0],
- self->pDriv->fPreset,
- self->pDriv->fLastCurrent,
- GetMonitor(self,4,pCon)/100000);
- }
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- case 12: /* gettime */
- fVal = GetCountTime(self,pCon);
- sprintf(pBueffel,"%s.CountTime = %f",argv[0],fVal);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- case 13:
- /* countnb, non blocking count */
- return DoCount(self,PaRes.Arg[0].fVal,pCon,0);
- break;
- case 14:
- /* get threshold value */
- iRet = self->pDriv->Get(self->pDriv,"threshold",
- PaRes.Arg[0].iVal,&fVal);
- if(iRet <= 0)
- {
- self->pDriv->GetError(self->pDriv,&iRet,
- pError,79);
- sprintf(pBueffel,"ERROR: %s",pError);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- else
- {
- sprintf(pBueffel,"%s.threshold%1.1d = %f",
- argv[0],PaRes.Arg[0].iVal,fVal);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- break;
- case 15:
- if(!SCMatchRights(pCon,usMugger))
- {
- SCWrite(pCon,
- "ERROR: Insufficient privilege to set threshold",eError);
- return 0;
- }
- if(isInRunMode(pServ->pExecutor))
- {
- SCWrite(pCon,
- "ERROR: cannot change threshold while instrument is active",
- eError);
- return 0;
- }
- /* set threshold value */
- iRet = self->pDriv->Set(self->pDriv,"threshold",
- PaRes.Arg[0].iVal,PaRes.Arg[1].fVal);
- if(iRet <= 0)
- {
- self->pDriv->GetError(self->pDriv,&iRet,
- pError,79);
- sprintf(pBueffel,"ERROR: %s",pError);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- else
- {
- SCparChange(pCon);
- SCSendOK(pCon);
- return 1;
- }
- break;
- case 16:
- /* stop */
- if(!SCMatchRights(pCon,usUser))
- {
- return 0;
- }
- self->pCountInt->Halt(self);
- SCSendOK(pCon);
- return 1;
- case 17:
- /* mode */
- if(PaRes.Arg[0].iVal) /* set case */
- {
- if(isAuthorised(pCon,usUser))
- {
- if(strcmp(PaRes.Arg[0].text,"timer") == 0)
- {
- SetCounterMode(self,eTimer);
- SCparChange(pCon);
- SCSendOK(pCon);
- return 1;
- }
- else if(strcmp(PaRes.Arg[0].text,"monitor") == 0)
- {
- SetCounterMode(self,ePreset);
- SCparChange(pCon);
- SCSendOK(pCon);
- return 1;
- }
- else
- {
- sprintf(pBueffel,
- "ERROR: %s not recognized as valid counter mode",
- PaRes.Arg[0].text);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- }
- }
- else /* get case */
- {
- eMode = GetCounterMode(self);
- if(eMode == eTimer)
- {
- sprintf(pBueffel,"%s.Mode = Timer",argv[0]);
- }
- else
- {
- sprintf(pBueffel,"%s.Mode = Monitor",argv[0]);
- }
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- break;
- }
- break;
- case 18: /* preset */
- if(PaRes.Arg[0].iVal) /* set case */
- {
- if(isAuthorised(pCon,usUser))
- {
- iRet2 = SetCounterPreset(self,PaRes.Arg[0].fVal);
- if(iRet2)
- SCSendOK(pCon);
- SCparChange(pCon);
- return iRet2;
- }
- else
- {
- return 0;
- }
- }
- else /* read case */
- {
- fVal = GetCounterPreset(self);
- sprintf(pBueffel,"%s.Preset = %f",argv[0],fVal);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- break;
- case 19: /* send */
- /* only manager may use this */
- if(!SCMatchRights(pCon,usMugger))
- {
- return 0;
- }
- Arg2Text(argc-2,&argv[2],pError,79);
- iRet = self->pDriv->Send(self->pDriv,pError,pBueffel,255);
- if(iRet == 1)
- {
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- else
- {
- self->pDriv->GetError(self->pDriv,&iRet,pError,79);
- SCWrite(pCon,pError,eError);
- return 0;
- }
- break;
- case 20: /* setpar*/
- if(!SCMatchRights(pCon,usMugger))
- {
- return 0;
- }
- iRet = self->pDriv->Set(self->pDriv,PaRes.Arg[0].text,
- PaRes.Arg[1].iVal, PaRes.Arg[2].fVal);
- if(iRet == 1)
- {
- SCparChange(pCon);
- SCSendOK(pCon);
- return 1;
- }
- else
- {
- self->pDriv->GetError(self->pDriv,&iRet,pError,79);
- SCWrite(pCon,pError,eError);
- return 0;
- }
- break;
- case 21: /* getpar*/
- if(!SCMatchRights(pCon,usMugger))
- {
- return 0;
- }
- iRet = self->pDriv->Get(self->pDriv,PaRes.Arg[0].text,
- PaRes.Arg[1].iVal, &fVal);
- if(iRet == 1)
- {
- sprintf(pBueffel,"%s.%s %s = %f",argv[0],PaRes.Arg[0].text,
- PaRes.Arg[1].text, fVal);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- else
- {
- self->pDriv->GetError(self->pDriv,&iRet,pError,79);
- SCWrite(pCon,pError,eError);
- return 0;
- }
- break;
- case 22: /* getnmon */
- snprintf(pBueffel,131,"%s.getnmon = %d", argv[0], GetNMonitor(self));
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- break;
- case 23: /* getchannel */
- snprintf(pBueffel,131,"%s.getchannel = %d", argv[0], GetControlMonitor(self));
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- break;
- case 24: /* setchannel */
- if (SetControlMonitor(self, PaRes.Arg[0].iVal)) {
- return 1;
- } else {
- SCWrite(pCon,"ERROR: Invalid channel id",eError);
- return 0;
- }
- break;
- default:
- assert(0); /* internal error */
- }
- return 0;
- }
+ SCSetRights(pCon, usSpy);
+ SCWrite(pCon, pBueffel, eWarning);
+ return 1;
+}
+/*------------------------------------------------------------------------*/
+pCounter CreateCounter(char *name, pCounterDriver pDriv)
+{
+ pCounter pRes = NULL;
-
+ assert(pDriv);
+
+ pRes = (pCounter) malloc(sizeof(Counter));
+ if (!pRes) {
+ return NULL;
+ }
+ pRes->pDes = CreateDescriptor("SingleCounter");
+ if (!pRes->pDes) {
+ free(pRes);
+ return NULL;
+ }
+ /* initialize Descriptor functions */
+ pRes->pDes->GetInterface = CounterGetInterface;
+ pRes->pDes->SaveStatus = SaveCounterStatus;
+
+ /* initialise countable interface */
+ pRes->pCountInt = CreateCountableInterface();
+ if (!pRes->pCountInt) {
+ DeleteDescriptor(pRes->pDes);
+ free(pRes);
+ return NULL;
+ }
+ pRes->pCountInt->SetCountParameters = SetCountParameters;
+ pRes->pCountInt->StartCount = StartCount;
+ pRes->pCountInt->CheckCountStatus = CheckCountStatus;
+ pRes->pCountInt->TransferData = TransferData;
+ pRes->pCountInt->Halt = Halt;
+ pRes->pCountInt->Pause = PauseCount;
+ pRes->pCountInt->Continue = ContinueCount;
+ pRes->iCallbackCounter = 20;
+
+ pRes->setMode = SetCounterModeImpl;
+ pRes->getMode = GetCounterModeImpl;
+ pRes->getNMonitor = GetNMonitorImpl;
+ pRes->setPreset = SetCounterPresetImpl;
+ pRes->getPreset = GetCounterPresetImpl;
+ pRes->getControlValue = GetControlValueImpl;
+ pRes->getCounts = GetCountsImpl;
+ pRes->getMonitor = GetMonitorImpl;
+ pRes->setMonitor = SetMonitorValueImpl;
+ pRes->getTime = GetCountTimeImpl;
+
+ pRes->pCall = CreateCallBackInterface();
+
+ pRes->pDriv = pDriv;
+ pRes->isUpToDate = 1;
+ pRes->iExponent = 0;
+ pRes->name = strdup(name);
+ return pRes;
+}
+
+/*-----------------------------------------------------------------------*/
+
+int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pCounter self = NULL;
+ int iRet, iRet2, i;
+ FuPaResult PaRes;
+ char pBueffel[256], pError[80];
+ char **argx;
+ float fVal;
+ long lVal;
+ long lID;
+ CounterMode eMode;
+ FuncTemplate ActionTemplate[] = {
+ {"count", 1, {FUPAFLOAT}},
+ {"getpreset", 0, {0.0}},
+ {"setpreset", 1, {FUPAFLOAT}},
+ {"getmode", 0, {0, 0}},
+ {"setmode", 1, {FUPATEXT}},
+ {"getcounts", 0, {0, 0}},
+ {"getmonitor", 1, {FUPAINT, 0}},
+ {"setexponent", 1, {FUPAINT, 0}},
+ {"getexponent", 0, {0, 0}},
+ {"interest", 0, {0, 0}},
+ {"uninterest", 0, {0, 0}},
+ {"status", 0, {0, 0}},
+ {"gettime", 0, {0, 0}},
+ {"countnb", 1, {FUPAFLOAT}},
+ {"getthreshold", 1, {FUPAINT}},
+ {"setthreshold", 2, {FUPAINT, FUPAFLOAT}},
+ {"stop", 0, {0, 0}},
+ {"mode", 1, {FUPAOPT}},
+ {"preset", 1, {FUPAOPT}},
+ {"send", 0, {0, 0}},
+ {"setpar", 3, {FUPATEXT, FUPAINT, FUPAFLOAT}},
+ {"getpar", 2, {FUPATEXT, FUPAOPT}},
+ {"getnmon", 0, {0, 0}}
+ };
+ char *pMode[] = {
+ "timer",
+ "monitor",
+ NULL
+ };
+
+ self = (pCounter) pData;
+ assert(self);
+ assert(pCon);
+ assert(pSics);
+
+ /* parse function args */
+ argtolower(argc, argv);
+ argx = &argv[1];
+ iRet =
+ EvaluateFuPa((pFuncTemplate) & ActionTemplate, 23, argc - 1, argx,
+ &PaRes);
+ if (iRet < 0) {
+ snprintf(pBueffel, 255,"%s", PaRes.pError);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+ /* do something! */
+ switch (iRet) {
+ case 0: /* Count */
+ return DoCount(self, PaRes.Arg[0].fVal, pCon, 1);
+ break;
+ case 1: /* GetPreset */
+ fVal = GetCounterPreset(self);
+ sprintf(pBueffel, "%s.Preset = %f", argv[0], fVal);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ break;
+ case 2: /* Set Preset */
+ if (isRunning(self->pCountInt)) {
+ SCWrite(pCon, "ERROR: cannot change preset while counting", eError);
+ return 0;
+ }
+ if (isAuthorised(pCon, usUser)) {
+ iRet2 = SetCounterPreset(self, PaRes.Arg[0].fVal);
+ SCparChange(pCon);
+ if (iRet2)
+ SCSendOK(pCon);
+ return iRet2;
+ } else {
+ return 0;
+ }
+ break;
+ case 3: /* GetMode */
+ eMode = GetCounterMode(self);
+ if (eMode == eTimer) {
+ sprintf(pBueffel, "%s.Mode = Timer", argv[0]);
+ } else {
+ sprintf(pBueffel, "%s.Mode = Monitor", argv[0]);
+ }
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ break;
+ case 4: /* Set Mode */
+ if (isRunning(self->pCountInt)) {
+ SCWrite(pCon, "ERROR: cannot change mode while counting", eError);
+ return 0;
+ }
+ if (isAuthorised(pCon, usUser)) {
+ if (strcmp(PaRes.Arg[0].text, "timer") == 0) {
+ SetCounterMode(self, eTimer);
+ SCparChange(pCon);
+ SCSendOK(pCon);
+ return 1;
+ } else if (strcmp(PaRes.Arg[0].text, "monitor") == 0) {
+ SetCounterMode(self, ePreset);
+ SCparChange(pCon);
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ snprintf(pBueffel,255, "ERROR: %s not recognized as valid counter mode",
+ PaRes.Arg[0].text);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ case 5: /* GetCounts */
+ lVal = GetCounts(self, pCon);
+ sprintf(pBueffel, "%s.Counts = %ld", argv[0], lVal);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+
+ case 6: /* GetMonitor */
+ lVal = GetMonitor(self, PaRes.Arg[0].iVal, pCon);
+ if (lVal < 0) {
+ sprintf(pBueffel, "ERROR: %d out of range for monitors",
+ PaRes.Arg[0].iVal);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ sprintf(pBueffel, "%s.Monitor %d = %ld", argv[0], PaRes.Arg[0].iVal,
+ lVal);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ case 7: /* SetExponent */
+ if (!SCMatchRights(pCon, usMugger)) {
+ return 0;
+ }
+ self->iExponent = PaRes.Arg[0].iVal;
+ SCparChange(pCon);
+ SCSendOK(pCon);
+ return 1;
+ case 8: /* GetExponent */
+ sprintf(pBueffel, "%s.Exponent = %d", argv[0], self->iExponent);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ case 9: /* interest */
+ lID = RegisterCallback(self->pCall, MONITOR, CounterInterest,
+ SCCopyConnection(pCon), SCDeleteConnection);
+ SCSendOK(pCon);
+ return 1;
+ case 10: /* uninterest */
+ RemoveCallbackCon(self->pCall, pCon);
+ SCSendOK(pCon);
+ return 1;
+ case 11: /* status */
+ self->pCountInt->TransferData(self, pCon);
+ if (GetCounterMode(self) == ePreset) {
+ lVal = GetCounterPreset(self);
+ for(i = 0; i < self->iExponent; i++){
+ lVal *= 10;
+ }
+ sprintf(pBueffel, "%s.CountStatus = %d %d Beam: %ld E6",
+ argv[0],
+ (int) nintf(lVal),
+ (int) nintf(GetControlValue(self)),
+ GetMonitor(self, 4, pCon) / 100000);
+ } else {
+ sprintf(pBueffel, "%s.CountStatus = %8.2f %8.2f Beam %ld E6",
+ argv[0],
+ self->pDriv->fPreset,
+ self->pDriv->fLastCurrent,
+ GetMonitor(self, 4, pCon) / 100000);
+ }
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ case 12: /* gettime */
+ fVal = GetCountTime(self, pCon);
+ sprintf(pBueffel, "%s.CountTime = %f", argv[0], fVal);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ case 13:
+ /* countnb, non blocking count */
+ return DoCount(self, PaRes.Arg[0].fVal, pCon, 0);
+ break;
+ case 14:
+ /* get threshold value */
+ iRet = self->pDriv->Get(self->pDriv, "threshold",
+ PaRes.Arg[0].iVal, &fVal);
+ if (iRet <= 0) {
+ self->pDriv->GetError(self->pDriv, &iRet, pError, 79);
+ sprintf(pBueffel, "ERROR: %s", pError);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ } else {
+ sprintf(pBueffel, "%s.threshold%1.1d = %f",
+ argv[0], PaRes.Arg[0].iVal, fVal);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ }
+ break;
+ case 15:
+ if (!SCMatchRights(pCon, usMugger)) {
+ SCWrite(pCon,
+ "ERROR: Insufficient privilege to set threshold", eError);
+ return 0;
+ }
+ if (isInRunMode(pServ->pExecutor)) {
+ SCWrite(pCon,
+ "ERROR: cannot change threshold while instrument is active",
+ eError);
+ return 0;
+ }
+ /* set threshold value */
+ iRet = self->pDriv->Set(self->pDriv, "threshold",
+ PaRes.Arg[0].iVal, PaRes.Arg[1].fVal);
+ if (iRet <= 0) {
+ self->pDriv->GetError(self->pDriv, &iRet, pError, 79);
+ sprintf(pBueffel, "ERROR: %s", pError);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ } else {
+ SCparChange(pCon);
+ SCSendOK(pCon);
+ return 1;
+ }
+ break;
+ case 16:
+ /* stop */
+ if (!SCMatchRights(pCon, usUser)) {
+ return 0;
+ }
+ self->pCountInt->Halt(self);
+ SCSendOK(pCon);
+ return 1;
+ case 17:
+ /* mode */
+ if (PaRes.Arg[0].iVal) { /* set case */
+ if (isRunning(self->pCountInt)) {
+ SCWrite(pCon, "ERROR: cannot change mode while counting", eError);
+ return 0;
+ }
+ if (isAuthorised(pCon, usUser)) {
+ if (strcmp(PaRes.Arg[0].text, "timer") == 0) {
+ SetCounterMode(self, eTimer);
+ SCparChange(pCon);
+ SCSendOK(pCon);
+ return 1;
+ } else if (strcmp(PaRes.Arg[0].text, "monitor") == 0) {
+ SetCounterMode(self, ePreset);
+ SCparChange(pCon);
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ snprintf(pBueffel,255,
+ "ERROR: %s not recognized as valid counter mode",
+ PaRes.Arg[0].text);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ }
+ } else { /* get case */
+
+ eMode = GetCounterMode(self);
+ if (eMode == eTimer) {
+ sprintf(pBueffel, "%s.Mode = Timer", argv[0]);
+ } else {
+ sprintf(pBueffel, "%s.Mode = Monitor", argv[0]);
+ }
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ break;
+ }
+ break;
+ case 18: /* preset */
+ if (PaRes.Arg[0].iVal) { /* set case */
+ if (isRunning(self->pCountInt)) {
+ SCWrite(pCon, "ERROR: cannot set preset while counting", eError);
+ return 0;
+ }
+ if (isAuthorised(pCon, usUser)) {
+ iRet2 = SetCounterPreset(self, PaRes.Arg[0].fVal);
+ if (iRet2)
+ SCSendOK(pCon);
+ SCparChange(pCon);
+ return iRet2;
+ } else {
+ return 0;
+ }
+ } else { /* read case */
+
+ fVal = GetCounterPreset(self);
+ sprintf(pBueffel, "%s.Preset = %f", argv[0], fVal);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ }
+ break;
+ case 19: /* send */
+ /* only manager may use this */
+ if (!SCMatchRights(pCon, usMugger)) {
+ return 0;
+ }
+ Arg2Text(argc - 2, &argv[2], pError, 79);
+ iRet = self->pDriv->Send(self->pDriv, pError, pBueffel, 255);
+ if (iRet == 1) {
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else {
+ self->pDriv->GetError(self->pDriv, &iRet, pError, 79);
+ SCWrite(pCon, pError, eError);
+ return 0;
+ }
+ break;
+ case 20: /* setpar */
+ if (isRunning(self->pCountInt)) {
+ SCWrite(pCon, "ERROR: cannot change parameters while counting",
+ eError);
+ return 0;
+ }
+ if (!SCMatchRights(pCon, usMugger)) {
+ return 0;
+ }
+ iRet = self->pDriv->Set(self->pDriv, PaRes.Arg[0].text,
+ PaRes.Arg[1].iVal, PaRes.Arg[2].fVal);
+ if (iRet == 1) {
+ SCparChange(pCon);
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ self->pDriv->GetError(self->pDriv, &iRet, pError, 79);
+ SCWrite(pCon, pError, eError);
+ return 0;
+ }
+ break;
+ case 21: /* getpar */
+ if (!SCMatchRights(pCon, usMugger)) {
+ return 0;
+ }
+ iRet = self->pDriv->Get(self->pDriv, PaRes.Arg[0].text,
+ PaRes.Arg[1].iVal, &fVal);
+ if (iRet == 1) {
+ snprintf(pBueffel,255, "%s.%s %d = %f", argv[0], PaRes.Arg[0].text,
+ PaRes.Arg[1].iVal, fVal);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ } else {
+ self->pDriv->GetError(self->pDriv, &iRet, pError, 79);
+ SCWrite(pCon, pError, eError);
+ return 0;
+ }
+ break;
+ case 22: /* getnmon */
+ snprintf(pBueffel, 131, "%s.getnmon = %d", argv[0], GetNMonitor(self));
+ SCWrite(pCon, pBueffel, eValue);
+ break;
+ default:
+ assert(0); /* internal error */
+ }
+ return 0;
+}
diff --git a/counter.h b/counter.h
index ba1382bb..b69573ca 100644
--- a/counter.h
+++ b/counter.h
@@ -8,54 +8,72 @@
Mark Koennecke, January 1996
copyright: see implementation file.
+
+ Massively reworked to accomodate second generation counter objects.
+
+ Mark Koennecke, January 2009
----------------------------------------------------------------------------*/
#ifndef SICSCOUNTER
#define SICSCOUNTER
#include "countdriv.h"
- typedef struct {
- pObjectDescriptor pDes;
- char *name;
- int isUpToDate;
- int iExponent;
- pICountable pCountInt;
- pCounterDriver pDriv;
- pICallBack pCall;
- unsigned long tStart;
- int iCallbackCounter;
- int badStatusCount;
- } Counter, *pCounter;
-
+typedef struct __Counter{
+ pObjectDescriptor pDes;
+ pHdb objectNode;
+ char *name;
+ int isUpToDate;
+ int iExponent;
+ pICountable pCountInt;
+ pCounterDriver pDriv;
+ pICallBack pCall;
+ unsigned long tStart;
+ int iCallbackCounter;
+ int badStatusCount;
+ int haltFixFlag; /* solely here to prevent multiple calls to the halt function on overrun timers in countersec.c*/
+ int (*setMode)(struct __Counter *self, CounterMode eMode);
+ CounterMode (*getMode)(struct __Counter *self);
+ int (*getNMonitor)(struct __Counter *self);
+ int (*setPreset)(struct __Counter *self, float val);
+ float (*getPreset)(struct __Counter *self);
+ float (*getControlValue)(struct __Counter *self);
+ long (*getCounts)(struct __Counter *self, SConnection *pCon);
+ long (*getMonitor)(struct __Counter *self, int iNum, SConnection *pCon);
+ void (*setMonitor)(struct __Counter *self, int iNum, long val);
+ float (*getTime)(struct __Counter *self, SConnection *pCon);
+} Counter, *pCounter;
+
/*----------------------------- birth & death -----------------------------*/
- pCounter CreateCounter(char *name, pCounterDriver pDriv);
- void DeleteCounter(void *self);
- int MakeCounter(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length);
+pCounter CreateCounter(char *name, pCounterDriver pDriv);
+void DeleteCounter(void *self);
+int MakeCounter(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+/* in countersec.c */
+int MakeSecCter(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
/*------------------------- set/get Parameters ----------------------------*/
- int SetCounterMode(pCounter self, CounterMode eNew);
- CounterMode GetCounterMode(pCounter self);
-
- int SetCounterPreset(pCounter self, float fVal);
- float GetCounterPreset(pCounter self);
-
- long GetCounts(pCounter self, SConnection *pCon);
- long GetMonitor(pCounter self, int iNum, SConnection *pCon);
- int GetNMonitor(pCounter self);
- int GetControlMonitor(pCounter self);
- int SetControlMonitor(pCounter self, int channel);
- void SetMonitorValue(pCounter self, int index, long value);
- float GetCountTime(pCounter self, SConnection *pCon);
+int SetCounterMode(pCounter self, CounterMode eNew);
+CounterMode GetCounterMode(pCounter self);
+
+int SetCounterPreset(pCounter self, float fVal);
+float GetCounterPreset(pCounter self);
+float GetControlValue(pCounter self);
+
+long GetCounts(pCounter self, SConnection * pCon);
+long GetMonitor(pCounter self, int iNum, SConnection * pCon);
+int GetNMonitor(pCounter self);
+void SetMonitorValue(pCounter self, int index, long value);
+float GetCountTime(pCounter self, SConnection * pCon);
+
+int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock);
- int DoCount(pCounter self,float fPreset, SConnection *pCon,
- int iBlock);
-
/*-------------------------------------------------------------------------
the real action: starting and checking is packaged with the
ObjectDescriptor.
*/
-
- int CountAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
-
-#endif
+
+int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+
+#endif
diff --git a/countersec.c b/countersec.c
new file mode 100644
index 00000000..9fdc3520
--- /dev/null
+++ b/countersec.c
@@ -0,0 +1,555 @@
+/**
+ * This is a second generation style counter object. It is supposed to work
+ * nicely with a scriptcontext to drive the actual hardware. This is supposed
+ * to interface to single counters and histogram memories. This tries to be
+ * backwards compatible with the old style counter module; thus some
+ * fields in the data structure will not be used.
+ *
+ * copyright: see file COPYRIGHT
+ *
+ * Mark Koennecke, February 2009
+ */
+#include
+#include
+#include
+#include "sicshipadaba.h"
+/*---------------------------------------------------------------------------
+ * defines for commmands
+ * -------------------------------------------------------------------------*/
+#define START 1000
+#define STOP 1001
+#define PAUSE 1002
+#define CONT 1003
+/*---------------------------------------------------------------------------*/
+typedef struct {
+ float fPreset;
+ float fCurrent;
+ char *pName;
+} MonEvent, *pMonEvent;
+/*---------------------------------------------------------------------------*/
+int SecCtrInvokeFunction(pCounter self, SConnection *pCon, int code)
+{
+ pHdb node = NULL;
+ hdbValue v;
+
+ node = GetHipadabaNode(self->pDes->parNode, "control");
+ assert(node != NULL);
+ v = MakeHdbFloat(code);
+ return SetHipadabaPar(node,v,pCon);
+}
+/*---------------------------------------------------------------------------*/
+static int SecCtrHalt(void *pData)
+{
+ pCounter self = (pCounter)pData;
+ assert(self != NULL);
+
+ SecCtrInvokeFunction(self,pServ->dummyCon, STOP);
+ ReleaseCountLock(self->pCountInt);
+ return 1;
+}
+/*---------------------------------------------------------------------------*/
+static int SecStartCount(void *pData, SConnection *pCon)
+{
+ pCounter self = (pCounter)pData;
+ int status;
+ pHdb node;
+
+ assert(self != NULL);
+
+ if (!GetCountLock(self->pCountInt, pCon)) {
+ return 0;
+ }
+
+ status = SecCtrInvokeFunction(self,pCon, START);
+ self->haltFixFlag = 0;
+ if(status == 1){
+ self->isUpToDate = 0;
+ self->badStatusCount = 0;
+ self->tStart = time(NULL);
+ node = GetHipadabaNode(self->pDes->parNode, "status");
+ UpdateHipadabaPar(node,MakeHdbText("run"), pCon);
+ node = GetHipadabaNode(self->pDes->parNode, "control");
+ UpdateHipadabaPar(node,MakeHdbFloat(.0), pCon);
+ SetHdbProperty(node,"geterror", NULL);
+ /*
+ * set time to 0. Otherwise, if there is a delay,
+ * the check for overrun counters in SecCtrCheckStatus
+ * may trigger!
+ */
+ node = GetHipadabaNode(self->pDes->parNode, "time");
+ UpdateHipadabaPar(node,MakeHdbFloat(.0), pCon);
+ InvokeCallBack(self->pCall,COUNTSTART, pCon);
+ return 1;
+ } else {
+ ReleaseCountLock(self->pCountInt);
+ return HWFault;
+ }
+}
+/*---------------------------------------------------------------------------*/
+static int SecPause(void *pData, SConnection *pCon)
+{
+ pCounter self = (pCounter)pData;
+
+ assert(self != NULL);
+ return SecCtrInvokeFunction(self,pCon, PAUSE);
+}
+/*---------------------------------------------------------------------------*/
+static int SecContinue(void *pData, SConnection *pCon)
+{
+ pCounter self = (pCounter)pData;
+
+ assert(self != NULL);
+ return SecCtrInvokeFunction(self,pCon, CONT);
+}
+/*----------------------------------------------------------------------------*/
+static int SecCtrCheckStatus(void *pData, SConnection *pCon)
+{
+ pCounter self = (pCounter)pData;
+ pHdb node = NULL, control = NULL;
+ hdbValue v;
+ int status;
+ MonEvent sMon;
+ float fControl, fPreset;
+
+ assert(self != NULL);
+
+ node = GetHipadabaNode(self->pDes->parNode,"status");
+ assert(node != NULL);
+ status = GetHipadabaPar(node,&v,pCon);
+
+ if(status != 1){
+ ReleaseCountLock(self->pCountInt);
+ return HWFault;
+ }
+
+ if(v.v.text == NULL){
+ return HWBusy;
+ }
+ if (strstr(v.v.text, "idle") != NULL) {
+ InvokeCallBack(self->pCall, COUNTEND, NULL);
+ ReleaseCountLock(self->pCountInt);
+ status = HWIdle;
+ } else if (strstr(v.v.text, "run") != NULL) {
+ status = HWBusy;
+ } else if (strstr(v.v.text, "nobeam") != NULL) {
+ status = HWNoBeam;
+ } else if (strstr(v.v.text, "pause") != NULL) {
+ status = HWPause;
+ } else if (strstr(v.v.text, "error") != NULL) {
+ InvokeCallBack(self->pCall, COUNTEND, NULL);
+ ReleaseCountLock(self->pCountInt);
+ status = HWFault;
+ } else {
+ SCPrintf(pCon, eError, "ERROR: unknown counter status %s found",
+ v.v.text);
+ ReleaseCountLock(self->pCountInt);
+ status = HWFault;
+ }
+ ReleaseHdbValue(&v);
+
+
+ node = GetHipadabaNode(self->pDes->parNode,"control");
+ assert(node != NULL);
+ GetHipadabaPar(node,&v,pCon);
+ fControl = v.v.doubleValue;
+ node = GetHipadabaNode(self->pDes->parNode,"preset");
+ assert(node != NULL);
+ GetHipadabaPar(node,&v,pCon);
+ fPreset = v.v.doubleValue;
+
+ sMon.fCurrent = fControl;
+ sMon.fPreset = fPreset;
+ sMon.pName = self->name;
+ self->badStatusCount = 0;
+
+ /*
+ * check for overrun counter boxes
+ */
+ if(self->getMode(self) == eTimer &&
+ (sMon.fCurrent > sMon.fPreset +1)
+ && self->haltFixFlag == 0){
+ SecCtrHalt(self);
+ self->haltFixFlag = 1;
+ }
+
+ /*
+ * invoke notifiactions, if necessary
+ */
+ if (self->iCallbackCounter > 20) {
+ InvokeCallBack(self->pCall, MONITOR, &sMon);
+ self->iCallbackCounter = 0;
+ } else {
+ self->iCallbackCounter++;
+ }
+
+ return status;
+}
+/*---------------------------------------------------------------------------
+ * Here is an issue: this ought to wait until data has arrived. Callers
+ * think now that the data is up to date. With scriptcontext this may not be
+ * the case. The update may come later or even never. Perhaps this needs
+ * to be emulated:
+ * - set a property to some value when starting
+ * - add an update callback which deletes the property when done.
+ * - Check that property or the geterror property here in a loop
+ * until done or we timeout.
+ * -----------------------------------------------------------------------*/
+static int SecCtrTransferData(void *pData, SConnection *pCon)
+{
+ pCounter self = (pCounter)pData;
+ assert(self != NULL);
+ pHdb node = NULL;
+ hdbValue v;
+ int status;
+
+ node = GetHipadabaNode(self->pDes->parNode,"values");
+ assert(node != NULL);
+ self->isUpToDate = 1;
+ status = GetHipadabaPar(node,&v,pCon);
+ ReleaseHdbValue(&v);
+ return status;
+}
+/*------------------------------------------------------------------------*/
+static void *SecCtrCounterGetInterface(void *pData, int iID)
+{
+ pCounter self = NULL;
+
+ self = (pCounter) pData;
+ assert(self);
+ if (iID == COUNTID) {
+ return self->pCountInt;
+ } else if (iID == CALLBACKINTERFACE) {
+ return self->pCall;
+ }
+ return NULL;
+}
+/*--------------------------------------------------------------------------*/
+static int SecCtrSetMode(pCounter self, CounterMode eNew)
+{
+ hdbValue v;
+ pHdb node = NULL;
+
+ node = GetHipadabaNode(self->pDes->parNode,"mode");
+ assert(node != NULL);
+ switch(eNew){
+ case eTimer:
+ v = MakeHdbText("timer");
+ break;
+ case ePreset:
+ v = MakeHdbText("monitor");
+ break;
+ }
+ return SetHipadabaPar(node,v,NULL);
+}
+/*---------------------------------------------------------------------------*/
+static CounterMode SecCtrGetMode(pCounter self)
+{
+ hdbValue v;
+ pHdb node = NULL;
+ CounterMode mode;
+
+ node = GetHipadabaNode(self->pDes->parNode,"mode");
+ assert(node != NULL);
+ GetHipadabaPar(node,&v,NULL);
+ assert(v.v.text != NULL);
+ if(strcmp(v.v.text,"timer") == 0){
+ mode = eTimer;
+ } else {
+ mode = ePreset;
+ }
+ ReleaseHdbValue(&v);
+ return mode;
+}
+/*--------------------------------------------------------------------------*/
+static int SecCtrSetPreset(pCounter self, float val)
+{
+ hdbValue v;
+ pHdb node = NULL;
+
+ node = GetHipadabaNode(self->pDes->parNode,"preset");
+ assert(node != NULL);
+ v = MakeHdbFloat(val);
+ return SetHipadabaPar(node,v,NULL);
+}
+/*--------------------------------------------------------------------------*/
+static void SecCtrSetCountParameters(void *pData, float fPreset,
+ CounterMode eMode)
+{
+ pCounter self = NULL;
+
+ assert(pData);
+ self = (pCounter) pData;
+
+ SetCounterPreset(self, fPreset);
+ SetCounterMode(self, eMode);
+}
+
+/*---------------------------------------------------------------------------*/
+static float SecCtrGetPreset(pCounter self)
+{
+ hdbValue v;
+ pHdb node = NULL;
+
+ node = GetHipadabaNode(self->pDes->parNode,"preset");
+ assert(node != NULL);
+ GetHipadabaPar(node,&v,NULL);
+ return (float)v.v.doubleValue;
+}
+/*---------------------------------------------------------------------------*/
+static float SecCtrGetControlValue(pCounter self)
+{
+ hdbValue v;
+ pHdb node = NULL;
+
+ node = GetHipadabaNode(self->pDes->parNode,"control");
+ assert(node != NULL);
+ GetHipadabaPar(node,&v,NULL);
+ return (float)v.v.doubleValue;
+}
+/*--------------------------------------------------------------------------*/
+static int SecCtrGetNMonitor(pCounter self)
+{
+ hdbValue v;
+ pHdb node = NULL;
+
+ node = GetHipadabaNode(self->pDes->parNode,"values");
+ assert(node != NULL);
+ GetHipadabaPar(node,&v,NULL);
+ return v.arrayLength;
+}
+/*--------------------------------------------------------------------------*/
+static long SecCtrGetMonitor(pCounter self, int iNum, SConnection *pCon)
+{
+ hdbValue v;
+ pHdb node = NULL;
+ long val;
+
+ if (!self->isUpToDate) {
+ self->pCountInt->TransferData(self, pCon);
+ }
+ node = GetHipadabaNode(self->pDes->parNode,"values");
+ assert(node != NULL);
+ GetHipadabaPar(node,&v,pCon);
+ if(iNum >= 0 && iNum < v.arrayLength){
+ val = (long)v.v.intArray[iNum];
+ } else {
+ val = -1L;
+ }
+ ReleaseHdbValue(&v);
+ return val;
+}
+/*--------------------------------------------------------------------------*/
+static long SecCtrGetCounts(pCounter self, SConnection *pCon)
+{
+ return SecCtrGetMonitor(self,0,pCon);
+}
+/*--------------------------------------------------------------------------*/
+static void SecCtrSetMonitor(pCounter self, int iNum, long val)
+{
+ hdbValue v;
+ pHdb node = NULL;
+
+ node = GetHipadabaNode(self->pDes->parNode,"values");
+ assert(node != NULL);
+ GetHipadabaPar(node,&v,NULL);
+ if(iNum >= 0 && iNum < v.arrayLength){
+ v.v.intArray[iNum] = val;
+ UpdateHipadabaPar(node,v,NULL);
+ }
+}
+/*---------------------------------------------------------------------------*/
+static float SecCtrGetTime(pCounter self, SConnection *pCon)
+{
+ hdbValue v;
+ pHdb node = NULL;
+
+ node = GetHipadabaNode(self->pDes->parNode,"time");
+ assert(node != NULL);
+ GetHipadabaPar(node,&v,pCon);
+ return (float)v.v.doubleValue;
+}
+/*--------------------------------------------------------------------------*/
+static int CountCmd(pSICSOBJ ccmd, SConnection * con,
+ Hdb * cmdNode, Hdb * par[], int nPar)
+{
+ float preset;
+
+ if(nPar < 1){
+ return 0;
+ }
+
+ preset = par[0]->value.v.doubleValue;
+ return DoCount((pCounter)ccmd, preset, con, 1);
+}
+/*--------------------------------------------------------------------------*/
+static int CountNBCmd(pSICSOBJ ccmd, SConnection * con,
+ Hdb * cmdNode, Hdb * par[], int nPar)
+{
+ float preset;
+
+ if(nPar < 1){
+ return 0;
+ }
+
+ preset = par[0]->value.v.doubleValue;
+ return DoCount((pCounter)ccmd, preset, con, 0);
+}
+/*--------------------------------------------------------------------------*/
+static int StopCmd(pSICSOBJ ccmd, SConnection * con,
+ Hdb * cmdNode, Hdb * par[], int nPar)
+{
+ pCounter self = (pCounter)ccmd;
+ return self->pCountInt->Halt(self);
+}
+/*--------------------------------------------------------------------------*/
+static int PauseCmd(pSICSOBJ ccmd, SConnection * con,
+ Hdb * cmdNode, Hdb * par[], int nPar)
+{
+ pCounter self = (pCounter)ccmd;
+ return self->pCountInt->Pause(self,con);
+}
+/*--------------------------------------------------------------------------*/
+static int ContinueCmd(pSICSOBJ ccmd, SConnection * con,
+ Hdb * cmdNode, Hdb * par[], int nPar)
+{
+ pCounter self = (pCounter)ccmd;
+ return self->pCountInt->Continue(self,con);
+}
+/*--------------------------------------------------------------------------*/
+pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length)
+{
+ pCounter pRes = NULL;
+ pHdb node = NULL, child = NULL;
+
+ pRes = (pCounter) malloc(sizeof(Counter));
+ if (!pRes) {
+ SCWrite(pCon,"ERROR: out of memory in MakeSecCter", eError);
+ return NULL;
+ }
+ memset(pRes,0,sizeof(Counter));
+ pRes->pDes = CreateDescriptor(type);
+ if (!pRes->pDes) {
+ SCWrite(pCon,"ERROR: out of memory in MakeSecCter", eError);
+ return 0;
+ }
+ /* initialize Descriptor functions */
+ pRes->pDes->GetInterface = SecCtrCounterGetInterface;
+ pRes->pDes->SaveStatus = SaveSICSOBJ;
+
+ /* initialise countable interface */
+ pRes->pCountInt = CreateCountableInterface();
+ if (!pRes->pCountInt) {
+ DeleteDescriptor(pRes->pDes);
+ SCWrite(pCon,"ERROR: out of memory in MakeSecCter", eError);
+ return 0;
+ }
+ pRes->pCountInt->SetCountParameters = SecCtrSetCountParameters;
+ pRes->pCountInt->StartCount = SecStartCount;
+ pRes->pCountInt->CheckCountStatus = SecCtrCheckStatus;
+ pRes->pCountInt->TransferData = SecCtrTransferData;
+ pRes->pCountInt->Halt = SecCtrHalt;
+ pRes->pCountInt->Pause = SecPause;
+ pRes->pCountInt->Continue = SecContinue;
+ pRes->iCallbackCounter = 20;
+
+ pRes->setMode = SecCtrSetMode;
+ pRes->getMode = SecCtrGetMode;
+ pRes->getNMonitor = SecCtrGetNMonitor;
+ pRes->setPreset = SecCtrSetPreset;
+ pRes->getPreset = SecCtrGetPreset;
+ pRes->getControlValue = SecCtrGetControlValue;
+ pRes->getCounts = SecCtrGetCounts;
+ pRes->getMonitor = SecCtrGetMonitor;
+ pRes->setMonitor = SecCtrSetMonitor;
+ pRes->getTime = SecCtrGetTime;
+
+ pRes->pCall = CreateCallBackInterface();
+
+ pRes->isUpToDate = 1;
+ pRes->iExponent = 0;
+ pRes->name = strdup(name);
+
+ node = MakeHipadabaNode(name,HIPNONE, 0);
+ pRes->pDes->parNode = node;
+ pRes->objectNode = node;
+
+ child = MakeSICSHdbPar("time", usInternal, MakeHdbFloat(.0));
+ if (child == NULL) {
+ return NULL;
+ }
+ AddHipadabaChild(node, child, NULL);
+
+ child = MakeSICSHdbPar("preset", usUser, MakeHdbFloat(.0));
+ if (child == NULL) {
+ return NULL;
+ }
+ SetHdbProperty(child, "__save", "true");
+ AddHipadabaChild(node, child, NULL);
+
+ child = MakeSICSHdbPar("mode", usUser, MakeHdbText("monitor"));
+ if (child == NULL) {
+ return NULL;
+ }
+ SetHdbProperty(child, "__save", "true");
+ AddHipadabaChild(node, child, NULL);
+
+ child = MakeSICSHdbPar("status", usInternal, MakeHdbText("idle"));
+ if (child == NULL) {
+ return NULL;
+ }
+ AddHipadabaChild(node, child, NULL);
+
+ child = MakeSICSHdbPar("control", usUser, MakeHdbFloat(.0));
+ if (child == NULL) {
+ return NULL;
+ }
+ AddHipadabaChild(node, child, NULL);
+
+ child = MakeSICSHdbPar("values", usInternal,
+ makeHdbValue(HIPINTAR, length));
+ if (child == NULL) {
+ return NULL;
+ }
+ AddHipadabaChild(node, child, NULL);
+
+ child = AddSICSHdbPar(node,"count", usUser, MakeSICSFunc(CountCmd));
+ AddSICSHdbPar(child, "preset", usUser, MakeHdbFloat(2));
+
+ child = AddSICSHdbPar(node,"countnb", usUser, MakeSICSFunc(CountNBCmd));
+ AddSICSHdbPar(child, "preset", usUser, MakeHdbFloat(2));
+
+ child = AddSICSHdbPar(node,"stop", usUser, MakeSICSFunc(StopCmd));
+ child = AddSICSHdbPar(node,"pause", usUser, MakeSICSFunc(PauseCmd));
+ child = AddSICSHdbPar(node,"continue", usUser, MakeSICSFunc(ContinueCmd));
+
+ return pRes;
+}
+/*--------------------------------------------------------------------------*/
+int MakeSecCter(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pCounter pRes = NULL;
+ int status, length;
+ pHdb node, child;
+
+ if(argc < 3) {
+ SCWrite(pCon,"ERROR: need at least a name and length to create a counter",
+ eError);
+ return 0;
+ }
+ length = atoi(argv[2]);
+
+ pRes = CreateSecCounter(pCon,"SingleCounter", argv[1], length);
+ if(pRes == NULL){
+ return 0;
+ }
+
+ status =
+ AddCommand(pSics, argv[1], InterInvokeSICSOBJ, DeleteCounter,
+ (void *) pRes);
+ if (status != 1) {
+ SCPrintf(pCon,eError, "ERROR: duplicate command %s not created", argv[1]);
+ return 0;
+ }
+ return 1;
+}
diff --git a/crysconv.c b/crysconv.c
index 64def425..cfd9036c 100644
--- a/crysconv.c
+++ b/crysconv.c
@@ -8,8 +8,8 @@
/* Common Block Declarations */
struct {
- doublereal s[16] /* was [4][4] */, sinv[16] /* was [4][4] */;
- integer iok;
+ doublereal s[16] /* was [4][4] */ , sinv[16] /* was [4][4] */ ;
+ integer iok;
} osolem_;
#define osolem_1 osolem_
@@ -39,25 +39,25 @@ struct {
/* SUBROUTINE INVS(S,SINV,IER) */
/* SUBROUTINE ERRESO(MODULE,IER) */
/* ------------------------------------------------------------------ */
-/* Subroutine */ int setrlp_(doublereal *sam, integer *ier)
+/* Subroutine */ int setrlp_(doublereal * sam, integer * ier)
{
- /* System generated locals */
- doublereal d__1;
+ /* System generated locals */
+ doublereal d__1;
- /* Builtin functions */
- double cos(doublereal), sin(doublereal), sqrt(doublereal), atan(
- doublereal);
+ /* Builtin functions */
+ double cos(doublereal), sin(doublereal), sqrt(doublereal),
+ atan(doublereal);
- /* Local variables */
- static doublereal alfa[3], cosa[3], cosb[3];
- static integer imod;
- static doublereal sina[3], sinb[3], aspv[6] /* was [3][2] */;
- extern /* Subroutine */ int invs_(doublereal *, doublereal *, integer *);
- static doublereal a[3], b[3], c__[3], bb[9] /* was [3][3] */, cc;
- static integer id, ie, jd, je, jf, kg, lf, lh, md, me, ne;
- static doublereal zp, vv[9] /* was [3][3] */;
- extern /* Subroutine */ int erreso_(integer *, integer *);
- static doublereal rlb[6] /* was [3][2] */;
+ /* Local variables */
+ static doublereal alfa[3], cosa[3], cosb[3];
+ static integer imod;
+ static doublereal sina[3], sinb[3], aspv[6] /* was [3][2] */ ;
+ extern /* Subroutine */ int invs_(doublereal *, doublereal *, integer *);
+ static doublereal a[3], b[3], c__[3], bb[9] /* was [3][3] */ , cc;
+ static integer id, ie, jd, je, jf, kg, lf, lh, md, me, ne;
+ static doublereal zp, vv[9] /* was [3][3] */ ;
+ extern /* Subroutine */ int erreso_(integer *, integer *);
+ static doublereal rlb[6] /* was [3][2] */ ;
/* ============================ */
@@ -95,186 +95,189 @@ struct {
/* ----------------------------------------------------------------------- */
/* SOME TESTS AND INIT OF CALCUALTION */
- /* Parameter adjustments */
- --sam;
+ /* Parameter adjustments */
+ --sam;
- /* Function Body */
- *ier = 0;
- imod = 1;
- zp = 6.2831853071795862;
- osolem_1.iok = 0;
- for (id = 1; id <= 3; ++id) {
- a[id - 1] = sam[id];
- alfa[id - 1] = sam[id + 3];
- aspv[id - 1] = sam[id + 6];
- aspv[id + 2] = sam[id + 9];
+ /* Function Body */
+ *ier = 0;
+ imod = 1;
+ zp = 6.2831853071795862;
+ osolem_1.iok = 0;
+ for (id = 1; id <= 3; ++id) {
+ a[id - 1] = sam[id];
+ alfa[id - 1] = sam[id + 3];
+ aspv[id - 1] = sam[id + 6];
+ aspv[id + 2] = sam[id + 9];
/* L10: */
- }
+ }
- for (id = 1; id <= 3; ++id) {
- *ier = 1;
- if ((d__1 = a[id - 1], abs(d__1)) <= 1e-8) {
- goto L999;
- }
- *ier = 0;
-/* L20: */
- }
- for (id = 1; id <= 3; ++id) {
- a[id - 1] /= zp;
- alfa[id - 1] /= 57.29577951308232087679815481410517;
- cosa[id - 1] = cos(alfa[id - 1]);
- sina[id - 1] = sin(alfa[id - 1]);
-/* L30: */
- }
- cc = cosa[0] * cosa[0] + cosa[1] * cosa[1] + cosa[2] * cosa[2];
- cc = cosa[0] * 2. * cosa[1] * cosa[2] + 1. - cc;
- *ier = 2;
- if (cc <= .1) {
- goto L999;
+ for (id = 1; id <= 3; ++id) {
+ *ier = 1;
+ if ((d__1 = a[id - 1], abs(d__1)) <= 1e-8) {
+ goto L999;
}
*ier = 0;
- cc = sqrt(cc);
- je = 2;
- kg = 3;
- for (id = 1; id <= 3; ++id) {
- b[id - 1] = sina[id - 1] / (a[id - 1] * cc);
- cosb[id - 1] = (cosa[je - 1] * cosa[kg - 1] - cosa[id - 1]) / (sina[
- je - 1] * sina[kg - 1]);
- sinb[id - 1] = sqrt(1. - cosb[id - 1] * cosb[id - 1]);
- rlb[id + 2] = (d__1 = atan(sinb[id - 1] / cosb[id - 1]), abs(d__1)) *
- 57.29577951308232087679815481410517;
- je = kg;
- kg = id;
+/* L20: */
+ }
+ for (id = 1; id <= 3; ++id) {
+ a[id - 1] /= zp;
+ alfa[id - 1] /= 57.29577951308232087679815481410517;
+ cosa[id - 1] = cos(alfa[id - 1]);
+ sina[id - 1] = sin(alfa[id - 1]);
+/* L30: */
+ }
+ cc = cosa[0] * cosa[0] + cosa[1] * cosa[1] + cosa[2] * cosa[2];
+ cc = cosa[0] * 2. * cosa[1] * cosa[2] + 1. - cc;
+ *ier = 2;
+ if (cc <= .1) {
+ goto L999;
+ }
+ *ier = 0;
+ cc = sqrt(cc);
+ je = 2;
+ kg = 3;
+ for (id = 1; id <= 3; ++id) {
+ b[id - 1] = sina[id - 1] / (a[id - 1] * cc);
+ cosb[id - 1] =
+ (cosa[je - 1] * cosa[kg - 1] -
+ cosa[id - 1]) / (sina[je - 1] * sina[kg - 1]);
+ sinb[id - 1] = sqrt(1. - cosb[id - 1] * cosb[id - 1]);
+ rlb[id + 2] = (d__1 = atan(sinb[id - 1] / cosb[id - 1]), abs(d__1)) *
+ 57.29577951308232087679815481410517;
+ je = kg;
+ kg = id;
/* L40: */
- }
- bb[0] = b[0];
- bb[1] = 0.;
- bb[2] = 0.;
- bb[3] = b[1] * cosb[2];
- bb[4] = b[1] * sinb[2];
- bb[5] = 0.;
- bb[6] = b[2] * cosb[1];
- bb[7] = -b[2] * sinb[1] * cosa[0];
- bb[8] = 1. / a[2];
+ }
+ bb[0] = b[0];
+ bb[1] = 0.;
+ bb[2] = 0.;
+ bb[3] = b[1] * cosb[2];
+ bb[4] = b[1] * sinb[2];
+ bb[5] = 0.;
+ bb[6] = b[2] * cosb[1];
+ bb[7] = -b[2] * sinb[1] * cosa[0];
+ bb[8] = 1. / a[2];
- for (id = 1; id <= 3; ++id) {
- rlb[id - 1] = 0.;
- for (je = 1; je <= 3; ++je) {
+ for (id = 1; id <= 3; ++id) {
+ rlb[id - 1] = 0.;
+ for (je = 1; je <= 3; ++je) {
/* Computing 2nd power */
- d__1 = bb[je + id * 3 - 4];
- rlb[id - 1] += d__1 * d__1;
+ d__1 = bb[je + id * 3 - 4];
+ rlb[id - 1] += d__1 * d__1;
/* L60: */
- }
- *ier = 1;
- if ((d__1 = rlb[id - 1], abs(d__1)) <= 1e-8) {
- goto L999;
- }
- *ier = 0;
- rlb[id - 1] = sqrt(rlb[id - 1]);
-/* L50: */
}
+ *ier = 1;
+ if ((d__1 = rlb[id - 1], abs(d__1)) <= 1e-8) {
+ goto L999;
+ }
+ *ier = 0;
+ rlb[id - 1] = sqrt(rlb[id - 1]);
+/* L50: */
+ }
/* ----------------------------------------------------------------------- */
/* GENERATION OF S ORIENTATION MATRIX REC. LATTICE TO SCATTERING PLANE */
- for (kg = 1; kg <= 2; ++kg) {
- for (ie = 1; ie <= 3; ++ie) {
- vv[kg + ie * 3 - 4] = 0.;
- for (jf = 1; jf <= 3; ++jf) {
- vv[kg + ie * 3 - 4] += bb[ie + jf * 3 - 4] * aspv[jf + kg * 3
- - 4];
+ for (kg = 1; kg <= 2; ++kg) {
+ for (ie = 1; ie <= 3; ++ie) {
+ vv[kg + ie * 3 - 4] = 0.;
+ for (jf = 1; jf <= 3; ++jf) {
+ vv[kg + ie * 3 - 4] += bb[ie + jf * 3 - 4] * aspv[jf + kg * 3 - 4];
/* L90: */
- }
+ }
/* L80: */
- }
+ }
/* L70: */
- }
- for (md = 3; md >= 2; --md) {
- for (ne = 1; ne <= 3; ++ne) {
- id = md % 3 + 1;
- je = (md + 1) % 3 + 1;
- kg = ne % 3 + 1;
- lh = (ne + 1) % 3 + 1;
- vv[md + ne * 3 - 4] = vv[id + kg * 3 - 4] * vv[je + lh * 3 - 4] -
- vv[id + lh * 3 - 4] * vv[je + kg * 3 - 4];
+ }
+ for (md = 3; md >= 2; --md) {
+ for (ne = 1; ne <= 3; ++ne) {
+ id = md % 3 + 1;
+ je = (md + 1) % 3 + 1;
+ kg = ne % 3 + 1;
+ lh = (ne + 1) % 3 + 1;
+ vv[md + ne * 3 - 4] = vv[id + kg * 3 - 4] * vv[je + lh * 3 - 4] -
+ vv[id + lh * 3 - 4] * vv[je + kg * 3 - 4];
/* L110: */
- }
+ }
/* L100: */
- }
+ }
- for (id = 1; id <= 3; ++id) {
- c__[id - 1] = 0.;
- for (je = 1; je <= 3; ++je) {
+ for (id = 1; id <= 3; ++id) {
+ c__[id - 1] = 0.;
+ for (je = 1; je <= 3; ++je) {
/* Computing 2nd power */
- d__1 = vv[id + je * 3 - 4];
- c__[id - 1] += d__1 * d__1;
+ d__1 = vv[id + je * 3 - 4];
+ c__[id - 1] += d__1 * d__1;
/* L130: */
- }
- *ier = 3;
- if ((d__1 = c__[id - 1], abs(d__1)) <= 1e-6) {
- goto L999;
- }
- *ier = 0;
- c__[id - 1] = sqrt(c__[id - 1]);
+ }
+ *ier = 3;
+ if ((d__1 = c__[id - 1], abs(d__1)) <= 1e-6) {
+ goto L999;
+ }
+ *ier = 0;
+ c__[id - 1] = sqrt(c__[id - 1]);
/* L120: */
- }
+ }
- for (id = 1; id <= 3; ++id) {
- for (je = 1; je <= 3; ++je) {
- vv[je + id * 3 - 4] /= c__[je - 1];
+ for (id = 1; id <= 3; ++id) {
+ for (je = 1; je <= 3; ++je) {
+ vv[je + id * 3 - 4] /= c__[je - 1];
/* L160: */
- }
+ }
/* L150: */
- }
- for (kg = 1; kg <= 3; ++kg) {
- for (me = 1; me <= 3; ++me) {
- osolem_1.s[kg + (me << 2) - 5] = 0.;
- for (lf = 1; lf <= 3; ++lf) {
- osolem_1.s[kg + (me << 2) - 5] += vv[kg + lf * 3 - 4] * bb[lf
- + me * 3 - 4];
+ }
+ for (kg = 1; kg <= 3; ++kg) {
+ for (me = 1; me <= 3; ++me) {
+ osolem_1.s[kg + (me << 2) - 5] = 0.;
+ for (lf = 1; lf <= 3; ++lf) {
+ osolem_1.s[kg + (me << 2) - 5] += vv[kg + lf * 3 - 4] * bb[lf
+ +
+ me * 3 -
+ 4];
/* L190: */
- }
+ }
/* L180: */
- }
+ }
/* L170: */
- }
- osolem_1.s[15] = 1.;
- for (jd = 1; jd <= 3; ++jd) {
- osolem_1.s[(jd << 2) - 1] = 0.;
- osolem_1.s[jd + 11] = 0.;
+ }
+ osolem_1.s[15] = 1.;
+ for (jd = 1; jd <= 3; ++jd) {
+ osolem_1.s[(jd << 2) - 1] = 0.;
+ osolem_1.s[jd + 11] = 0.;
/* L200: */
- }
+ }
/* ----------------------------------------------------------------------- */
/* INVERT TRANSFORMATION MATRIX S AND PU RESULT IN SINV */
- *ier = 3;
- invs_(osolem_1.s, osolem_1.sinv, ier);
- *ier = 0;
- if (*ier != 0) {
- goto L999;
- }
- osolem_1.iok = 123;
+ *ier = 3;
+ invs_(osolem_1.s, osolem_1.sinv, ier);
+ *ier = 0;
+ if (*ier != 0) {
+ goto L999;
+ }
+ osolem_1.iok = 123;
/* --------------------------------------------------------------------------- */
/* SORTIE */
L999:
- if (*ier != 0) {
- erreso_(&imod, ier);
- }
- return 0;
-} /* setrlp_ */
+ if (*ier != 0) {
+ erreso_(&imod, ier);
+ }
+ return 0;
+} /* setrlp_ */
/* =========================================================================== */
-/* Subroutine */ int rl2spv_(doublereal *qhkl, doublereal *qt, doublereal *qm,
- doublereal *qs, integer *ier)
+/* Subroutine */ int rl2spv_(doublereal * qhkl, doublereal * qt,
+ doublereal * qm,
+ doublereal * qs, integer * ier)
{
- /* System generated locals */
- doublereal d__1;
+ /* System generated locals */
+ doublereal d__1;
- /* Builtin functions */
- double sqrt(doublereal);
+ /* Builtin functions */
+ double sqrt(doublereal);
- /* Local variables */
- static integer id, je;
+ /* Local variables */
+ static integer id, je;
/* ========================================= */
@@ -302,61 +305,62 @@ L999:
/* --------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------- */
/* INIT AND TEST IF TRANSFO MATRICES ARE OK */
- /* Parameter adjustments */
- --qt;
- --qhkl;
+ /* Parameter adjustments */
+ --qt;
+ --qhkl;
- /* Function Body */
- *ier = 1;
- if (osolem_1.iok != 123) {
- goto L999;
- }
- *ier = 0;
+ /* Function Body */
+ *ier = 1;
+ if (osolem_1.iok != 123) {
+ goto L999;
+ }
+ *ier = 0;
/* ----------------------------------------------------------------------- */
- for (id = 1; id <= 3; ++id) {
- qt[id] = 0.;
- for (je = 1; je <= 3; ++je) {
- qt[id] += qhkl[je] * osolem_1.s[id + (je << 2) - 5];
+ for (id = 1; id <= 3; ++id) {
+ qt[id] = 0.;
+ for (je = 1; je <= 3; ++je) {
+ qt[id] += qhkl[je] * osolem_1.s[id + (je << 2) - 5];
/* L20: */
- }
+ }
/* L10: */
- }
- *ier = 2;
- if (abs(qt[3]) > 1e-4) {
- goto L999;
- }
- *ier = 0;
- *qs = 0.;
- for (id = 1; id <= 3; ++id) {
+ }
+ *ier = 2;
+ if (abs(qt[3]) > 1e-4) {
+ goto L999;
+ }
+ *ier = 0;
+ *qs = 0.;
+ for (id = 1; id <= 3; ++id) {
/* Computing 2nd power */
- d__1 = qt[id];
- *qs += d__1 * d__1;
+ d__1 = qt[id];
+ *qs += d__1 * d__1;
/* L30: */
- }
- if (*qs < 1e-8) {
- *ier = 3;
- } else {
- *qm = sqrt(*qs);
- }
+ }
+ if (*qs < 1e-8) {
+ *ier = 3;
+ } else {
+ *qm = sqrt(*qs);
+ }
/* --------------------------------------------------------------------------- */
L999:
- return 0;
-} /* rl2spv_ */
+ return 0;
+} /* rl2spv_ */
/* =========================================================================== */
-/* Subroutine */ int sp2rlv_(doublereal *qhkl, doublereal *qt, doublereal *qm,
- doublereal *qs, integer *ier)
+/* Subroutine */ int sp2rlv_(doublereal * qhkl, doublereal * qt,
+ doublereal * qm,
+ doublereal * qs, integer * ier)
{
- /* System generated locals */
- doublereal d__1;
+ /* System generated locals */
+ doublereal d__1;
- /* Builtin functions */
- double sqrt(doublereal);
+ /* Builtin functions */
+ double sqrt(doublereal);
- /* Local variables */
- static integer id, je;
+ /* Local variables */
+ static integer id, je;
/* ========================================= */
@@ -384,59 +388,60 @@ L999:
/* --------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------- */
/* INIT AND TEST IF TRANSFO MATRICES ARE OK */
- /* Parameter adjustments */
- --qt;
- --qhkl;
+ /* Parameter adjustments */
+ --qt;
+ --qhkl;
- /* Function Body */
- *ier = 1;
- if (osolem_1.iok != 123) {
- goto L999;
- }
- *ier = 2;
- if (abs(qt[3]) > 1e-4) {
- goto L999;
- }
- *ier = 0;
+ /* Function Body */
+ *ier = 1;
+ if (osolem_1.iok != 123) {
+ goto L999;
+ }
+ *ier = 2;
+ if (abs(qt[3]) > 1e-4) {
+ goto L999;
+ }
+ *ier = 0;
/* ----------------------------------------------------------------------- */
- *qs = 0.;
- for (id = 1; id <= 3; ++id) {
+ *qs = 0.;
+ for (id = 1; id <= 3; ++id) {
/* Computing 2nd power */
- d__1 = qt[id];
- *qs += d__1 * d__1;
+ d__1 = qt[id];
+ *qs += d__1 * d__1;
/* L10: */
- }
- if (*qs < 1e-8) {
- *ier = 3;
- } else {
- *qm = sqrt(*qs);
- }
+ }
+ if (*qs < 1e-8) {
+ *ier = 3;
+ } else {
+ *qm = sqrt(*qs);
+ }
/* ----------------------------------------------------------------------- */
- for (id = 1; id <= 3; ++id) {
- qhkl[id] = 0.;
- for (je = 1; je <= 3; ++je) {
- qhkl[id] += osolem_1.sinv[id + (je << 2) - 5] * qt[je];
+ for (id = 1; id <= 3; ++id) {
+ qhkl[id] = 0.;
+ for (je = 1; je <= 3; ++je) {
+ qhkl[id] += osolem_1.sinv[id + (je << 2) - 5] * qt[je];
/* L30: */
- }
-/* L20: */
}
+/* L20: */
+ }
/* --------------------------------------------------------------------------- */
L999:
- return 0;
-} /* sp2rlv_ */
+ return 0;
+} /* sp2rlv_ */
/* ========================================================================== */
-/* Subroutine */ int invs_(doublereal *s, doublereal *sinv, integer *ier)
+/* Subroutine */ int invs_(doublereal * s, doublereal * sinv,
+ integer * ier)
{
- /* Initialized data */
+ /* Initialized data */
- static integer m[3] = { 2,3,1 };
- static integer n[3] = { 3,1,2 };
+ static integer m[3] = { 2, 3, 1 };
+ static integer n[3] = { 3, 1, 2 };
- static integer id, je, mi, mj, ni, nj;
- static doublereal det;
+ static integer id, je, mi, mj, ni, nj;
+ static doublereal det;
/* ============================== */
@@ -453,58 +458,61 @@ L999:
/* Define the dummy arguments */
/* ------------------------------------------------------------------ */
- /* Parameter adjustments */
- sinv -= 5;
- s -= 5;
+ /* Parameter adjustments */
+ sinv -= 5;
+ s -= 5;
- /* Function Body */
+ /* Function Body */
/* ------------------------------------------------------------------ */
- *ier = 0;
- for (id = 1; id <= 4; ++id) {
- for (je = 1; je <= 4; ++je) {
- sinv[id + (je << 2)] = 0.;
+ *ier = 0;
+ for (id = 1; id <= 4; ++id) {
+ for (je = 1; je <= 4; ++je) {
+ sinv[id + (je << 2)] = 0.;
/* L20: */
- }
+ }
/* L10: */
- }
- det = 0.;
- for (id = 1; id <= 3; ++id) {
- for (je = 1; je <= 3; ++je) {
- mi = m[id - 1];
- mj = m[je - 1];
- ni = n[id - 1];
- nj = n[je - 1];
- sinv[je + (id << 2)] = s[mi + (mj << 2)] * s[ni + (nj << 2)] - s[
- ni + (mj << 2)] * s[mi + (nj << 2)];
+ }
+ det = 0.;
+ for (id = 1; id <= 3; ++id) {
+ for (je = 1; je <= 3; ++je) {
+ mi = m[id - 1];
+ mj = m[je - 1];
+ ni = n[id - 1];
+ nj = n[je - 1];
+ sinv[je + (id << 2)] =
+ s[mi + (mj << 2)] * s[ni + (nj << 2)] - s[ni +
+ (mj << 2)] * s[mi +
+ (nj <<
+ 2)];
/* L40: */
- }
- det += s[id + 4] * sinv[(id << 2) + 1];
+ }
+ det += s[id + 4] * sinv[(id << 2) + 1];
/* L30: */
- }
- if (abs(det) < 1e-6) {
- *ier = 1;
- } else {
- for (id = 1; id <= 3; ++id) {
- for (je = 1; je <= 3; ++je) {
- sinv[id + (je << 2)] /= det;
+ }
+ if (abs(det) < 1e-6) {
+ *ier = 1;
+ } else {
+ for (id = 1; id <= 3; ++id) {
+ for (je = 1; je <= 3; ++je) {
+ sinv[id + (je << 2)] /= det;
/* L70: */
- }
+ }
/* L60: */
- }
}
- sinv[20] = 1.;
- return 0;
-} /* invs_ */
+ }
+ sinv[20] = 1.;
+ return 0;
+} /* invs_ */
/* ========================================================================= */
-/* Subroutine */ int erreso_(integer *module, integer *ier)
+/* Subroutine */ int erreso_(integer * module, integer * ier)
{
- /* System generated locals */
- integer i__1;
+ /* System generated locals */
+ integer i__1;
- /* Local variables */
- static integer lmod, lier;
+ /* Local variables */
+ static integer lmod, lier;
/* ============================= */
@@ -524,15 +532,12 @@ L999:
/* --------------------------------------------------------------------------- */
/* Computing MIN */
- i__1 = max(*ier,1);
- lier = min(i__1,4);
+ i__1 = max(*ier, 1);
+ lier = min(i__1, 4);
/* Computing MIN */
- i__1 = max(*module,1);
- lmod = min(i__1,3);
+ i__1 = max(*module, 1);
+ lmod = min(i__1, 3);
/* WRITE(6,501) MESER(LIER,LMOD) */
/* 501 FORMAT(A) */
- return 0;
-} /* erreso_ */
-
-
-
+ return 0;
+} /* erreso_ */
diff --git a/cryst.c b/cryst.c
deleted file mode 100644
index 5ae01f8b..00000000
--- a/cryst.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*---------------------------------------------------------------------------
- C r y s t
-
- This is a library of crystallographic utility routines for four
- circle diffractometers. It deals with all sorts of rotations and
- stuff. This is based on code originally developed by John Allibon
- at ILL and reimplemented in C using a matrix-library.
-
- Mark Koennecke, July 2000
-----------------------------------------------------------------------------*/
-#include
-#include
-#include
-#include
-#include "matrix/matrix.h"
-#include "cryst.h"
-
-#define PIR 57.30
-
-/*-------------------------------------------------------------------------
- chimat, calculate chi rotation matrix. The input angle is in degrees.
- The setting is Busing & Levy.
---------------------------------------------------------------------------*/
-
-MATRIX chimat(double dAngle)
-{
- MATRIX res;
- double dChi;
-
- res = mat_creat(3,3,ZERO_MATRIX);
- dChi = dAngle/PIR;
-
- res[0][0] = cos(dChi);
- res[0][2] = sin(dChi);
- res[1][1] = 1.;
- res[2][0] = -res[0][2];
- res[2][2] = res[0][0];
-
- return res;
-}
-
-
-/*-------------------------------------------------------------------------
- phimat, calculate phi rotation matrix. The input angle is in degrees.
- The setting is Busing & Levy.
---------------------------------------------------------------------------*/
-
-MATRIX phimat(double dAngle)
-{
- MATRIX res;
- double dPhi;
-
- res = mat_creat(3,3,ZERO_MATRIX);
- dPhi = dAngle/PIR;
-
- res[0][0] = cos(dPhi);
- res[0][1] = sin(dChi);
- res[2][2] = 1.;
- res[1][0] = -res[0][1];
- res[1][1] = res[0][0];
-
- return res;
-}
-/*-------------------------------------------------------------------------
- psimat, calculate psi rotation matrix. The input angle is in degrees.
- The setting is Busing & Levy.
---------------------------------------------------------------------------*/
-
-MATRIX psimat(double dAngle)
-{
- MATRIX res;
- double dPsi;
-
- res = mat_creat(3,3,ZERO_MATRIX);
- dPsi = dAngle/PIR;
-
- res[0][0] = 1.;
- res[1][1] = cos(dPsi);
- res[1][2] = -sin(dPsi);
- res[2][1] = -res[1][2];
- res[2][2] = res[1][1];
-
- return res;
-}
-
-/*-------------------------------------------------------------------------
- diffFromAngles calculates the diffraction vector from two theta, omega
- chi and phi. The angled need not be bissecting but it is assumed that
- the diffraction vector is in the equatorial plane.
---------------------------------------------------------------------------*/
-
-MATRIX diffFromAngles(double wave, double tth, double om,
- double chi, double phi)
-{
- MATRIX res, rot, dum, z;
- double dTh;
-
- dTh = (tth/2.)/PIR;
- res = mat_creat(3,1,ZERO_MATRIX);
- res[0][0] = (2.*sin(dTh)*cos(dTh))/wave;
- res[1][0] = (-2. *sin(dTh)*sin(dTh))/wave;
-
- /* undo omega rotation */
- rot = phimat(om);
- dum = mat_tran(rot);
- mat_free(rot);
- z = mat_mul(dum,res);
- mat_free(dum);
- mat_free(res);
-
- /* result is now z */
-
-}
-
diff --git a/d_mod.c b/d_mod.c
index 3766d9fa..6c667a24 100644
--- a/d_mod.c
+++ b/d_mod.c
@@ -6,7 +6,8 @@ double drem();
#else
double floor();
#endif
-double d_mod(x,y) doublereal *x, *y;
+double d_mod(x, y)
+doublereal *x, *y;
#else
#ifdef IEEE_drem
double drem(double, double);
@@ -17,30 +18,29 @@ double drem(double, double);
extern "C" {
#endif
#endif
-double d_mod(doublereal *x, doublereal *y)
+ double d_mod(doublereal * x, doublereal * y)
#endif
-{
+ {
#ifdef IEEE_drem
- double xa, ya, z;
- if ((ya = *y) < 0.)
- ya = -ya;
- z = drem(xa = *x, ya);
- if (xa > 0) {
- if (z < 0)
- z += ya;
- }
- else if (z > 0)
- z -= ya;
- return z;
+ double xa, ya, z;
+ if ((ya = *y) < 0.)
+ ya = -ya;
+ z = drem(xa = *x, ya);
+ if (xa > 0) {
+ if (z < 0)
+ z += ya;
+ } else if (z > 0)
+ z -= ya;
+ return z;
#else
- double quotient;
- if( (quotient = *x / *y) >= 0)
- quotient = floor(quotient);
- else
- quotient = -floor(-quotient);
- return(*x - (*y) * quotient );
+ double quotient;
+ if ((quotient = *x / *y) >= 0)
+ quotient = floor(quotient);
+ else
+ quotient = -floor(-quotient);
+ return (*x - (*y) * quotient);
#endif
-}
+ }
#ifdef __cplusplus
}
#endif
diff --git a/d_sign.c b/d_sign.c
index d06e0d19..6f05e712 100644
--- a/d_sign.c
+++ b/d_sign.c
@@ -4,15 +4,15 @@ extern "C" {
#endif
#ifdef KR_headers
-double d_sign(a,b) doublereal *a, *b;
+ double d_sign(a, b) doublereal *a, *b;
#else
-double d_sign(doublereal *a, doublereal *b)
+ double d_sign(doublereal * a, doublereal * b)
#endif
-{
-double x;
-x = (*a >= 0 ? *a : - *a);
-return( *b >= 0 ? x : -x);
-}
+ {
+ double x;
+ x = (*a >= 0 ? *a : -*a);
+ return (*b >= 0 ? x : -x);
+ }
#ifdef __cplusplus
}
#endif
diff --git a/danu.c b/danu.c
index e1978362..8354ccd8 100644
--- a/danu.c
+++ b/danu.c
@@ -51,11 +51,11 @@
#include "danu.h"
/* ------------------ the data structure ----------------------------------*/
- typedef struct __DataNumber {
- pObjectDescriptor pDes;
- pICallBack pCall;
- char *pFileName;
- } DataNumber;
+typedef struct __DataNumber {
+ pObjectDescriptor pDes;
+ pICallBack pCall;
+ char *pFileName;
+} DataNumber;
/*----------------------------------------------------------------------*/
static int readDataNumber(pDataNumber self)
{
@@ -63,356 +63,329 @@ static int readDataNumber(pDataNumber self)
int iNum = 0;
/* open file */
- fd = fopen(self->pFileName,"r");
- if(!fd)
- {
+ fd = fopen(self->pFileName, "r");
+ if (!fd) {
return -1;
}
-
+
/* get and increment number */
- fscanf(fd,"%d",&iNum);
+ fscanf(fd, "%d", &iNum);
fclose(fd);
return iNum;
}
+
/*-----------------------------------------------------------------------*/
static int writeDataNumber(pDataNumber self, int iNum)
{
FILE *fd = NULL;
/* reopen for rewriting */
- fd = fopen(self->pFileName,"w");
- if(fd == NULL)
- {
+ fd = fopen(self->pFileName, "w");
+ if (fd == NULL) {
return -1;
}
-
+
/* write file and leave */
- fprintf(fd," %d \n",iNum);
- fprintf(fd,"NEVER, EVER modify or delete this file\n");
+ fprintf(fd, " %d \n", iNum);
+ fprintf(fd, "NEVER, EVER modify or delete this file\n");
fprintf(fd,
- "You'll risk eternal damnation and a reincarnation as a cockroach!\n");
+ "You'll risk eternal damnation and a reincarnation as a cockroach!\n");
fclose(fd);
return 1;
}
+
/*------------------- The CallBack function for interest ------------------*/
- static int InterestCallback(int iEvent, void *pEvent, void *pUser,
- commandContext cc)
- {
- pDataNumber self = NULL;
- SConnection *pCon = NULL;
- char pBueffel[132];
- int iNum;
-
- if(iEvent != VALUECHANGE)
- {
- return 1;
- }
-
- assert(pEvent);
- assert(pUser);
-
- pCon = (SConnection *)pUser;
- self = (pDataNumber)pEvent;
-
- /*
- read number
- */
- iNum = readDataNumber(self);
- if(iNum > 0)
- {
- snprintf(pBueffel,131,"sicsdatanumber = %d", iNum);
- SCWriteInContext(pCon,pBueffel,eValue,cc);
- }
- return 1;
- }
-/*-------------------------------------------------------------------------*/
- pDataNumber CreateDataNumber(char *pFileName)
- {
- pDataNumber pNew = NULL;
- FILE *fd = NULL;
-
- pNew = (pDataNumber)malloc(sizeof(DataNumber));
- if(!pNew)
- {
- return NULL;
- }
- memset(pNew,0,sizeof(DataNumber));
-
- pNew->pDes = CreateDescriptor("DataNumber");
- pNew->pCall = CreateCallBackInterface();
- if(!pNew->pDes || !pNew->pCall)
- {
- free(pNew);
- return NULL;
- }
-
- /* check filename */
- fd = fopen(pFileName,"r");
- if(!fd)
- {
- printf("Serious error: cannot open file for Data Number!!!!\n");
- printf("I continue, but you should not write data files!\n");
- pNew->pFileName = strdup("default.num");
- return pNew;
- }
- fclose(fd);
- pNew->pFileName = strdup(pFileName);
- return pNew;
- }
-/*--------------------------------------------------------------------------*/
- void DeleteDataNumber(void *pData)
- {
- pDataNumber self = NULL;
-
- self = (pDataNumber)pData;
- assert(self);
-
- if(self->pDes)
- {
- DeleteDescriptor(self->pDes);
- }
- if(self->pCall)
- {
- DeleteCallBackInterface(self->pCall);
- self->pCall = NULL;
- }
- if(self->pFileName)
- {
- free(self->pFileName);
- }
- free(self);
- }
-/*-------------------------------------------------------------------------*/
- int IncrementDataNumber(pDataNumber self, int *iYear)
- {
- FILE *fd = NULL;
- int iNum;
- time_t iTime;
- struct tm *psTime;
-
-
- iNum = readDataNumber(self);
- if(iNum < 0)
- {
- return iNum;
- }
-
- iNum++;
-
- /* get year */
- iTime = time(NULL);
- psTime = localtime(&iTime);
- *iYear = psTime->tm_year + 1900;
-
- if(writeDataNumber(self,iNum) < 0)
- {
- return -1;
- }
-
- InvokeCallBack(self->pCall, VALUECHANGE, self);
-
- return iNum;
- }
-/*-------------------------------------------------------------------------*/
- int DecrementDataNumber(pDataNumber self)
- {
- FILE *fd = NULL;
- int iNum, currentThousand;
-
- iNum = readDataNumber(self);
- if(iNum < 0)
- {
- return iNum;
- }
-
- /*
- decrement DataNumber with restrictions:
- - not at all lower 0
- - do not understep a thousand boundary
- */
- currentThousand = (int)floor(iNum/1000.);
- iNum--;
- if((int)floor(iNum/1000.) < currentThousand)
- {
- iNum++;
- }
-
- if(writeDataNumber(self,iNum) < 0)
- {
- return -1;
- }
-
- return iNum;
- }
-/*------------------------------------------------------------------------*/
-int NewThousand(pDataNumber self)
+static int InterestCallback(int iEvent, void *pEvent, void *pUser)
{
- int iNum, currentThousand;
-
+ pDataNumber self = NULL;
+ SConnection *pCon = NULL;
+ char pBueffel[132];
+ int iNum;
+
+ pCon = (SConnection *) pUser;
+ if (pCon == NULL || !SCisConnected(pCon)) {
+ return -1;
+ }
+
+ if (iEvent != VALUECHANGE) {
+ return 1;
+ }
+
+ assert(pEvent);
+ assert(pUser);
+
+ self = (pDataNumber) pEvent;
+
+ /*
+ read number
+ */
iNum = readDataNumber(self);
- if(iNum < 0)
- {
+ if (iNum > 0) {
+ snprintf(pBueffel, 131, "sicsdatanumber = %d", iNum);
+ SCWrite(pCon, pBueffel, eValue);
+ }
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+pDataNumber CreateDataNumber(char *pFileName)
+{
+ pDataNumber pNew = NULL;
+ FILE *fd = NULL;
+
+ pNew = (pDataNumber) malloc(sizeof(DataNumber));
+ if (!pNew) {
+ return NULL;
+ }
+ memset(pNew, 0, sizeof(DataNumber));
+
+ pNew->pDes = CreateDescriptor("DataNumber");
+ pNew->pCall = CreateCallBackInterface();
+ if (!pNew->pDes || !pNew->pCall) {
+ free(pNew);
+ return NULL;
+ }
+
+ /* check filename */
+ fd = fopen(pFileName, "r");
+ if (!fd) {
+ printf("Serious error: cannot open file for Data Number!!!!\n");
+ printf("I continue, but you should not write data files!\n");
+ pNew->pFileName = strdup("default.num");
+ return pNew;
+ }
+ fclose(fd);
+ pNew->pFileName = strdup(pFileName);
+ return pNew;
+}
+
+/*--------------------------------------------------------------------------*/
+void DeleteDataNumber(void *pData)
+{
+ pDataNumber self = NULL;
+
+ self = (pDataNumber) pData;
+ assert(self);
+
+ if (self->pDes) {
+ DeleteDescriptor(self->pDes);
+ }
+ if (self->pCall) {
+ DeleteCallBackInterface(self->pCall);
+ self->pCall = NULL;
+ }
+ if (self->pFileName) {
+ free(self->pFileName);
+ }
+ free(self);
+}
+
+/*-------------------------------------------------------------------------*/
+int IncrementDataNumber(pDataNumber self, int *iYear)
+{
+ FILE *fd = NULL;
+ int iNum;
+ time_t iTime;
+ struct tm *psTime;
+
+
+ iNum = readDataNumber(self);
+ if (iNum < 0) {
return iNum;
}
-
- /* set to next thousand number */
- currentThousand = (int)floor(iNum/1000.);
- iNum = (currentThousand + 1)*1000;
- if(writeDataNumber(self,iNum) < 0)
- {
+ iNum++;
+
+ /* get year */
+ iTime = time(NULL);
+ psTime = localtime(&iTime);
+ *iYear = psTime->tm_year + 1900;
+
+ if (writeDataNumber(self, iNum) < 0) {
+ return -1;
+ }
+
+ InvokeCallBack(self->pCall, VALUECHANGE, self);
+
+ return iNum;
+}
+
+/*-------------------------------------------------------------------------*/
+int DecrementDataNumber(pDataNumber self)
+{
+ FILE *fd = NULL;
+ int iNum, currentThousand;
+
+ iNum = readDataNumber(self);
+ if (iNum < 0) {
+ return iNum;
+ }
+
+ /*
+ decrement DataNumber with restrictions:
+ - not at all lower 0
+ - do not understep a thousand boundary
+ */
+ currentThousand = (int) floor(iNum / 1000.);
+ iNum--;
+ if ((int) floor(iNum / 1000.) < currentThousand) {
+ iNum++;
+ }
+
+ if (writeDataNumber(self, iNum) < 0) {
return -1;
}
return iNum;
-}
-/*-------------------------------------------------------------------------*/
- int DNWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pDataNumber self = NULL;
- FILE *fd = NULL;
- int iNum, iYear;
- char pBueffel[512];
- long lID;
-
- self = (pDataNumber)pData;
- assert(self);
- assert(pCon);
-
- argtolower(argc,argv);
- if(argc < 2) /* value request */
- {
- iNum = readDataNumber(self);
- if(iNum < 0)
- {
- sprintf(pBueffel,"ERROR: cannot open file %s",self->pFileName);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- sprintf(pBueffel,"%s = %d",argv[0],iNum);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
-
- if(strcmp(argv[1],"incr") == 0)
- {
- iNum = IncrementDataNumber(self,&iYear);
- if(iNum > 0)
- {
- SCSendOK(pCon);
- return 1;
- }
- else
- {
- sprintf(pBueffel,"ERROR: cannot increment %s",argv[0]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- }
- if(strcmp(argv[1],"nextthousand") == 0)
- {
- if(!SCMatchRights(pCon,usMugger))
- {
- return 0;
- }
- iNum = NewThousand(self);
- if(iNum > 0)
- {
- SCSendOK(pCon);
- return 1;
- }
- else
- {
- sprintf(pBueffel,"ERROR: cannot increment %s",argv[0]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- }
- if(strcmp(argv[1],"interest") == 0)
- {
- lID = RegisterCallback(self->pCall, SCGetContext(pCon),
- VALUECHANGE, InterestCallback,
- pCon, NULL);
- SCRegister(pCon,pSics, self->pCall,lID);
- SCSendOK(pCon);
- return 1;
- }
- if(strcmp(argv[1],"uninterest") == 0)
- {
- RemoveCallback2(self->pCall,pCon);
- SCSendOK(pCon);
- }
-
- sprintf(pBueffel,"ERROR: unknown command %s supplied to %s",
- argv[1], argv[0]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
+}
+
/*------------------------------------------------------------------------*/
- int DEWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pDataNumber self = NULL;
- int iNum;
- char pBueffel[512];
-
- self = (pDataNumber)pData;
- assert(self);
- assert(pCon);
+int NewThousand(pDataNumber self)
+{
+ int iNum, currentThousand;
- if(SCMatchRights(pCon,usMugger))
- {
- iNum = DecrementDataNumber(self);
- snprintf(pBueffel,511,"Data file %d killed", iNum+1);
- SCWrite(pCon,pBueffel,eWarning);
- return 1;
- }
- else
- {
- SCWrite(pCon,"ERROR: you are not authorized to kill data files",
- eError);
- return 0;
- }
- }
+ iNum = readDataNumber(self);
+ if (iNum < 0) {
+ return iNum;
+ }
+
+ /* set to next thousand number */
+ currentThousand = (int) floor(iNum / 1000.);
+ iNum = (currentThousand + 1) * 1000;
+
+ if (writeDataNumber(self, iNum) < 0) {
+ return -1;
+ }
+
+ return iNum;
+}
/*-------------------------------------------------------------------------*/
- int DNFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pDataNumber self = NULL;
- char pBueffel[512];
- int iRet;
-
- if(argc < 3)
- {
- SCWrite(pCon,
- "ERROR: not enough arguments provided to make DataNumber",eError);
- return 0;
- }
-
- self = CreateDataNumber(argv[2]);
- if(!self)
- {
- SCWrite(pCon,"ERROR: no memory to create data number",eError);
- return 0;
- }
-
- iRet = AddCommand(pSics, argv[1],DNWrapper, DeleteDataNumber, self);
- if(!iRet)
- {
- sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- iRet = AddCommand(pSics,"killfile",DEWrapper,NULL, self);
- if(!iRet)
- {
- sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- return 1;
- }
+int DNWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pDataNumber self = NULL;
+ FILE *fd = NULL;
+ int iNum, iYear;
+ char pBueffel[512];
+ long lID;
-
+ self = (pDataNumber) pData;
+ assert(self);
+ assert(pCon);
+
+ argtolower(argc, argv);
+ if (argc < 2) { /* value request */
+ iNum = readDataNumber(self);
+ if (iNum < 0) {
+ snprintf(pBueffel,511, "ERROR: cannot open file %s", self->pFileName);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ sprintf(pBueffel, "%s = %d", argv[0], iNum);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ }
+
+ if (strcmp(argv[1], "incr") == 0) {
+ iNum = IncrementDataNumber(self, &iYear);
+ if (iNum > 0) {
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ sprintf(pBueffel, "ERROR: cannot increment %s", argv[0]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ }
+ if (strcmp(argv[1], "nextthousand") == 0) {
+ if (!SCMatchRights(pCon, usMugger)) {
+ return 0;
+ }
+ iNum = NewThousand(self);
+ if (iNum > 0) {
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ sprintf(pBueffel, "ERROR: cannot increment %s", argv[0]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ }
+ if (strcmp(argv[1], "interest") == 0) {
+ lID = RegisterCallback(self->pCall,
+ VALUECHANGE, InterestCallback,
+ SCCopyConnection(pCon), SCDeleteConnection);
+ SCSendOK(pCon);
+ return 1;
+ }
+ if (strcmp(argv[1], "uninterest") == 0) {
+ RemoveCallbackCon(self->pCall, pCon);
+ SCSendOK(pCon);
+ }
+
+ snprintf(pBueffel,511, "ERROR: unknown command %s supplied to %s",
+ argv[1], argv[0]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+int DEWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pDataNumber self = NULL;
+ int iNum;
+ char pBueffel[512];
+
+ self = (pDataNumber) pData;
+ assert(self);
+ assert(pCon);
+
+ if (SCMatchRights(pCon, usMugger)) {
+ iNum = DecrementDataNumber(self);
+ snprintf(pBueffel, 511, "Data file %d killed", iNum + 1);
+ SCWrite(pCon, pBueffel, eWarning);
+ return 1;
+ } else {
+ SCWrite(pCon, "ERROR: you are not authorized to kill data files",
+ eError);
+ return 0;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+int DNFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pDataNumber self = NULL;
+ char pBueffel[512];
+ int iRet;
+
+ if (argc < 3) {
+ SCWrite(pCon,
+ "ERROR: not enough arguments provided to make DataNumber",
+ eError);
+ return 0;
+ }
+
+ self = CreateDataNumber(argv[2]);
+ if (!self) {
+ SCWrite(pCon, "ERROR: no memory to create data number", eError);
+ return 0;
+ }
+
+ iRet = AddCommand(pSics, argv[1], DNWrapper, DeleteDataNumber, self);
+ if (!iRet) {
+ snprintf(pBueffel, 511,"ERROR: duplicate command %s not created", argv[1]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ iRet = AddCommand(pSics, "killfile", DEWrapper, NULL, self);
+ if (!iRet) {
+ snprintf(pBueffel, 511,"ERROR: duplicate command %s not created", argv[1]);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ return 1;
+}
diff --git a/danu.h b/danu.h
index 1e8c27d9..cddf4201 100644
--- a/danu.h
+++ b/danu.h
@@ -17,23 +17,23 @@
#line 15 "danu.w"
- typedef struct __DataNumber *pDataNumber;
+typedef struct __DataNumber *pDataNumber;
- pDataNumber CreateDataNumber(char *pFilename);
- void DeleteDataNumber(void *pData);
+pDataNumber CreateDataNumber(char *pFilename);
+void DeleteDataNumber(void *pData);
- int IncrementDataNumber(pDataNumber self, int *iYear);
+int IncrementDataNumber(pDataNumber self, int *iYear);
- int DecrementDataNumber(pDataNumber self);
+int DecrementDataNumber(pDataNumber self);
- int DNWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int DNWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
- int DEWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int DEWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
- int DNFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int DNFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
#line 67 "danu.w"
diff --git a/definealias.c b/definealias.c
index 5845cb9c..1f8b93e1 100644
--- a/definealias.c
+++ b/definealias.c
@@ -41,177 +41,219 @@
#include
#include
#include "fortify.h"
+#include "sics.h"
+#include "strlutil.h"
+#include "dynstring.h"
#include "definealias.h"
typedef struct __Aitem {
- struct __Aitem *pNext;
- char *pName;
- char *pCmd;
- } AliasItem;
+ struct __Aitem *pNext;
+ char *pName;
+ char *pCmd;
+} AliasItem;
/*------------------------------------------------------------------------*/
- char *TranslateAlias(AliasList *pAList, char *pCmd)
- {
- AliasItem *pAlias;
+char *TranslateAlias(AliasList * pAList, char *pCmd)
+{
+ AliasItem *pAlias;
- assert(pAList!=NULL && pCmd!=NULL);
+ assert(pAList != NULL && pCmd != NULL);
- pAlias=pAList->pFirst;
- while (pAlias!=NULL)
- {
- if (0 == strcmp(pAlias->pName, pCmd))
- {
- pCmd = pAlias->pCmd; /* note that there may be cascaded translations */
- }
- pAlias = pAlias->pNext;
+ pAlias = pAList->pFirst;
+ while (pAlias != NULL) {
+ if (0 == strcmp(pAlias->pName, pCmd)) {
+ pCmd = pAlias->pCmd; /* note that there may be cascaded translations */
}
- return(pCmd);
+ pAlias = pAlias->pNext;
}
+ return (pCmd);
+}
+
/*------------------------------------------------------------------------*/
- int RemoveAlias(AliasList *pAList, char *pCmd)
- {
- AliasItem *pAlias = NULL, *pPrev = NULL;
+int RemoveAlias(AliasList * pAList, char *pCmd)
+{
+ AliasItem *pAlias = NULL, *pPrev = NULL;
- assert(pAList!=NULL && pCmd!=NULL);
+ assert(pAList != NULL && pCmd != NULL);
- pPrev=(AliasItem *)pAList;
- pAlias=pAList->pFirst;
- while (pAlias != NULL && 0 != strcmp(pAlias->pName, pCmd))
- {
- pPrev = pAlias;
- pAlias = pAlias->pNext;
- }
- if (pAlias==NULL)
- {
- return 0; /* not found */
- }
+ pPrev = (AliasItem *) pAList;
+ pAlias = pAList->pFirst;
+ while (pAlias != NULL && 0 != strcmp(pAlias->pName, pCmd)) {
+ pPrev = pAlias;
+ pAlias = pAlias->pNext;
+ }
+ if (pAlias == NULL) {
+ return 0; /* not found */
+ }
- /* remove it */
- pPrev->pNext = pAlias->pNext;
+ /* remove it */
+ pPrev->pNext = pAlias->pNext;
+ free(pAlias->pName);
+ free(pAlias->pCmd);
+ free(pAlias);
+ return (1);
+}
+
+/*------------------------------------------------------------------------*/
+void FreeAliasList(AliasList * pAList)
+{
+ AliasItem *pAlias = NULL, *pNext = NULL;
+
+ assert(pAList != NULL);
+
+ pAlias = pAList->pFirst;
+ while (pAlias != NULL) {
+ pNext = pAlias->pNext;
free(pAlias->pName);
free(pAlias->pCmd);
free(pAlias);
- return(1);
- }
-/*------------------------------------------------------------------------*/
- void FreeAliasList(AliasList *pAList)
- {
- AliasItem *pAlias = NULL, *pNext = NULL;
-
- assert(pAList!=NULL);
-
- pAlias=pAList->pFirst;
- while (pAlias != NULL)
- {
- pNext=pAlias->pNext;
- free(pAlias->pName);
- free(pAlias->pCmd);
- free(pAlias);
- pAlias = pNext;
- }
- }
-/*------------------------------------------------------------------------*/
- char *CreateAlias(AliasList *pAList, char *pName, char *pTranslation)
- { /* arguments must be lower case */
- AliasItem *pAlias = NULL, *pNew = NULL, *pTail = NULL;
- char *pCmd;
-
- /* translate 2nd argument */
- pCmd=TranslateAlias(pAList, pTranslation);
- if (0==strcmp(pName, pCmd)) /* translation matches */
- {
- return "recursive alias not allowed";
- }
-
- /* find last element pTail and check that alias does not yet exist */
- pTail = (AliasItem *)pAList;
- pAlias = pAList->pFirst;
- while (pAlias!=NULL)
- {
- pTail=pAlias;
- if (0 == strcmp(pAlias->pName, pName))
- {
- return "alias already exists";
- }
- pAlias = pAlias->pNext;
- }
-
- /* allocate the list entry */
- pNew = malloc(sizeof(AliasItem));
- if (pNew!=NULL)
- {
- pNew->pNext = NULL;
- pNew->pName = strdup(pName);
- if (pNew->pName!=NULL)
- {
- pNew->pCmd = strdup(pCmd);
- if (pNew->pCmd!=NULL)
- {
- /* insert at tail */
- pTail->pNext = pNew;
- return NULL; /* o.k. */
- }
- }
- }
- return "not enough memory to create an alias";
-
+ pAlias = pNext;
}
+}
/*------------------------------------------------------------------------*/
- int DefineAlias(pSConnection pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- char pBueffel[256];
- int iRet;
- CommandList *pCom = NULL;
- char *pErr;
+char *CreateAlias(AliasList * pAList, char *pName, char *pTranslation)
+{ /* arguments must be lower case */
+ AliasItem *pAlias = NULL, *pNew = NULL, *pTail = NULL;
+ char *pCmd;
- if(!SCMatchRights(pCon,usMugger))
- {
- SCWrite(pCon,"ERROR: only managers may define aliases",
- eError);
- return 0;
+ /* translate 2nd argument */
+ pCmd = TranslateAlias(pAList, pTranslation);
+ if (0 == strcmp(pName, pCmd)) { /* translation matches */
+ return "recursive alias not allowed";
+ }
+
+ /* find last element pTail and check that alias does not yet exist */
+ pTail = (AliasItem *) pAList;
+ pAlias = pAList->pFirst;
+ while (pAlias != NULL) {
+ pTail = pAlias;
+ if (0 == strcmp(pAlias->pName, pName)) {
+ return "alias already exists";
}
+ pAlias = pAlias->pNext;
+ }
- argtolower(argc,argv);
-
- if(argc == 2) /* remove case */
- {
- iRet=RemoveAlias(&pSics->AList, argv[1]);
- if (iRet==0)
- {
- SCWrite(pCon,"ERROR: alias not found",
- eError);
- return 0;
+ /* allocate the list entry */
+ pNew = malloc(sizeof(AliasItem));
+ if (pNew != NULL) {
+ pNew->pNext = NULL;
+ pNew->pName = strdup(pName);
+ if (pNew->pName != NULL) {
+ pNew->pCmd = strdup(pCmd);
+ if (pNew->pCmd != NULL) {
+ /* insert at tail */
+ pTail->pNext = pNew;
+ return NULL; /* o.k. */
}
- return 1;
}
- if(argc != 3)
- {
- SCWrite(pCon,"ERROR: illegal number of arguments to DefineAlias",
- eError);
- return 0;
+ }
+ return "not enough memory to create an alias";
+
+}
+
+/*------------------------------------------------------------------------*/
+int DefineAlias(pSConnection pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ char arg1[256];
+ char arg2[256];
+ int iRet;
+ CommandList *pCom = NULL;
+ char *pErr;
+ char *pCmd;
+ AliasItem *pAlias;
+ pDynString str;
+
+ if (argc == 3) {
+ strlcpy(arg2, argv[2], sizeof arg2);
+ strtolower(arg2);
+ } else if (argc > 3 || argc < 2) {
+ SCWrite(pCon, "ERROR: illegal number of arguments to DefineAlias",
+ eError);
+ return 0;
+ }
+
+ strlcpy(arg1, argv[1], sizeof arg1);
+ strtolower(arg1);
+
+ if (argc == 3 && strcasecmp(arg1, "-show") == 0) {
+ for (pAlias = pSics->AList.pFirst; pAlias!=NULL; pAlias=pAlias->pNext) {
+ if (0 == strcmp(pAlias->pName, arg2)) {
+ SCWrite(pCon, pAlias->pCmd, eValue);
+ return 1;
+ }
}
-
- pCom = FindCommand(pSics, argv[1]);
- if (pCom!=NULL)
- {
- SCWrite(pCon,"ERROR: an alias must not overwrite a command",
- eError);
- return 0;
- }
-
- /* remove the old alias, if any */
- RemoveAlias(&pSics->AList, argv[1]);
-
- pErr=CreateAlias(&pSics->AList, argv[1], argv[2]);
- if (pErr!=NULL)
- {
- sprintf(pBueffel,"ERROR: %s", pErr);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
+ SCWrite(pCon, "NA", eValue);
return 1;
}
+ if (argc == 2 && strcasecmp(arg1, "-list") == 0) {
+ str = CreateDynString(60,63);
+ for (pAlias = pSics->AList.pFirst; pAlias!=NULL; pAlias=pAlias->pNext) {
+ DynStringConcat(str, pAlias->pName);
+ DynStringConcat(str, " ");
+ }
+ if (GetDynStringLength(str) > 0) {
+ DynStringBackspace(str);
+ }
+ SCWrite(pCon, GetCharArray(str), eValue);
+ DeleteDynString(str);
+ return 1;
+ }
+
+ if (argc == 3 && strcasecmp(arg1, "-translate") == 0) {
+ pCmd = TranslateAlias(&pSics->AList, arg2);
+ SCWrite(pCon, pCmd, eValue);
+ return 1;
+ }
+
+ if (!SCMatchRights(pCon, usMugger)) {
+ SCWrite(pCon, "ERROR: only managers may define aliases", eError);
+ return 0;
+ }
+
+ if (argc == 2) { /* remove case */
+ iRet = RemoveAlias(&pSics->AList, arg1);
+ if (iRet == 0) {
+ SCWrite(pCon, "ERROR: alias not found", eError);
+ return 0;
+ }
+ return 1;
+ }
+
+ pCom = FindCommand(pSics, arg1);
+ /* do not complain when the command was a translated alias */
+ if (pCom != NULL && strcmp(pCom->pName, arg1) == 0) {
+ SCWrite(pCon, "ERROR: an alias must not overwrite a command", eError);
+ return 0;
+ }
+
+ /* remove the old alias, if any */
+ RemoveAlias(&pSics->AList, arg1);
+
+ pErr = CreateAlias(&pSics->AList, arg1, arg2);
+ if (pErr != NULL) {
+ SCPrintf(pCon, eError, "ERROR: %s", pErr);
+ return 0;
+ }
+
+ return 1;
+}
+/*------------------------------------------------------------------------*/
+static int AliasSaver(void *object, char *name, FILE * fil)
+{
+ AliasItem *pAlias;
+
+ for (pAlias = pServ->pSics->AList.pFirst; pAlias != NULL; pAlias = pAlias->pNext) {
+ fprintf(fil, "definealias %s %s\n", pAlias->pName, pAlias->pCmd);
+ }
+ return 1;
+}
+/*------------------------------------------------------------------------*/
+void DefineAliasInit(void) {
+ Dummy *as;
+ as = CreateDummy("alias saver");
+ as->pDescriptor->SaveStatus = AliasSaver;
+ AddCommandWithFlag(pServ->pSics, "definealias", DefineAlias, KillDummy, as, 0);
+}
diff --git a/definealias.h b/definealias.h
index 9fbb5a55..a9d17adc 100644
--- a/definealias.h
+++ b/definealias.h
@@ -17,77 +17,77 @@
---------------------------------------------------------------------------*/
#ifndef DEFINE_ALIAS
#define DEFINE_ALIAS
-#include "conman.h"
+#include "conman.h"
#include "definealias.i"
/*---------------------------------------------------------------------------*/
- char *TranslateAlias(AliasList *pAList, char *pCmd);
+char *TranslateAlias(AliasList * pAList, char *pCmd);
/*
- translate the command *pCmd
- - the translation may go through several steps
- - if no translation is found, the return value is equal to pCmd
- - no strings are copied
- - the return value becomes invalid when the corresponding alias is removed
- - *pCmd must be lowercase
- */
+ translate the command *pCmd
+ - the translation may go through several steps
+ - if no translation is found, the return value is equal to pCmd
+ - no strings are copied
+ - the return value becomes invalid when the corresponding alias is removed
+ - *pCmd must be lowercase
+ */
/*---------------------------------------------------------------------------*/
- int RemoveAlias(AliasList *pAList, char *pCmd);
+int RemoveAlias(AliasList * pAList, char *pCmd);
/*
- remove the alias *pCmd
- - returns 1 when the alias existed, 0 otherwise
- - *pCmd must be lowercase
- */
+ remove the alias *pCmd
+ - returns 1 when the alias existed, 0 otherwise
+ - *pCmd must be lowercase
+ */
/*---------------------------------------------------------------------------*/
- void FreeAliasList(AliasList *pAList);
+void FreeAliasList(AliasList * pAList);
/*
- dispose the alias list
- */
+ dispose the alias list
+ */
/*---------------------------------------------------------------------------*/
- char *CreateAlias(AliasList *pAList, char *pName, char *pTranslation);
+char *CreateAlias(AliasList * pAList, char *pName, char *pTranslation);
/*
- create a new alias *pName with the translation *pTranslation
+ create a new alias *pName with the translation *pTranslation
- - the alias *pName must not yet exist
- - *pTranslation is translated first
- - recursive definitions are prohibited
- - *pName and *pTranslation must be lowercase
+ - the alias *pName must not yet exist
+ - *pTranslation is translated first
+ - recursive definitions are prohibited
+ - *pName and *pTranslation must be lowercase
- if the creation is successful, the return value is NULL, otherwise
- it points to one of the following error messages:
+ if the creation is successful, the return value is NULL, otherwise
+ it points to one of the following error messages:
- "recursive alias not allowed"
- "alias already exists"
- "not enough memory to create an alias"
+ "recursive alias not allowed"
+ "alias already exists"
+ "not enough memory to create an alias"
- */
+ */
/*---------------------------------------------------------------------------*/
- int DefineAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
+int DefineAlias(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
/* this command requires manager privileges
- argv[1]: the alias to define
- - must not be a proper SICS command
- - if an alias with this name exists already, it is removed first
+ argv[1]: the alias to define
+ - must not be a proper SICS command
+ - if an alias with this name exists already, it is removed first
- argv[2]: the original command
- - if omitted, the alias is removed
- - if it is an alias the definiton refers to it's translation
- - may be an unknown command (probably defined later)
+ argv[2]: the original command
+ - if omitted, the alias is removed
+ - if it is an alias the definiton refers to it's translation
+ - may be an unknown command (probably defined later)
- - AddCommand removes an eventual alias matching the command name
+ - AddCommand removes an eventual alias matching the command name
- - RemoveCommand does not remove it's aliases
- Trying to use an alias of a removed command leads to the error message
- "object > ... < NOT found"
+ - RemoveCommand does not remove it's aliases
+ Trying to use an alias of a removed command leads to the error message
+ "object > ... < NOT found"
- - trying to define a recursive alias leads the error message
- "recursive alias not allowed"
- */
+ - trying to define a recursive alias leads the error message
+ "recursive alias not allowed"
+ */
#endif
diff --git a/defines.h b/defines.h
index 064a4023..bce64662 100644
--- a/defines.h
+++ b/defines.h
@@ -8,8 +8,8 @@
/_|__| A.Reitsma, Delft, Nederland.
/ | \ --------------------------------------------------------------- */
-#include /* for malloc() prototype */
-#include /* for memcpy() prototype */
+#include /* for malloc() prototype */
+#include /* for memcpy() prototype */
#include "fortify.h"
#define MALLOC(size,type) (type *) malloc( (size) * sizeof( type ))
diff --git a/devexec.c b/devexec.c
index f59ffb2b..5aad35f2 100644
--- a/devexec.c
+++ b/devexec.c
@@ -9,9 +9,15 @@
revised for use with tasker: Mark Koennecke, September 1997
Locking added: Mark Koennecke, August 2002
- Refactored and instrumentation for instrument staticstics added.
+ Refactored and instrumentation for instrument statistics added.
Mark Koennecke, July 2006
+ Reworked to use copied connection objects instead of context pushes.
+ Mark Koennecke, January 2009
+
+ Modified to accommodate run levels
+ Mark Koennecke, April 2009
+
Copyright:
Labor fuer Neutronenstreuung
@@ -67,1397 +73,1406 @@
/*======================== Logging stuff ==================================*/
static FILE *devLog = NULL;
/*-------------------------------------------------------------------------*/
-int openDevexecLog(){
- char *fileName = NULL;
- char fileBuffer[1024];
- time_t iDate;
- struct tm *psTime;
+int openDevexecLog()
+{
+ char *fileName = NULL;
+ char fileBuffer[1024];
+ time_t iDate;
+ struct tm *psTime;
-
- if(devLog == NULL){
- fileName = IFindOption(pSICSOptions,"devexeclog");
- if(fileName != NULL){
- strcpy(fileBuffer,fileName);
- } else {
- iDate = time(NULL);
- psTime = localtime(&iDate);
- fileBuffer[0] = '\0';
- fileName = getenv("HOME");
- if(fileName != NULL){
- snprintf(fileBuffer,1023,"%s/log/devexec%4.4d.log",
- fileName, psTime->tm_year + 1900);
- }
- }
- devLog = fopen(fileBuffer,"a+");
- }
- if(devLog == NULL){
- return 0;
+
+ if (devLog == NULL) {
+ fileName = IFindOption(pSICSOptions, "devexeclog");
+ if (fileName != NULL) {
+ strlcpy(fileBuffer, fileName,1024);
} else {
- return 1;
+ iDate = time(NULL);
+ psTime = localtime(&iDate);
+ fileBuffer[0] = '\0';
+ fileName = getenv("HOME");
+ if (fileName != NULL) {
+ snprintf(fileBuffer, 1023, "%s/log/devexec%4.4d.log",
+ fileName, psTime->tm_year + 1900);
+ }
}
+ devLog = fopen(fileBuffer, "a+");
+ }
+ if (devLog == NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
}
+
/*-------------------------------------------------------------------------*/
-void DevexecLog(char *operation, char *device) {
- struct timeval tv;
- struct timezone tm;
- if(devLog != NULL){
- gettimeofday(&tv,&tm);
- fprintf(devLog, "DEVEXEC:%s:%s:%ld:%ld\n",operation,device,
- (long)tv.tv_sec, (long)tv.tv_usec);
- fflush(devLog);
- }
+void DevexecLog(char *operation, char *device)
+{
+ struct timeval tv;
+ struct timezone tm;
+ if (devLog != NULL) {
+ gettimeofday(&tv, &tm);
+ fprintf(devLog, "DEVEXEC:%s:%s:%ld:%ld\n", operation, device,
+ (long) tv.tv_sec, (long) tv.tv_usec);
+ fflush(devLog);
+ }
+ traceDevice("devexec","%s:%s",device, operation);
}
+
/*======================== internal data structures =======================*/
- typedef struct _DevEntry {
- void *pData;
- pObjectDescriptor pDescriptor;
- float fVal;
- char *name;
- commandContext comCon;
- } DevEntry, *pDevEntry;
+typedef struct _DevEntry {
+ void *pData;
+ pObjectDescriptor pDescriptor;
+ float fVal;
+ char *name;
+ SConnection *pCon;
+ int level;
+} DevEntry, *pDevEntry;
/*------------------------------------------------------------------------*/
typedef struct {
- pExeList self;
- pDevEntry pDev;
- pICountable pCountInt;
- pIDrivable pDrivInt;
-}checkContext, *pCheckContext;
+ pExeList self;
+ pDevEntry pDev;
+ pICountable pCountInt;
+ pIDrivable pDrivInt;
+} checkContext, *pCheckContext;
/*-------------------------------------------------------------------------*/
- static pDevEntry CreateDevEntry(pObjectDescriptor pDes, void *pData,
- float fVal, char *name)
- {
- pDevEntry pNew = NULL;
-
- assert(pDes);
-
- pNew = (pDevEntry)malloc(sizeof(DevEntry));
- if(!pNew)
- {
- return NULL;
- }
- pNew->pDescriptor = pDes;
- pNew->pData = pData;
- pNew->name = strdup(name);
- pNew->fVal = fVal;
- memset(&pNew->comCon,0,sizeof(commandContext));
- return pNew;
- }
+static pDevEntry CreateDevEntry(pObjectDescriptor pDes, SConnection * pCon,
+ void *pData, float fVal, char *name, int level)
+{
+ pDevEntry pNew = NULL;
+
+ assert(pDes);
+
+ pNew = (pDevEntry) malloc(sizeof(DevEntry));
+ if (!pNew) {
+ return NULL;
+ }
+ pNew->pDescriptor = pDes;
+ pNew->pData = pData;
+ pNew->name = strdup(name);
+ pNew->fVal = fVal;
+ pNew->pCon = SCCopyConnection(pCon);
+ pNew->pCon->runLevel = level;
+ pNew->level = level;
+ return pNew;
+}
+
/*-------------------------------------------------------------------------*/
- static void DeleteDevEntry(pDevEntry self)
- {
- assert(self);
-
- if(self->name)
- {
- free(self->name);
- }
- free(self);
- }
-
+static void DeleteDevEntry(pDevEntry self)
+{
+ assert(self);
+
+ if (self->name) {
+ free(self->name);
+ }
+ if (self->pCon) {
+ SCDeleteConnection(self->pCon);
+ }
+ free(self);
+}
+
/* ----------------- The Executor himself ---------------------------------*/
- typedef struct __EXELIST{
- pObjectDescriptor pDes;
- SConnection *pOwner;
- int iList;
- int iRun;
- int iStop;
- int iStatus;
- int iEnd;
- int drivePrint;
- long lTask;
- pTaskMan pTask;
- int iLock;
- pICallBack pCall;
- time_t lastRun;
- int paused;
- int taskRunning;
- } ExeList;
-
- static pExeList pExecutor = NULL;
+typedef struct __EXELIST {
+ pObjectDescriptor pDes;
+ SConnection *pOwner;
+ int iList;
+ int iRun;
+ int iStop;
+ int iStatus;
+ int iEnd;
+ int drivePrint;
+ long lTask;
+ pTaskMan pTask;
+ int iLock;
+ pICallBack pCall;
+ time_t lastRun;
+ int paused;
+ int taskRunning;
+} ExeList;
+
+static pExeList pExecutor = NULL;
/*--------------------------------------------------------------------------*/
- static void *DevexecInterface(void *pData, int iInter)
- {
- pExeList self = NULL;
-
- self = (pExeList)pData;
- assert(self);
-
- if(iInter == CALLBACKINTERFACE)
- {
- return self->pCall;
- }
- return NULL;
- }
+static void *DevexecInterface(void *pData, int iInter)
+{
+ pExeList self = NULL;
+
+ self = (pExeList) pData;
+ assert(self);
+
+ if (iInter == CALLBACKINTERFACE) {
+ return self->pCall;
+ }
+ return NULL;
+}
+
/*--------------------------------------------------------------------------*/
- pExeList CreateExeList(pTaskMan pTask)
- {
- pExeList pRes = NULL;
-
- assert(pTask);
-
- pRes = (pExeList)malloc(sizeof(ExeList));
- if(!pRes)
- {
- return NULL;
- }
-
- pRes->pOwner = NULL;
- pRes->pDes = CreateDescriptor("DeviceExecutor");
- if(!pRes->pDes)
- {
- free(pRes);
- return NULL;
- }
- pRes->iList = LLDcreate(sizeof(pDevEntry));
- if(pRes->iList == -1)
- {
- free(pRes);
- return NULL;
- }
- pRes->iRun = 0;
- pRes->iStatus = DEVDONE;
- pRes->pTask = pTask;
- pRes->lTask = -1;
- pRes->iLock = 0;
- pRes->drivePrint = 0;
- pRes->paused = 0;
- pRes->taskRunning = 0;
- pRes->pCall = CreateCallBackInterface();
- pRes->lastRun = time(NULL);
- pRes->pDes->GetInterface = DevexecInterface;
- return pRes;
- }
+pExeList CreateExeList(pTaskMan pTask)
+{
+ pExeList pRes = NULL;
+
+ assert(pTask);
+
+ pRes = (pExeList) malloc(sizeof(ExeList));
+ if (!pRes) {
+ return NULL;
+ }
+
+ pRes->pOwner = NULL;
+ pRes->pDes = CreateDescriptor("DeviceExecutor");
+ if (!pRes->pDes) {
+ free(pRes);
+ return NULL;
+ }
+ pRes->iList = LLDcreate(sizeof(pDevEntry));
+ if (pRes->iList == -1) {
+ free(pRes);
+ return NULL;
+ }
+ pRes->iRun = 0;
+ pRes->iStatus = DEVDONE;
+ pRes->pTask = pTask;
+ pRes->lTask = -1;
+ pRes->iLock = 0;
+ pRes->drivePrint = 0;
+ pRes->paused = 0;
+ pRes->taskRunning = 0;
+ pRes->pCall = CreateCallBackInterface();
+ pRes->lastRun = time(NULL);
+ pRes->pDes->GetInterface = DevexecInterface;
+ return pRes;
+}
+
/*-------------------------------------------------------------------------*/
- void DeleteExeList(void *pData)
- {
- pExeList self;
-
- assert(pData);
-
- self = (pExeList)pData;
- if(self->pDes)
- DeleteDescriptor(self->pDes);
- ClearExecutor(self);
- LLDdelete(self->iList);
- if(self->pCall)
- DeleteCallBackInterface(self->pCall);
+void DeleteExeList(void *pData)
+{
+ pExeList self;
- free(self);
- pServ->pExecutor = NULL;
- if(devLog != NULL){
- fclose(devLog);
- devLog = NULL;
- }
+ assert(pData);
+
+ self = (pExeList) pData;
+ if (self->pDes)
+ DeleteDescriptor(self->pDes);
+ ClearExecutor(self);
+ LLDdelete(self->iList);
+ if (self->pCall)
+ DeleteCallBackInterface(self->pCall);
+
+ if (self->pOwner) {
+ SCDeleteConnection(self->pOwner);
+ self->pOwner = NULL;
}
+
+ free(self);
+ pServ->pExecutor = NULL;
+ if (devLog != NULL) {
+ fclose(devLog);
+ devLog = NULL;
+ }
+}
+
/*--------------------------------------------------------------------------*/
- void ExeInterest(pExeList self, pDevEntry pDev, char *text) {
- char buf[128];
+void ExeInterest(pExeList self, pDevEntry pDev, char *text)
+{
+ char buf[128];
- if(pDev)
- {
- snprintf(buf, sizeof(buf),"%s %s",pDev->name,text);
- InvokeCallBack(self->pCall, DRIVSTAT, buf);
- }
+ if (pDev) {
+ snprintf(buf, sizeof(buf), "%s %s", pDev->name, text);
+ InvokeCallBack(self->pCall, DRIVSTAT, buf);
}
+}
/*------------------------------------------------------------------------*/
- int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,
- void *pData, SConnection *pCon, float fNew)
- {
- pDevEntry pNew = NULL;
- int iRet;
- char pBueffel[132], pError[80];
- pIDrivable pDrivInt = NULL;
- pICountable pCountInt = NULL;
- static int overwriteOwner = -1;
- char *overwriteOption;
- float oldVal;
-
- assert(self);
- assert(pDes);
- assert(pCon);
+void InvokeNewTarget(pExeList self, char *name, float target)
+{
+ NewTarget targetEvent;
- /* may we? */
- if(self->pOwner != NULL)
- {
- if(pCon != self->pOwner)
- {
- /* this hack helps on rita2, when using the sendsics script
- which opens a client for every command */
- if (overwriteOwner < 0) {
- overwriteOption = IFindOption(pSICSOptions, "overwriteOwner");
- overwriteOwner = overwriteOption && *overwriteOption != '0';
- }
- if (overwriteOwner) {
- self->pOwner = pCon;
- } else {
- SCWrite(pCon,
- "ERROR: somebody else is still driving, Request rejected",eError);
- return 0;
- }
- }
- }
- else
- {
- self->pOwner = pCon;
- }
- if(self->iLock == 1)
- {
- SCWrite(pCon,"ERROR: instrument is locked",eError);
- return 0;
- }
+ targetEvent.name = strdup(name);
+ targetEvent.target = target;
+ InvokeCallBack(self->pCall, NEWTARGET, &targetEvent);
+ if(targetEvent.name != NULL){
+ free(targetEvent.name);
+ }
+}
+/*------------------------------------------------------------------------*/
+int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,
+ void *pData, SConnection * pCon, int level, float fNew)
+{
+ pDevEntry pNew = NULL;
+ int iRet;
+ char pBueffel[132], pError[80];
+ pIDrivable pDrivInt = NULL;
+ pICountable pCountInt = NULL;
+ static int overwriteOwner = -1;
+ char *overwriteOption;
+ float oldVal;
- /* well create a new entry */
- self->iStop = 0;
- pNew = CreateDevEntry(pDes,pData,fNew,name);
- if(!pNew)
- {
- SCWrite(pCon,"ERROR: memory exhausted in Device Executor ",eError);
- return 0;
- }
- pNew->comCon = SCGetContext(pCon);
- strncpy(pNew->comCon.deviceID,name,SCDEVIDLEN);
-
- /* start it */
- pDrivInt = pDes->GetInterface(pData,DRIVEID);
- pCountInt = pDes->GetInterface(pData,COUNTID);
- if(pDrivInt)
- {
- iRet = pDrivInt->SetValue(pData,pCon,fNew);
- if(iRet == OKOK && self->drivePrint == 1)
- {
- oldVal = pDrivInt->GetValue(pData,pCon);
- snprintf(pBueffel,131,"Driving %s from %8.3f to %8.3f",
- name, oldVal, fNew);
- SCWrite(pCon,pBueffel,eWarning);
- }
- }
- else if(pCountInt)
- {
- iRet = pCountInt->StartCount(pData,pCon);
- }
- else
- { /* this is a programmers error */
- SCWrite(pCon,"ERROR: Programmer error in StartDevice ",eError);
- iRet = 0;
- }
-
- /* check return status */
- if(iRet == OKOK)
- {
- LLDnodeAppendFrom(self->iList,&pNew);
- sprintf(pBueffel,"started");
- if(NULL!=pNew->comCon.deviceID)
- {
- snprintf(pBueffel,130,"started (%s)",pNew->comCon.deviceID);
- }
- ExeInterest(self, pNew, pBueffel);
- self->iRun = 1;
- self->iStatus = DEVDONE;
- /* if no task: start it */
- if(self->lTask < 0)
- {
- self->lTask = TaskRegister(self->pTask,
- DevExecTask,
- DevExecSignal,
- NULL,
- self,
- 1);
- self->iEnd = 0;
- pCon->conStatus = HWBusy;
- }
- DevexecLog("START",pNew->name);
- return 1;
- }
- else
- {
- sprintf(pBueffel,"ERROR: cannot start device %s",name);
- SCWrite(pCon,pBueffel,eError);
- DeleteDevEntry(pNew);
- if(LLDcheck(self->iList) >= LIST_EMPTY)
- {
- self->pOwner = NULL;
- }
- return 0;
- }
- return 0;
- }
-/*-----------------------------------------------------------------------*/
-/*--------------------------------------------------------------------------*/
- int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon,
- char *name, float fVal)
- {
- pDummy pMot = NULL;
- CommandList *pCom = NULL;
- char pBueffel[256];
+ assert(self);
+ assert(pDes);
+ assert(pCon);
- assert(self);
- assert(pSics);
- assert(name);
-
- pCom = FindCommand(pSics,name);
- if(!pCom)
- {
- sprintf(pBueffel,"ERROR: cannot find motor %s",name);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- pMot = (pDummy)pCom->pData;
- if(!pMot)
- {
- sprintf(pBueffel,"ERROR: %s is no motor ",name);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
-
- if(!pMot->pDescriptor)
- {
- sprintf(pBueffel,"ERROR: cannot find motor %s",name);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- if(!pMot->pDescriptor->GetInterface(pMot,DRIVEID))
- {
- sprintf(pBueffel,"ERROR: %s is no motor",name);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- return StartDevice(self,name,pMot->pDescriptor,(void *)pMot,pCon,fVal);
- }
-/*---------------------------------------------------------------------------*/
- int StartCounter(pExeList self, SicsInterp *pSics,SConnection *pCon,
- char *name)
- {
- pCounter pCter = NULL;
- CommandList *pCom = NULL;
- char pBueffel[256];
-
- assert(self);
- assert(pSics);
- assert(name);
-
- pCom = FindCommand(pSics,name);
- if(!pCom)
- {
- sprintf(pBueffel,"ERROR: cannot find counter %s",name);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- pCter = (pCounter)pCom->pData;
- if(!pCter)
- {
- sprintf(pBueffel,"ERROR: %s is no counter ",name);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
-
- if(!pCter->pDes)
- {
- sprintf(pBueffel,"ERROR: cannot find counter %s",name);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- if(!pCter->pDes->GetInterface(pCter,COUNTID))
- {
- sprintf(pBueffel,"ERROR: %s is no counter",name);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- return StartDevice(self,name,pCter->pDes,(void *)pCter,
- pCon,pCter->pDriv->fPreset);
- }
-/*--------------------------------------------------------------------------*/
- int CheckExeListOld(pExeList self)
- {
- int iRet;
- pDevEntry pDev = NULL;
- pICountable pCountInt = NULL;
- pIDrivable pDrivInt = NULL;
- int eCode;
- int isCounting=0, isDriving=0;
- char pBueffel[512];
- SConnection *pCon;
- pCon = self->pOwner;
-
- assert(self);
-
- /* Sometimes this gets called, though nothing is running. There are
- cases where this is feasible for maintenance, but in some cases it
- is pure rubbish, because nothing runs. This will be checked here.
- */
- if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY))
- {
- self->iRun = 0;
- self->iEnd = 1;
- self->iStop = 0;
- return 1;
- }
-
- /*
- check the status of all registered devices. Remove when finished
- */
- iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- LLDnodeDataTo(self->iList,&pDev);
- if(pDev)
- {
- SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
-
- pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
- pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
-
- if(pDrivInt)
- {
- eCode = pDrivInt->CheckStatus(pDev->pData,self->pOwner);
- }
- else if(pCountInt)
- {
- eCode = pCountInt->CheckCountStatus(pDev->pData,self->pOwner);
- }
- switch(eCode)
- {
- case HWIdle:
- case OKOK:
- if(pCountInt)
- {
- pCountInt->TransferData(pDev->pData,self->pOwner);
- }
- else if(pDrivInt)
- {
- pDrivInt->iErrorCount = 0;
- }
- ExeInterest(self, pDev, "finished");
- DeleteDevEntry(pDev);
- LLDnodeDelete(self->iList);
- SCWrite(pCon, "", eFinish);
- iRet = LLDnodePtr2Prev(self->iList);
- if(SCGetInterrupt(self->pOwner) != eContinue)
- {
- self->iStatus = DEVINT;
- SCPopContext(self->pOwner);
- return -1;
- }
- self->iStatus = DEVDONE;
- break;
- case HWFault: /* real HW error: burning, no net etc.. */
- ExeInterest(self, pDev, "finished with problem");
- DeleteDevEntry(pDev);
- pDev = NULL;
- SCWrite(pCon, "", eFinish);
- LLDnodeDataTo(self->iList,&pDev);
- LLDnodeDelete(self->iList);
- iRet = LLDnodePtr2Prev(self->iList);
- self->iStatus = DEVERROR;
- if(pDrivInt)
- {
- pDrivInt->iErrorCount++;
- }
- if(SCGetInterrupt(self->pOwner) != eContinue)
- {
- self->iStatus = DEVINT;
- SCPopContext(self->pOwner);
- return -1;
- }
- break;
- case HWNoBeam:
- SetStatus(eOutOfBeam);
- if(SCGetInterrupt(self->pOwner) != eContinue)
- {
- SetStatus(eEager);
- self->iStatus = DEVINT;
- SCPopContext(self->pOwner);
- return -1;
- }
- break;
- case HWPause:
- SetStatus(ePaused);
- if(SCGetInterrupt(self->pOwner) != eContinue)
- {
- ContinueExecution(self);
- self->iStatus = DEVINT;
- SCPopContext(self->pOwner);
- return -1;
- }
- break;
- case HWBusy:
- if(pDrivInt != NULL)
- {
- isDriving = 1;
- }
- else if(pCountInt != NULL)
- {
- isCounting = 1;
- }
- self->iStatus = DEVBUSY;
- break;
- case HWPosFault: /* cannot get somewhere... */
- ExeInterest(self, pDev, "finished with problem");
- DeleteDevEntry(pDev);
- LLDnodeDelete(self->iList);
- SCWrite(pCon, "", eFinish);
- self->iStatus = DEVERROR;
- if(pDrivInt)
- {
- pDrivInt->iErrorCount++;
- }
- if(SCGetInterrupt(self->pOwner) != eContinue)
- {
- self->iStatus = DEVINT;
- SCPopContext(self->pOwner);
- return -1;
- }
- break;
- }
- SCPopContext(self->pOwner);
- }
- iRet = LLDnodePtr2Next(self->iList);
- }
-
- if (isCounting) {
- if (isDriving) {
- SetStatus(eCountDrive);
- } else {
- SetStatus(eCounting);
+ /* may we? */
+ if (self->pOwner != NULL) {
+ if (pCon->ident != self->pOwner->ident) {
+ /* this hack helps on rita2, when using the sendsics script
+ which opens a client for every command */
+ if (overwriteOwner < 0) {
+ overwriteOption = IFindOption(pSICSOptions, "overwriteOwner");
+ overwriteOwner = overwriteOption && *overwriteOption != '0';
}
- } else if (isDriving) {
- SetStatus(eDriving);
- }
-
- iRet = LLDnodePtr2First(self->iList);
- if(LLDcheck(self->iList) == LIST_EMPTY)
- {
- self->pOwner = NULL;
- self->iEnd = 1;
- self->iRun = 0;
- self->lTask = -1;
- return 1;
- }
- else
- {
- return 0;
- }
- }
-/*-------------------------------------------------------------------------*/
-static int checkInterrupt(pCheckContext pCheck, int targetStatus){
- if(SCGetInterrupt(pCheck->self->pOwner) != eContinue) {
- pCheck->self->iStatus = DEVINT;
- SCPopContext(pCheck->self->pOwner);
- SetStatus(eEager);
- return -1;
- } else {
- return targetStatus;
- }
-}
-/*--------------------------------------------------------------------------*/
-static int initializeCheck(pCheckContext pCheck, pDevEntry pDev){
- int eCode = HWFault;
-
- SCPushContext(pCheck->self->pOwner,
- pDev->comCon.transID, pDev->comCon.deviceID);
- pCheck->pDev = pDev;
- pCheck->pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
- pCheck->pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
- if(pCheck->pDrivInt != NULL){
- eCode = pCheck->pDrivInt->CheckStatus(pDev->pData,pCheck->self->pOwner);
- } else if(pCheck->pCountInt != NULL) {
- eCode = pCheck->pCountInt->CheckCountStatus(pDev->pData,pCheck->self->pOwner);
- }
- return eCode;
-}
-/*--------------------------------------------------------------------------*/
-static int finishDevice(pCheckContext pCheck){
- int status;
-
- if(pCheck->pCountInt != NULL) {
- pCheck->pCountInt->TransferData(pCheck->pDev->pData,pCheck->self->pOwner);
- } else if(pCheck->pDrivInt != NULL) {
- pCheck->pDrivInt->iErrorCount = 0;
- }
- ExeInterest(pCheck->self, pCheck->pDev, "finished");
- DevexecLog("STOP",pCheck->pDev->name);
- DeleteDevEntry(pCheck->pDev);
- LLDnodeDelete(pCheck->self->iList);
- status = LLDnodePtr2Prev(pCheck->self->iList);
- SCWrite(pCheck->self->pOwner, "", eFinish);
- pCheck->self->iStatus = DEVDONE;
- return checkInterrupt(pCheck,status);
-}
-/*-------------------------------------------------------------------------*/
-static int errorDevice(pCheckContext pCheck){
- int status;
-
- ExeInterest(pCheck->self, pCheck->pDev, "finished with problem");
- DevexecLog("STOP",pCheck->pDev->name);
- LLDnodeDelete(pCheck->self->iList);
- status = LLDnodePtr2Prev(pCheck->self->iList);
- SCWrite(pCheck->self->pOwner, "", eFinish);
- pCheck->self->iStatus = DEVERROR;
- if(pCheck->pDrivInt != NULL) {
- pCheck->pDrivInt->iErrorCount++;
- }
- status = checkInterrupt(pCheck,status);
- DeleteDevEntry(pCheck->pDev);
- return status;
-}
-/*-------------------------------------------------------------------------*/
-static int testFinish(pExeList self){
- if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) {
- self->pOwner = NULL;
- self->iRun = 0;
- self->iEnd = 1;
- self->iStop = 0;
- self->lTask = -1;
- return 1;
- } else {
+ if (overwriteOwner) {
+ SCDeleteConnection(self->pOwner);
+ self->pOwner = SCCopyConnection(pCon);
+ } else {
+ SCWrite(pCon,
+ "ERROR: somebody else is still driving, Request rejected",
+ eLogError);
return 0;
+ }
}
+ } else {
+ self->pOwner = SCCopyConnection(pCon);
+ }
+ if (self->iLock == 1) {
+ SCWrite(pCon, "ERROR: instrument is locked", eError);
+ return 0;
+ }
+
+ /* well create a new entry */
+ self->iStop = 0;
+ pNew = CreateDevEntry(pDes, pCon, pData, fNew, name, level);
+ if (!pNew) {
+ SCWrite(pCon, "ERROR: memory exhausted in Device Executor ", eError);
+ return 0;
+ }
+
+ /* start it */
+ pDrivInt = pDes->GetInterface(pData, DRIVEID);
+ pCountInt = pDes->GetInterface(pData, COUNTID);
+ if (pDrivInt) {
+ iRet = pDrivInt->SetValue(pData, pCon, fNew);
+ if (iRet == OKOK && self->drivePrint == 1) {
+ oldVal = pDrivInt->GetValue(pData, pCon);
+ snprintf(pBueffel, 131, "Driving %s from %8.3f to %8.3f",
+ name, oldVal, fNew);
+ SCWrite(pCon, pBueffel, eValue);
+ }
+ if(iRet == OKOK){
+ InvokeNewTarget(self,name,fNew);
+ }
+ } else if (pCountInt) {
+ iRet = pCountInt->StartCount(pData, pCon);
+ } else { /* this is a programmers error */
+ SCWrite(pCon, "ERROR: Programmer error in StartDevice ", eError);
+ iRet = 0;
+ }
+
+ /* check return status */
+ if (iRet == OKOK) {
+ LLDnodeAppendFrom(self->iList, &pNew);
+ sprintf(pBueffel, "started");
+ if (NULL != pNew->pCon->deviceID) {
+ snprintf(pBueffel, 130, "started (%s)", pNew->pCon->deviceID);
+ }
+ ExeInterest(self, pNew, pBueffel);
+ self->iRun = 1;
+ self->iStatus = DEVDONE;
+ /* if no task: start it */
+ if (self->lTask < 0) {
+ self->lTask = TaskRegister(self->pTask,
+ DevExecTask,
+ DevExecSignal, NULL, self, 1);
+ self->iEnd = 0;
+ pCon->conStatus = HWBusy;
+ }
+ DevexecLog("START", pNew->name);
+ return 1;
+ } else {
+ snprintf(pBueffel,131, "ERROR: cannot start device %s", name);
+ SCWrite(pCon, pBueffel, eError);
+ DeleteDevEntry(pNew);
+ if (LLDcheck(self->iList) >= LIST_EMPTY) {
+ if (self->pOwner != NULL) {
+ SCDeleteConnection(self->pOwner);
+ }
+ self->pOwner = NULL;
+ }
+ return 0;
+ }
+ return 0;
+}
+/*------------------------------------------------------------------------
+ * This is a hacking thing to bypass the whole access checking thing. I
+ * need it at POLDI to run the fucking high voltage while the instrument is
+ * still counting.
+ */
+static int ForceStartDevice(pExeList self, char *name, pObjectDescriptor pDes,
+ void *pData, SConnection * pCon, float fNew)
+{
+ pDevEntry pNew = NULL;
+ int iRet;
+ char pBueffel[132], pError[80];
+ pIDrivable pDrivInt = NULL;
+ pICountable pCountInt = NULL;
+ static int overwriteOwner = -1;
+ char *overwriteOption;
+ float oldVal;
+
+ assert(self);
+ assert(pDes);
+ assert(pCon);
+
+ /* may we? */
+ if (self->pOwner != NULL) {
+ pCon = self->pOwner;
+ }
+ if (self->iLock == 1) {
+ SCWrite(pCon, "ERROR: instrument is locked", eError);
+ return 0;
+ }
+
+ /* well create a new entry */
+ self->iStop = 0;
+ pNew = CreateDevEntry(pDes, SCCopyConnection(pCon),
+ pData, fNew, name, RUNRUN);
+ if (!pNew) {
+ SCWrite(pCon, "ERROR: memory exhausted in Device Executor ", eError);
+ return 0;
+ }
+
+ /* start it */
+ pDrivInt = pDes->GetInterface(pData, DRIVEID);
+ pCountInt = pDes->GetInterface(pData, COUNTID);
+ if (pDrivInt) {
+ iRet = pDrivInt->SetValue(pData, pCon, fNew);
+ if (iRet == OKOK && self->drivePrint == 1) {
+ oldVal = pDrivInt->GetValue(pData, pCon);
+ snprintf(pBueffel, 131, "Driving %s from %8.3f to %8.3f",
+ name, oldVal, fNew);
+ SCWrite(pCon, pBueffel, eValue);
+ }
+ if(iRet == OKOK){
+ InvokeNewTarget(self,name,fNew);
+ }
+ } else if (pCountInt) {
+ /**
+ * Cannot set count parameters here: means of getting hold of the
+ * count mode missing here. As this is a POLDI hack where I only need
+ * to run a HV, I omit this now. But it will work if a proper
+ * preset and mode is set on a counter to start it.
+ */
+ iRet = pCountInt->StartCount(pData, pCon);
+ } else { /* this is a programmers error */
+ SCWrite(pCon, "ERROR: Programmer error in StartDevice ", eError);
+ iRet = 0;
+ }
+
+ /* check return status */
+ if (iRet == OKOK) {
+ LLDnodeAppendFrom(self->iList, &pNew);
+ sprintf(pBueffel, "started");
+ if (NULL != pNew->pCon->deviceID) {
+ snprintf(pBueffel, 130, "started (%s)", pNew->pCon->deviceID);
+ }
+ ExeInterest(self, pNew, pBueffel);
+ self->iRun = 1;
+ self->iStatus = DEVDONE;
+ /* if no task: start it */
+ if (self->lTask < 0) {
+ self->lTask = TaskRegister(self->pTask,
+ DevExecTask,
+ DevExecSignal, NULL, self, 1);
+ self->iEnd = 0;
+ pCon->conStatus = HWBusy;
+ }
+ DevexecLog("START", pNew->name);
+ return 1;
+ } else {
+ snprintf(pBueffel,131, "ERROR: cannot start device %s", name);
+ SCWrite(pCon, pBueffel, eError);
+ DeleteDevEntry(pNew);
+ if (LLDcheck(self->iList) >= LIST_EMPTY) {
+ if (self->pOwner != NULL) {
+ SCDeleteConnection(self->pOwner);
+ }
+ self->pOwner = NULL;
+ }
+ return 0;
+ }
+ return 0;
}
/*--------------------------------------------------------------------------*/
- int CheckExeList(pExeList self)
- {
- int iRet, status;
- checkContext check;
- pDevEntry pDev = NULL;
- pICountable pCountInt = NULL;
- pIDrivable pDrivInt = NULL;
- int eCode;
- int isCounting=0, isDriving=0;
- char pBueffel[512];
- SConnection *pCon;
- pCon = self->pOwner;
+int StartMotor(pExeList self, SicsInterp * pSics, SConnection * pCon,
+ char *name, int level, float fVal)
+{
+ pDummy pMot = NULL;
+ CommandList *pCom = NULL;
+ char pBueffel[256];
- assert(self);
-
- /* Sometimes this gets called, though nothing is running. There are
- cases where this is feasible for maintenance, but in some cases it
- is pure rubbish, because nothing runs. This will be checked here.
- */
- if(testFinish(self) == 1){
- return 1;
- }
-
- /*
- check the status of all registered devices. Remove when finished
- */
- check.self = self;
- status = LLDnodePtr2First(self->iList);
- while(status != 0)
- {
- LLDnodeDataTo(self->iList,&pDev);
- if(pDev)
- {
- eCode = initializeCheck(&check,pDev);
- if(eCode != HWNoBeam && eCode != HWPause && self->paused == 1){
- DevexecLog("CONTINUE","ALL");
- self->paused = 0;
- }
- switch(eCode)
- {
- case HWIdle:
- case OKOK:
- status = finishDevice(&check);
- if(status < 0){
- return status;
- }
- break;
- case HWFault: /* real HW error: burning, no net etc.. */
- status = errorDevice(&check);
- if(status < 0){
- return status;
- }
- break;
- case HWNoBeam:
- SetStatus(eOutOfBeam);
- if(self->paused == 0){
- self->paused = 1;
- DevexecLog("NOBEAM","ALL");
- }
- status = checkInterrupt(&check,1);
- if(status < 0){
- return status;
- }
- break;
- case HWPause:
- SetStatus(ePaused);
- if(self->paused == 0){
- self->paused = 1;
- DevexecLog("PAUSE","ALL");
- }
- status = checkInterrupt(&check,1);
- if(status < 0){
- /*
- * continue in order to wait for devices to come to a stop
- */
- ContinueExecution(self);
- return status;
- }
- break;
- case HWBusy:
- if(check.pDrivInt != NULL)
- {
- isDriving = 1;
- }
- else if(check.pCountInt != NULL)
- {
- isCounting = 1;
- }
- self->iStatus = DEVBUSY;
- break;
- case HWPosFault: /* cannot get somewhere... */
- status = errorDevice(&check);
- if(status < 0){
- return status;
- }
- break;
- }
- SCPopContext(self->pOwner);
- }
- status = LLDnodePtr2Next(self->iList);
- }
-
- if (isCounting) {
- if (isDriving) {
- SetStatus(eCountDrive);
- } else {
- SetStatus(eCounting);
- }
- } else if (isDriving) {
- SetStatus(eDriving);
- }
+ assert(self);
+ assert(pSics);
+ assert(name);
- iRet = LLDnodePtr2First(self->iList);
- return testFinish(self);
+ pCom = FindCommand(pSics, name);
+ if (!pCom) {
+ snprintf(pBueffel,255, "ERROR: cannot find motor %s", name);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
}
+ pMot = (pDummy) pCom->pData;
+ if (!pMot) {
+ snprintf(pBueffel,255, "ERROR: %s is no motor ", name);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+
+ if (!pMot->pDescriptor) {
+ snprintf(pBueffel,255, "ERROR: cannot find motor %s", name);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ if (!pMot->pDescriptor->GetInterface(pMot, DRIVEID)) {
+ snprintf(pBueffel, 255, "ERROR: %s is no motor", name);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ return StartDevice(self, name, pMot->pDescriptor, (void *) pMot, pCon,
+ level, fVal);
+}
+
/*---------------------------------------------------------------------------*/
- int Wait4Success(pExeList self)
- {
- int iRet;
- assert(self);
-
- /* do nothing if not running */
- if(self->lTask < 0)
- {
- printf("Nothing to wait for.... \n");
- self->iRun = 0; /* not sure if this is needed here, but does not harm */
- return self->iStatus;
- }
-
- /* wait for Devexec task to finish */
- TaskWait(self->pTask,self->lTask);
-#ifdef DEBUG
- printf("Wait4Success finished\n");
-#endif
- self->iRun = 0;
- return self->iStatus;
+int StartCounter(pExeList self, SicsInterp * pSics, SConnection * pCon,
+ int level, char *name)
+{
+ pCounter pCter = NULL;
+ CommandList *pCom = NULL;
+ char pBueffel[256];
+
+ assert(self);
+ assert(pSics);
+ assert(name);
+
+ pCom = FindCommand(pSics, name);
+ if (!pCom) {
+ snprintf(pBueffel,255, "ERROR: cannot find counter %s", name);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
}
+ pCter = (pCounter) pCom->pData;
+ if (!pCter) {
+ snprintf(pBueffel,255, "ERROR: %s is no counter ", name);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+
+
+ if (!pCter->pDes) {
+ snprintf(pBueffel, 255, "ERROR: cannot find counter %s", name);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ if (!pCter->pDes->GetInterface(pCter, COUNTID)) {
+ snprintf(pBueffel,255, "ERROR: %s is no counter", name);
+ SCWrite(pCon, pBueffel, eError);
+ return 0;
+ }
+ return StartDevice(self, name, pCter->pDes, (void *) pCter,
+ pCon, level, pCter->pDriv->fPreset);
+}
+
+/*-------------------------------------------------------------------------*/
+static int checkInterrupt(pCheckContext pCheck, int targetStatus)
+{
+ if (SCGetInterrupt(pCheck->self->pOwner) != eContinue) {
+ pCheck->self->iStatus = DEVINT;
+ SetStatus(eEager);
+ return -1;
+ } else {
+ return targetStatus;
+ }
+}
+
/*--------------------------------------------------------------------------*/
- int ListPending(pExeList self, SConnection *pCon)
- {
- int iRet,i;
- char pBueffel[512];
- pDevEntry pDev = NULL;
-
- assert(self);
- assert(pCon);
-
- /* first make sure that the list is fully updated */
- iRet = CheckExeList(self);
- if(iRet == 1) /* nothing to do! */
- {
- SCWrite(pCon,"Machine idle",eStatus);
- return 1;
+static int initializeCheck(pCheckContext pCheck, pDevEntry pDev)
+{
+ int eCode = HWFault;
+
+ pCheck->pDev = pDev;
+ pCheck->pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData, DRIVEID);
+ pCheck->pCountInt =
+ pDev->pDescriptor->GetInterface(pDev->pData, COUNTID);
+ if (pCheck->pDrivInt != NULL) {
+ eCode = pCheck->pDrivInt->CheckStatus(pDev->pData, pDev->pCon);
+ } else if (pCheck->pCountInt != NULL) {
+ eCode = pCheck->pCountInt->CheckCountStatus(pDev->pData, pDev->pCon);
+ }
+ return eCode;
+}
+
+/*--------------------------------------------------------------------------*/
+static int finishDevice(pCheckContext pCheck)
+{
+ int status;
+
+ if (pCheck->pCountInt != NULL) {
+ pCheck->pCountInt->TransferData(pCheck->pDev->pData,
+ pCheck->pDev->pCon);
+ } else if (pCheck->pDrivInt != NULL) {
+ pCheck->pDrivInt->iErrorCount = 0;
+ }
+ ExeInterest(pCheck->self, pCheck->pDev, "finished");
+ DevexecLog("STOP", pCheck->pDev->name);
+ DeleteDevEntry(pCheck->pDev);
+ LLDnodeDelete(pCheck->self->iList);
+ status = LLDnodePtr2Prev(pCheck->self->iList);
+ SCWrite(pCheck->self->pOwner, "", eFinish);
+ pCheck->self->iStatus = DEVDONE;
+ return checkInterrupt(pCheck, status);
+}
+
+/*-------------------------------------------------------------------------*/
+static int errorDevice(pCheckContext pCheck)
+{
+ int status;
+
+ ExeInterest(pCheck->self, pCheck->pDev, "finished with problem");
+ DevexecLog("STOP", pCheck->pDev->name);
+ LLDnodeDelete(pCheck->self->iList);
+ status = LLDnodePtr2Prev(pCheck->self->iList);
+ SCWrite(pCheck->self->pOwner, "", eFinish);
+ pCheck->self->iStatus = DEVERROR;
+ if (pCheck->pDrivInt != NULL) {
+ pCheck->pDrivInt->iErrorCount++;
+ }
+ status = checkInterrupt(pCheck, status);
+ DeleteDevEntry(pCheck->pDev);
+ return status;
+}
+
+/*-------------------------------------------------------------------------*/
+static int testFinish(pExeList self)
+{
+ if ((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) {
+ if (self->pOwner != NULL) {
+ SCDeleteConnection(self->pOwner);
}
- else if(iRet == -1)
- {
- SCWrite(pCon,"Handling Interrupt",eStatus);
+ self->pOwner = NULL;
+ self->iRun = 0;
+ self->iEnd = 1;
+ self->iStop = 0;
+ self->lTask = -1;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+int CheckExeList(pExeList self)
+{
+ int iRet, status;
+ checkContext check;
+ pDevEntry pDev = NULL;
+ pICountable pCountInt = NULL;
+ pIDrivable pDrivInt = NULL;
+ int eCode;
+ int isCounting = 0, isDriving = 0;
+ char pBueffel[512];
+
+ assert(self);
+
+ /* Sometimes this gets called, though nothing is running. There are
+ cases where this is feasible for maintainance, but in some cases it
+ is pure rubbish, because nothing runs. This will be checked here.
+ */
+ if (testFinish(self) == 1) {
+ return 1;
+ }
+
+ /*
+ check the status of all registered devices. Remove when finished
+ */
+ check.self = self;
+ status = LLDnodePtr2First(self->iList);
+ while (status != 0) {
+ LLDnodeDataTo(self->iList, &pDev);
+ if (pDev) {
+ eCode = initializeCheck(&check, pDev);
+ if (eCode != HWNoBeam && eCode != HWPause && self->paused == 1) {
+ DevexecLog("CONTINUE", "ALL");
+ self->paused = 0;
+ }
+ switch (eCode) {
+ case HWIdle:
+ case OKOK:
+ status = finishDevice(&check);
+ if (status < 0) {
+ return status;
+ }
+ break;
+ case HWFault: /* real HW error: burning, no net etc.. */
+ status = errorDevice(&check);
+ if (status < 0) {
+ return status;
+ }
+ break;
+ case HWNoBeam:
+ SetStatus(eOutOfBeam);
+ if (self->paused == 0) {
+ self->paused = 1;
+ DevexecLog("NOBEAM", "ALL");
+ }
+ status = checkInterrupt(&check, 1);
+ if (status < 0) {
+ return status;
+ }
+ break;
+ case HWPause:
+ SetStatus(ePaused);
+ if (self->paused == 0) {
+ self->paused = 1;
+ DevexecLog("PAUSE", "ALL");
+ }
+ status = checkInterrupt(&check, 1);
+ if (status < 0) {
+ /*
+ * continue in order to wait for devices to come to a stop
+ */
+ ContinueExecution(self);
+ return status;
+ }
+ break;
+ case HWBusy:
+ if (check.pDrivInt != NULL) {
+ isDriving = 1;
+ } else if (check.pCountInt != NULL) {
+ isCounting = 1;
+ }
+ self->iStatus = DEVBUSY;
+ break;
+ case HWPosFault: /* cannot get somewhere... */
+ status = errorDevice(&check);
+ if (status < 0) {
+ return status;
+ }
+ break;
+ }
+ }
+ status = LLDnodePtr2Next(self->iList);
+ }
+
+ if (isCounting) {
+ if (isDriving) {
+ SetStatus(eCountDrive);
+ } else {
+ SetStatus(eCounting);
+ }
+ } else if (isDriving) {
+ SetStatus(eDriving);
+ }
+
+ iRet = LLDnodePtr2First(self->iList);
+ return testFinish(self);
+}
+/*--------------------------------------------------------------------------
+Cludge to not move the current pointer for CheckExeList
+*/
+void *LLDgetCurrent(int List);
+void LLDsetCurrent(int List, void *pointer);
+
+/*---------------------------------------------------------------------------*/
+int DevExecLevelRunning(pExeList self, int level)
+{
+ int iRet;
+ pDevEntry pDev = NULL;
+ void *current;
+
+ if(self->lTask < 0){
+ return 0;
+ }
+ current = LLDgetCurrent(self->iList);
+ iRet = LLDnodePtr2First(self->iList);
+ while (iRet != 0) {
+ LLDnodeDataTo(self->iList, &pDev);
+ if (pDev) {
+ if(pDev->level >= level){
+ LLDsetCurrent(self->iList,current);
+ return 1;
+ }
+ }
+ iRet = LLDnodePtr2Next(self->iList);
+ }
+ LLDsetCurrent(self->iList,current);
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+int Wait4Success(pExeList self)
+{
+ int iRet;
+ assert(self);
+
+ /* do nothing if not running */
+ if (self->lTask < 0) {
+ printf("Nothing to wait for.... \n");
+ self->iRun = 0; /* not sure if this is needed here, but does not harm */
+ return self->iStatus;
+ }
+
+ /* wait for Devexec task to finish */
+ /*TaskWait(self->pTask, self->lTask); */
+ while(DevExecLevelRunning(self,RUNDRIVE)){
+ TaskYield(self->pTask);
+ }
+#ifdef DEBUG
+ printf("Wait4Success finished\n");
+#endif
+ self->iRun = 0;
+ return self->iStatus;
+}
+
+/*--------------------------------------------------------------------------*/
+int ListPending(pExeList self, SConnection * pCon)
+{
+ int iRet, i;
+ char pBueffel[512];
+ pDevEntry pDev = NULL;
+
+ assert(self);
+ assert(pCon);
+
+ /* first make sure that the list is fully updated */
+ iRet = CheckExeList(self);
+ if (iRet == 1) { /* nothing to do! */
+ SCWrite(pCon, "Machine idle", eValue);
+ return 1;
+ } else if (iRet == -1) {
+ SCWrite(pCon, "Handling Interrupt", eError);
+ return 0;
+ }
+
+
+ /* search the list for entries */
+ iRet = LLDnodePtr2First(self->iList);
+ while (iRet != 0) {
+ LLDnodeDataTo(self->iList, &pDev);
+ if (pDev) {
+ sprintf(pBueffel, "\t%s %f", pDev->name, pDev->fVal);
+ SCWrite(pCon, pBueffel, eValue);
+ }
+ iRet = LLDnodePtr2Next(self->iList);
+ }
+ return 1;
+}
+
+/* -----------------------------------------------------------------------*/
+long GetDevexecID(pExeList self)
+{
+ assert(self);
+
+ return self->lTask;
+}
+
+/*--------------------------------------------------------------------------*/
+int StopExe(pExeList self, char *name)
+{
+ int i, iRet;
+ pDevEntry pDev = NULL;
+ pIDrivable pDrivInt = NULL;
+ pICountable pCountInt = NULL;
+ assert(self);
+
+ /* if not active, nothing to do */
+ if ((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) {
+ self->iRun = 0;
+ return 1;
+ }
+
+ /* first the ALL case */
+ if (strcmp(name, "all") == 0) {
+ /*
+ check for stop flag. This is to stop unnecessary calls to StopExe.
+ There may be way to many, but each call is reasonable under certain
+ circumstances.
+ */
+ if (self->iStop == 1) {
return 0;
+ } else {
+ self->iStop = 1;
}
-
-
- /* search the list for entries */
+
iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- LLDnodeDataTo(self->iList,&pDev);
- if(pDev)
- {
- sprintf(pBueffel,"\t%s %f",pDev->name,pDev->fVal);
- SCWrite(pCon,pBueffel,eStatus);
+ while (iRet != 0) {
+ pDev = (pDevEntry) LLDnodePtr(self->iList);
+ if (pDev) {
+ pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData, DRIVEID);
+ pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID);
+ if (pDrivInt) {
+ pDrivInt->Halt(pDev->pData);
+ } else if (pCountInt) {
+ pCountInt->Halt(pDev->pData);
+ }
}
iRet = LLDnodePtr2Next(self->iList);
}
+ SCWrite(self->pOwner, "ERROR: Full Stop called!!", eLogError);
+ if (SCGetInterrupt(self->pOwner) > eContinue) {
+ self->iStatus = DEVINT;
+ }
return 1;
}
-/* -----------------------------------------------------------------------*/
- long GetDevexecID(pExeList self)
- {
- assert(self);
-
- return self->lTask;
- }
-/*--------------------------------------------------------------------------*/
- int StopExe(pExeList self, char *name)
- {
- int i, iRet;
- pDevEntry pDev = NULL;
- pIDrivable pDrivInt = NULL;
- pICountable pCountInt = NULL;
- assert(self);
-
- /* if not active, nothing to do */
- if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY))
- {
- self->iRun = 0;
- return 1;
- }
- /* first the ALL case */
- if(strcmp(name,"all") == 0)
- {
- /*
- check for stop flag. This is to stop unnecessary calls to StopExe.
- There may be way to many, but each call is reasonable under certain
- circumstances.
- */
- if(self->iStop == 1)
- {
- return 0;
- }
- else
- {
- self->iStop = 1;
- }
-
- iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- pDev = (pDevEntry)LLDnodePtr(self->iList);
- if(pDev)
- {
- pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
- pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
- if(pDrivInt)
- {
- pDrivInt->Halt(pDev->pData);
- }
- else if(pCountInt)
- {
- pCountInt->Halt(pDev->pData);
- }
- }
- iRet = LLDnodePtr2Next(self->iList);
- }
- SCPushContext(self->pOwner,0,"system");
- SCWrite(self->pOwner,"ERROR: Full Stop called!!",eError);
- SCPopContext(self->pOwner);
- if(SCGetInterrupt(self->pOwner) > eContinue)
- {
- self->iStatus = DEVINT;
+ /* now the special case: a well defined command */
+ iRet = LLDnodePtr2First(self->iList);
+ while (iRet != 0) {
+ pDev = (pDevEntry) LLDnodePtr(self->iList);
+ if (pDev) {
+ if (strcmp(pDev->name, name) == 0) {
+ pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData, DRIVEID);
+ pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID);
+ if (pDrivInt) {
+ pDrivInt->Halt(pDev->pData);
+ } else if (pCountInt) {
+ pCountInt->Halt(pDev->pData);
}
return 1;
- }
-
- /* now the special case: a well defined command */
- iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- pDev = (pDevEntry)LLDnodePtr(self->iList);
- if(pDev)
- {
- if(strcmp(pDev->name,name) == 0)
- {
- pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
- pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
- if(pDrivInt)
- {
- pDrivInt->Halt(pDev->pData);
- }
- else if(pCountInt)
- {
- pCountInt->Halt(pDev->pData);
- }
- return 1;
- }
- }
- iRet = LLDnodePtr2Next(self->iList);
- }
-
- return 0;
- }
-/*-------------------------------------------------------------------------*/
- int StopExeWait(pExeList self)
- {
- StopExe(self,"all");
- Wait4Success(self);
- return 1;
+ }
+ }
+ iRet = LLDnodePtr2Next(self->iList);
}
-/*--------------------------------------------------------------------------*/
- int PauseExecution(pExeList self)
- {
- int i, iRet, iRes;
- pDevEntry pDev = NULL;
- pICountable pCountInt = NULL;
- assert(self);
-
- /* step through the list */
- iRes = 1;
- iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- pDev = (pDevEntry)LLDnodePtr(self->iList);
- if(pDev)
- {
- SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
-
- pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
- if(pCountInt)
- {
- iRet = pCountInt->Pause(pDev->pData,self->pOwner);
- if(!iRet)
- {
- iRes = 0;
- }
- }
-
- }
- SCPopContext(self->pOwner);
- iRet = LLDnodePtr2Next(self->iList);
- }
- SetStatus(ePaused);
- return iRes;
- }
-/*------------------------------------------------------------------------*/
- int IsCounting(pExeList self)
- {
- int iRet;
- pDevEntry pDev = NULL;
- pICountable pCountInt = NULL;
- assert(self);
-
- /* step through the list */
- iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- pDev = (pDevEntry)LLDnodePtr(self->iList);
- if(pDev)
- {
- pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
- if(pCountInt)
- {
- return 1;
- }
- }
- iRet = LLDnodePtr2Next(self->iList);
- }
- return 0;
- }
-/*--------------------------------------------------------------------------*/
- int ContinueExecution(pExeList self)
- {
- int i, iRet, iRes;
- pDevEntry pDev = NULL;
- pICountable pCountInt = NULL;
- assert(self);
-
- /* step through the list */
- iRes = 1;
- iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- pDev = (pDevEntry)LLDnodePtr(self->iList);
- if(pDev)
- {
- pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
- if(pCountInt)
- {
- SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
- iRet = pCountInt->Continue(pDev->pData,self->pOwner);
- if(!iRet)
- {
- iRes = 0;
- }
- SCPopContext(self->pOwner);
- }
-
- }
- iRet = LLDnodePtr2Next(self->iList);
- }
- SetStatus(eCounting);
- return iRes;
- }
-/*------------------------------------------------------------------------*/
- void ClearExecutor(pExeList self)
- {
- int iRet;
- pDevEntry pDev = NULL;
-
- assert(self);
-
- iRet = LLDnodePtr2First(self->iList);
- while(iRet != 0)
- {
- pDev = (pDevEntry)LLDnodePtr(self->iList);
- if(pDev)
- {
- DeleteDevEntry(pDev);
- }
- LLDnodeDelete(self->iList);
- iRet = LLDnodePtr2Prev(self->iList);
- iRet = LLDnodePtr2Next(self->iList);
- }
- if(self->pOwner)
- {
- if(SCGetInterrupt(self->pOwner) > eContinue)
- {
- self->iStatus = DEVINT;
- }
- }
- self->pOwner = NULL;
- self->iEnd = 1;
- self->lTask = -1;
- self->iRun = 0;
- self->iLock = 0;
- }
-/*-------------------------------------------------------------------------*/
- int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pExeList self = NULL;
- int iRet;
- char pBueffel[132];
-
- assert(pCon);
- assert(pSics);
- assert(pData);
-
- /* check Privilege: Muggers may do it */
- if(!SCMatchRights(pCon,usUser))
- {
- SCWrite(pCon,"ERROR: NO Privilege to Stop operation ",eError);
- return 0;
- }
- argtolower(argc,argv);
- self = (pExeList)pData;
- if(argc < 2)
- {
- ListPending(self,pCon);
- return 1;
- }
-
- iRet = StopExe(self,argv[1]);
- if(!iRet)
- {
- sprintf(pBueffel,"ERROR: %s not found, so could not halt", argv[1]);
- SCWrite(pCon,pBueffel,eError);
- }
- return iRet;
- }
-/*------------------- The CallBack function for interest ------------------*/
- static int DrivStatCallback(int iEvent, void *text, void *pCon,
- commandContext cc)
- {
- assert(pCon);
- assert(text);
-
- SCPushContext2(pCon,cc);
- SCWrite(pCon, text, eValue);
- SCPopContext(pCon);
- return 1;
- }
- /*--------------------------------------------------------------------------*/
- int ListExe(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pExeList self = NULL;
- int list;
-
- if (argc == 1) {
- return ListPending((pExeList)pData,pCon);
- }
- argtolower(argc,argv);
- self = (pExeList)pData;
- assert(self);
- if (argc == 2) {
- if (strcmp(argv[1], "interest") == 0)
- {
- list = RegisterCallback(self->pCall, SCGetContext(pCon),
- DRIVSTAT, DrivStatCallback,
- pCon, NULL);
- SCRegister(pCon, pSics, self->pCall,list);
- SCSendOK(pCon);
- return 1;
- }
- if (strcmp(argv[1], "uninterest") == 0)
- {
- RemoveCallback2(self->pCall, pCon);
- SCUnregister(pCon, self->pCall);
- SCSendOK(pCon);
- return 1;
- }
- }
- SCWrite(pCon, "ERROR: illegal arguments for ListExe", eError);
- return 0;
- }
+ return 0;
+}
+
/*-------------------------------------------------------------------------*/
- int SicsIdle(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- pExeList self = NULL;
- int idle;
- char pBueffel[80];
-
- self = (pExeList)pData;
- assert(self);
- idle = time(NULL) - self->lastRun;
- snprintf(pBueffel,79,"sicsidle = %d",idle);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
+int StopByData(pExeList self, void *data)
+{
+ int iRet;
+ pDevEntry pDev = NULL;
+ pIDrivable pDrivInt = NULL;
+ pICountable pCountInt = NULL;
+
+ iRet = LLDnodePtr2First(self->iList);
+ while (iRet != 0) {
+ pDev = (pDevEntry) LLDnodePtr(self->iList);
+ if (pDev) {
+ if (pDev->pData == data) {
+ pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData, DRIVEID);
+ pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID);
+ if (pDrivInt) {
+ pDrivInt->Halt(pDev->pData);
+ } else if (pCountInt) {
+ pCountInt->Halt(pDev->pData);
+ }
+ ExeInterest(self, pDev, "finished");
+ DevexecLog("FINISHED", pDev->name);
+ DeleteDevEntry(pDev);
+ LLDnodeDelete(self->iList);
+ self->iStatus = DEVDONE;
+ SCWrite(self->pOwner, "", eFinish);
+ return 1;
+ }
+ }
+ iRet = LLDnodePtr2Next(self->iList);
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+int StopExeWait(pExeList self)
+{
+ StopExe(self, "all");
+ while(DevExecLevelRunning(self,RUNRUN)){
+ TaskYield(self->pTask);
+ }
+ return 1;
+}
+/*--------------------------------------------------------------------------*/
+int PauseExecution(pExeList self)
+{
+ int i, iRet, iRes;
+ pDevEntry pDev = NULL;
+ pICountable pCountInt = NULL;
+ assert(self);
+
+ /* step through the list */
+ iRes = 1;
+ iRet = LLDnodePtr2First(self->iList);
+ while (iRet != 0) {
+ pDev = (pDevEntry) LLDnodePtr(self->iList);
+ if (pDev) {
+ pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID);
+ if (pCountInt) {
+ iRet = pCountInt->Pause(pDev->pData, pDev->pCon);
+ if (!iRet) {
+ iRes = 0;
+ }
+ }
+
+ }
+ iRet = LLDnodePtr2Next(self->iList);
+ }
+ SetStatus(ePaused);
+ return iRes;
+}
+
+/*------------------------------------------------------------------------*/
+int IsCounting(pExeList self)
+{
+ int iRet;
+ pDevEntry pDev = NULL;
+ pICountable pCountInt = NULL;
+ assert(self);
+
+ /* step through the list */
+ iRet = LLDnodePtr2First(self->iList);
+ while (iRet != 0) {
+ pDev = (pDevEntry) LLDnodePtr(self->iList);
+ if (pDev) {
+ pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID);
+ if (pCountInt) {
+ return 1;
+ }
+ }
+ iRet = LLDnodePtr2Next(self->iList);
+ }
+ return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+int ContinueExecution(pExeList self)
+{
+ int i, iRet, iRes;
+ pDevEntry pDev = NULL;
+ pICountable pCountInt = NULL;
+ assert(self);
+
+ /* step through the list */
+ iRes = 1;
+ iRet = LLDnodePtr2First(self->iList);
+ while (iRet != 0) {
+ pDev = (pDevEntry) LLDnodePtr(self->iList);
+ if (pDev) {
+ pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID);
+ if (pCountInt) {
+ iRet = pCountInt->Continue(pDev->pData, pDev->pCon);
+ if (!iRet) {
+ iRes = 0;
+ }
+ }
+
+ }
+ iRet = LLDnodePtr2Next(self->iList);
+ }
+ SetStatus(eCounting);
+ return iRes;
+}
+
+/*------------------------------------------------------------------------*/
+void ClearExecutor(pExeList self)
+{
+ int iRet;
+ pDevEntry pDev = NULL;
+
+ assert(self);
+
+ iRet = LLDnodePtr2First(self->iList);
+ while (iRet != 0) {
+ pDev = (pDevEntry) LLDnodePtr(self->iList);
+ if (pDev) {
+ DeleteDevEntry(pDev);
+ }
+ LLDnodeDelete(self->iList);
+ iRet = LLDnodePtr2Prev(self->iList);
+ iRet = LLDnodePtr2Next(self->iList);
+ }
+ if (self->pOwner) {
+ if (SCGetInterrupt(self->pOwner) > eContinue) {
+ self->iStatus = DEVINT;
+ }
+ SCDeleteConnection(self->pOwner);
+ }
+ self->pOwner = NULL;
+ self->iEnd = 1;
+ self->lTask = -1;
+ self->iRun = 0;
+ self->iLock = 0;
+}
+
+/*-------------------------------------------------------------------------*/
+int StopCommand(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pExeList self = NULL;
+ int iRet;
+ char pBueffel[132];
+
+ assert(pCon);
+ assert(pSics);
+ assert(pData);
+
+ /* check Privilege: Muggers may do it */
+ if (!SCMatchRights(pCon, usUser)) {
+ SCWrite(pCon, "ERROR: NO Privilege to Stop operation ", eError);
+ return 0;
+ }
+
+ argtolower(argc, argv);
+ self = (pExeList) pData;
+ if (argc < 2) {
+ ListPending(self, pCon);
+ return 1;
+ }
+
+ iRet = StopExe(self, argv[1]);
+ if (!iRet) {
+ snprintf(pBueffel,131, "ERROR: %s not found, so could not halt", argv[1]);
+ SCWrite(pCon, pBueffel, eError);
+ }
+ return iRet;
+}
+
+/*------------------- The CallBack function for interest ------------------*/
+static int DrivStatCallback(int iEvent, void *text, void *pCon)
+{
+ assert(pCon);
+ assert(text);
+ SConnection *con = (SConnection *) pCon;
+
+ if (con == NULL || !SCisConnected(con)) {
+ return -1;
+ }
+ SCWrite(pCon, text, eLog);
+ return 1;
+}
+
+ /*--------------------------------------------------------------------------*/
+int ListExe(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pExeList self = NULL;
+ int list;
+
+ if (argc == 1) {
+ return ListPending((pExeList) pData, pCon);
+ }
+ argtolower(argc, argv);
+ self = (pExeList) pData;
+ assert(self);
+ if (argc == 2) {
+ if (strcmp(argv[1], "interest") == 0) {
+ list = RegisterCallback(self->pCall,
+ DRIVSTAT, DrivStatCallback,
+ SCCopyConnection(pCon), NULL);
+ SCSendOK(pCon);
+ return 1;
+ }
+ if (strcmp(argv[1], "uninterest") == 0) {
+ RemoveCallbackCon(self->pCall, pCon);
+ SCSendOK(pCon);
+ return 1;
+ }
+ }
+ SCWrite(pCon, "ERROR: illegal arguments for ListExe", eError);
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+int SicsIdle(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ pExeList self = NULL;
+ int idle;
+ char pBueffel[80];
+
+ self = (pExeList) pData;
+ assert(self);
+ idle = time(NULL) - self->lastRun;
+ snprintf(pBueffel, 79, "sicsidle = %d", idle);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+}
+
/*--------------------------------------------------------------------------
Usage:
- Success
+ Success [level]
*/
-
- int Success(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- int iRet;
- Status eOld;
-
- eOld = GetStatus();
- SetStatus(eRunning);
- iRet = Wait4Success((pExeList)pData);
- if(iRet == DEVINT)
- {
- if(SCGetInterrupt(pCon) == eAbortOperation)
- {
- SCSetInterrupt(pCon,eContinue);
- iRet = 0;
- }
- }
- else if(iRet == DEVDONE)
- {
- SCWrite(pCon,"All done",eStatus);
- iRet = 1;
- }
- else if(iRet == DEVERROR)
- {
- SCWrite(pCon,"Finished with Problems",eStatus);
- iRet = 1;
- }
- SetStatus(eEager);
- return iRet;
- }
-/*-------------------------------------------------------------------------*/
- int PauseAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- int status;
+int Success(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ int iRet, level;
+ Status eOld;
+ pExeList self = (pExeList)pData;
- status = PauseExecution((pExeList)pData);
- if(status)
- {
- SCSendOK(pCon);
- return 1;
- }
- else
- {
- SCWrite(pCon,"ERROR: failed to pause",eError);
- return 0;
- }
- }
- /*---------------------------------------------------------------------*/
- int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- int val;
- char pBueffel[256];
-
- pExeList self = (pExeList)pData;
- if(argc < 2)
- {
- SCWrite(pCon,"ERROR: not enough arguments to devexec command",eError);
- return 0;
+ eOld = GetStatus();
+ SetStatus(eRunning);
+
+ if(argc > 1){
+ if(strcmp(argv[1],"RUNDRIVE") == 0){
+ level = RUNDRIVE;
+ }
+ } else {
+ level = RUNRUN;
+ }
+
+ while(DevExecLevelRunning(self, level)){
+ TaskYield(self->pTask);
+ }
+ iRet = self->iStatus;
+ if (iRet == DEVINT) {
+ if (SCGetInterrupt(pCon) == eAbortOperation) {
+ SCSetInterrupt(pCon, eContinue);
+ iRet = 1;
+ } else {
+ iRet = 0;
}
- strtolower(argv[1]);
- if(strcmp(argv[1],"driveprint") == 0)
- {
- if(argc > 2 && SCMatchRights(pCon,usUser))
- {
- val = atoi(argv[2]);
- self->drivePrint = val;
- SCSendOK(pCon);
- return 1;
- } else {
- snprintf(pBueffel,255,"devexe.drivePrint = %d",
- self->drivePrint);
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- } else {
- SCWrite(pCon,"ERROR: unknown subcommand to devexec",eError);
- return 0;
- }
- }
+ } else if (iRet == DEVDONE) {
+ SCWrite(pCon, "All done", eValue);
+ iRet = 1;
+ } else if (iRet == DEVERROR) {
+ SCWrite(pCon, "Finished with Problems", eValue);
+ iRet = 1;
+ }
+ SetStatus(eEager);
+ return iRet;
+}
/*-------------------------------------------------------------------------*/
- int ContinueAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- int status;
- Status eStat;
+int PauseAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ int status;
- eStat = GetStatus();
- if(eStat != ePaused)
- {
- SCWrite(pCon,"ERROR: Not paused, ignored",eError);
- return 0;
- }
-
- status = ContinueExecution((pExeList)pData);
- if(status)
- {
- SCSendOK(pCon);
- return 1;
- }
- else
- {
- SCWrite(pCon,"ERROR: failed to pause",eError);
- return 0;
- }
- }
-
-/*--------------------------------------------------------------------------*/
- int isInRunMode(pExeList self)
- {
- if(self == NULL)
- {
- return 0;
- }
- else
- {
- return self->iRun;
- }
+ status = PauseExecution((pExeList) pData);
+ if (status) {
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ SCWrite(pCon, "ERROR: failed to pause", eError);
+ return 0;
}
-/*--------------------------------------------------------------------------*/
- SConnection *GetExeOwner(pExeList self)
- {
- if(self == NULL)
- return NULL;
+}
- return self->pOwner;
+ /*---------------------------------------------------------------------*/
+int DevexecAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ int val;
+ char pBueffel[256];
+ void *data = NULL;
+ pDummy pDum = NULL;
+ float fTarget;
+ CommandList *pCom = NULL;
+
+ pExeList self = (pExeList) pData;
+ if (argc < 2) {
+ SCWrite(pCon, "ERROR: not enough argumentd to devexec command",
+ eError);
+ return 0;
}
-/*--------------------------------------------------------------------------*/
- int DevExecTask(void *pData)
- {
- pExeList self = NULL;
- char pBueffel[132], pInterrupt[80];
- int iRet, iInterrupt;
-
- self = (pExeList)pData;
-
- /* am I bound to end ? */
- if(self->iEnd)
- {
- self->lTask = -1;
- SetStatus(eEager);
- return 0;
- }
-
- if(self->taskRunning == 1){
- printf("DevexecTask reentrant protection triggered\n");
- return 1;
- }
- /*
- * CheckExeList may cause waits and thus reentrant calls to
- * this. Which can cause trouble
- */
- self->taskRunning = 1;
- iRet = CheckExeList(self);
- self->taskRunning = 0;
-
-
- self->lastRun = time(NULL);
- switch(iRet)
- {
- case -1: /* some problem */
- iInterrupt = SCGetInterrupt(self->pOwner);
- if(iInterrupt != eContinue)
- {
- if(iInterrupt > 1)
- {
- self->taskRunning = 1;
- StopExe(self,"all");
- self->taskRunning = 0;
- }
-#ifdef DEBUG
- printf("DevExecTask found an error\n");
-#endif
- return 1;
- }
- else
- {
- return 1;
- }
- break;
- case 1: /* Success */
- self->lTask = -1;
- self->iEnd = 1;
- SetStatus(eEager);
-#ifdef DEBUG
- printf("DevExecTask finishes on success\n");
-#endif
- return 0;
- break;
- default: /* continue, still busy */
- return 1;
- }
- /* should not get here */
+ strtolower(argv[1]);
+ if (strcmp(argv[1], "driveprint") == 0) {
+ if (argc > 2 && SCMatchRights(pCon, usUser)) {
+ val = atoi(argv[2]);
+ self->drivePrint = val;
+ SCSendOK(pCon);
return 1;
- }
-/*---------------------------------------------------------------------------*/
- void DevExecSignal(void *pEL, int iSignal, void *pSigData)
- {
- int *iInt;
- pExeList self = NULL;
-
- self = (pExeList)pEL;
- assert(self);
-
- if(iSignal == SICSINT)
- {
- iInt = (int *)pSigData;
- if(*iInt != eContinue)
- {
- if(self->pOwner)
- {
- SCPushContext(self->pOwner,0,"system");
- SCWrite(self->pOwner,
- "ERROR: Interrupting Current Hardware Operation",
- eError);
- SCSetInterrupt(self->pOwner,*iInt);
- SCPopContext(self->pOwner);
- }
- StopExe(self,"all");
- }
+ } else {
+ snprintf(pBueffel, 255, "devexe.drivePrint = %d", self->drivePrint);
+ SCWrite(pCon, pBueffel, eValue);
+ return 1;
+ }
+ } else if(strcmp(argv[1],"force") == 0) {
+ if(argc < 4){
+ SCWrite(pCon,"ERROR: insufficient number of arguments to devexec force",
+ eError);
+ return 0;
+ }
+ pCom = FindCommand(pSics,argv[2]);
+ fTarget = atof(argv[3]);
+ if(pCom == NULL){
+ SCPrintf(pCon,eError,"ERROR: command %s to force not found", argv[2]);
+ return 0;
+ }
+ data = pCom->pData;
+ pDum = (pDummy)data;
+ if(GetDrivableInterface(data) == NULL && GetCountableInterface(data) == NULL ){
+ SCPrintf(pCon,eError,"ERROR: command %s not startable", argv[2]);
+ return 0;
+ }
+ val = ForceStartDevice(self,argv[2],pDum->pDescriptor,data, pCon, fTarget);
+ return val;
+ } else {
+ SCWrite(pCon, "ERROR: unknown subcommand to devexec", eError);
+ return 0;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+int ContinueAction(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ int status;
+ Status eStat;
+
+ eStat = GetStatus();
+ if (eStat != ePaused) {
+ SCWrite(pCon, "ERROR: Not paused, ignored", eError);
+ return 0;
+ }
+
+ status = ContinueExecution((pExeList) pData);
+ if (status) {
+ SCSendOK(pCon);
+ return 1;
+ } else {
+ SCWrite(pCon, "ERROR: failed to pause", eError);
+ return 0;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+int isInRunMode(pExeList self)
+{
+ if (self == NULL) {
+ return 0;
+ } else {
+ return self->iRun;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+SConnection *GetExeOwner(pExeList self)
+{
+ if (self == NULL)
+ return NULL;
+
+ return self->pOwner;
+}
+
+/*--------------------------------------------------------------------------*/
+int DevExecTask(void *pData)
+{
+ pExeList self = NULL;
+ char pBueffel[132], pInterrupt[80];
+ int iRet, iInterrupt;
+
+ self = (pExeList) pData;
+
+ /* am I bound to end ? */
+ if (self->iEnd) {
+ self->lTask = -1;
+ SetStatus(eEager);
+ return 0;
+ }
+
+ if (self->taskRunning == 1) {
+ printf("DevexecTask reentrant protection triggered\n");
+ return 1;
+ }
+ /*
+ * CheckExeList may cause waits and thus reentrant calls to
+ * this. Which can cause trouble
+ */
+ self->taskRunning = 1;
+ iRet = CheckExeList(self);
+ self->taskRunning = 0;
+
+
+ self->lastRun = time(NULL);
+ switch (iRet) {
+ case -1: /* some problem */
+ iInterrupt = SCGetInterrupt(self->pOwner);
+ if (iInterrupt != eContinue) {
+ if (iInterrupt > 1) {
+ self->taskRunning = 1;
+ StopExe(self, "all");
+ self->taskRunning = 0;
}
- }
+#ifdef DEBUG
+ printf("DevExecTask found an error\n");
+#endif
+ return 1;
+ } else {
+ return 1;
+ }
+ break;
+ case 1: /* Success */
+ self->lTask = -1;
+ self->iEnd = 1;
+ SetStatus(eEager);
+#ifdef DEBUG
+ printf("DevExecTask finishes on success\n");
+#endif
+ return 0;
+ break;
+ default: /* continue, still busy */
+ return 1;
+ }
+ /* should not get here */
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+void DevExecSignal(void *pEL, int iSignal, void *pSigData)
+{
+ int *iInt;
+ pExeList self = NULL;
+ SConnection *pCon = NULL;
+
+ self = (pExeList) pEL;
+ assert(self);
+
+ if (iSignal == SICSINT) {
+ iInt = (int *) pSigData;
+ if (*iInt != eContinue) {
+ if (self->pOwner) {
+ pCon = SCCopyConnection(self->pOwner);
+ if (pCon != NULL) {
+ pCon->transID = 0;
+ strcpy(pCon->deviceID, "system");
+ SCWrite(pCon,
+ "ERROR: Interrupting Current Hardware Operation",
+ eError);
+ SCSetInterrupt(pCon, *iInt);
+ SCSetInterrupt(self->pOwner, *iInt);
+ SCDeleteConnection(pCon);
+ }
+ }
+ StopExe(self, "all");
+ }
+ }
+}
+
/*--------------------------------------------------------------------*/
void LockDeviceExecutor(pExeList self)
{
assert(self);
self->iLock = 1;
-}
+}
+
/*--------------------------------------------------------------------*/
void UnlockDeviceExecutor(pExeList self)
{
assert(self);
self->iLock = 0;
-}
+}
+/*--------------------------------------------------------------------*/
+void DevExecInit(void)
+{
+ pExeList pExe = pServ->pExecutor;
-
-
-
-
+ /* commands to do with the executor. Only StopExe carries the
+ DeleteFunction in order to avoid double deletion. All the
+ other commands operate on the same datastructure.
+ */
+ AddCommand(pServ->pSics, "StopExe", StopCommand, DeleteExeList, pExe);
+ AddCommand(pServ->pSics, "ListExe", ListExe, NULL, pExe);
+ AddCommand(pServ->pSics, "sicsidle", SicsIdle, NULL, pExe);
+ AddCommand(pServ->pSics, "Success", Success, NULL, pExe);
+ AddCommand(pServ->pSics, "pause", PauseAction, NULL, pExe);
+ AddCommand(pServ->pSics, "continue", ContinueAction, NULL, pExe);
+ AddCommand(pServ->pSics, "devexec", DevexecAction, NULL, pExe);
+}
+/*---------------------------------------------------------------------*/
+void *GetExecutorCallback(pExeList self)
+{
+ return self->pCall;
+}
diff --git a/devexec.h b/devexec.h
index 028d5e37..3a8a1668 100644
--- a/devexec.h
+++ b/devexec.h
@@ -1,5 +1,5 @@
-#line 195 "devexec.w"
+#line 202 "devexec.w"
/*----------------------------------------------------------------------------
@@ -37,6 +37,9 @@
#define DEVERROR 2
#define DEVBUSY 3
+/* run level codes */
+#define RUNRUN 0
+#define RUNDRIVE 1
/*------------------------------------------------------------------------
B I R T H & D E A T H
*/
@@ -48,17 +51,17 @@
#line 43 "devexec.w"
int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,
- void *pData, SConnection *pCon, float fNew);
+ void *pData, SConnection *pCon, int level, float fNew);
int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon,
- char *name, float fNew);
+ char *name, int level, float fNew);
int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon,
- char *name);
+ int level, char *name);
-#line 239 "devexec.w"
+#line 249 "devexec.w"
/*------------------------------------------------------------------------*/
-#line 88 "devexec.w"
+#line 89 "devexec.w"
int CheckExeList(pExeList self);
/*
@@ -69,11 +72,13 @@
long GetDevexecID(pExeList self);
+ int DevExecLevelRunning(pExeList self, int level);
+
int DevExecTask(void *pEL);
void DevExecSignal(void *pEL, int iSignal, void *pSigData);
-#line 241 "devexec.w"
+#line 251 "devexec.w"
/*
@@ -93,7 +98,7 @@
*/
/*-------------------------------------------------------------------------*/
-#line 137 "devexec.w"
+#line 142 "devexec.w"
int StopExe(pExeList self, char *name);
int StopExeWait(pExeList self);
@@ -104,6 +109,8 @@
StopExeWait will stop all running things and wait for the stop
to complete.
*/
+ int StopByData(pExeList self, void *data);
+ /* stop the entry with the given data from execution */
/*------------------------------------------------------------------------*/
void ClearExecutor(pExeList self);
/*
@@ -115,7 +122,7 @@
int ContinueExecution(pExeList self);
-#line 259 "devexec.w"
+#line 269 "devexec.w"
/*-------------------------- Commands ------------------------------------*/
int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
@@ -157,18 +164,25 @@
/*--------------------------- Locking ---------------------------------*/
-#line 183 "devexec.w"
+#line 190 "devexec.w"
void LockDeviceExecutor(pExeList self);
void UnlockDeviceExecutor(pExeList self);
-#line 299 "devexec.w"
+#line 309 "devexec.w"
/* -------------------------- Executor management -------------------------*/
pExeList GetExecutor(void);
void SetExecutor(pExeList pExe);
+
+ /**
+ * This is only used in sicshdbadapter.c
+ * It became a void pointer because of circular dependencies in the
+ * header files.
+ */
+ void *GetExecutorCallback(pExeList self);
/*----------------------- Logging -----------------------------------------*/
void DevexecLog(char *op, char *device);
#endif
diff --git a/devexec.tex b/devexec.tex
index 6ebd2463..1539537a 100644
--- a/devexec.tex
+++ b/devexec.tex
@@ -47,12 +47,12 @@ $\langle$devreg {\footnotesize ?}$\rangle\equiv$
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,@\\
-\mbox{}\verb@ void *pData, SConnection *pCon, float fNew);@\\
+\mbox{}\verb@ void *pData, SConnection *pCon, int level, float fNew);@\\
\mbox{}\verb@ int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon,@\\
-\mbox{}\verb@ char *name, float fNew);@\\
+\mbox{}\verb@ char *name, int level, float fNew);@\\
\mbox{}\verb@ int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon,@\\
-\mbox{}\verb@ char *name); @\\
-\mbox{}\verb@@$\diamond$
+\mbox{}\verb@ int level, char *name); @\\
+\mbox{}\verb@@$\Diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
@@ -67,6 +67,7 @@ The main interface function is {\bf StartDevice}. The parameters are:
\item {\bf name}. The name of the object which operates.
\item {\bf pDes}. A pointer to the ObjectDescriptor of the object to drive or count.
\item {\bf pData}. A pointer to the data structure coming with the object.
+\item {\bf level} The start level of the device.
\item {\bf pCon}. A pointer to the client connection on whose request the
operation was initiated.
\item {\bf fNew}. A floating point value which sets the target value for
@@ -112,10 +113,12 @@ $\langle$devcheck {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@@\\
\mbox{}\verb@ long GetDevexecID(pExeList self);@\\
\mbox{}\verb@@\\
+\mbox{}\verb@ int DevExecLevelRunning(pExeList self, int level);@\\
+\mbox{}\verb@@\\
\mbox{}\verb@ int DevExecTask(void *pEL);@\\
\mbox{}\verb@ void DevExecSignal(void *pEL, int iSignal, void *pSigData);@\\
\mbox{}\verb@@\\
-\mbox{}\verb@@$\diamond$
+\mbox{}\verb@@$\Diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
@@ -155,6 +158,8 @@ properly finished operation, DEVERROR for an operation which finished
with an error code and DEVINT for an aoperation which was interrupted
by the user.
+ {\bf DevExeclevelRunning} tests if the level given as a parameter is still running.
+
\subsubsection{Influencing Execution}
In certain cases it is necessary to interact with running devices directly.
This is done via the following interface.
@@ -174,6 +179,8 @@ $\langle$devstop {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ StopExeWait will stop all running things and wait for the stop@\\
\mbox{}\verb@ to complete.@\\
\mbox{}\verb@ */@\\
+\mbox{}\verb@ int StopByData(pExeList self, void *data);@\\
+\mbox{}\verb@ /* stop the entry with the given data from execution */@\\
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
\mbox{}\verb@ void ClearExecutor(pExeList self);@\\
\mbox{}\verb@ /*@\\
@@ -184,7 +191,7 @@ $\langle$devstop {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ int PauseExecution(pExeList self);@\\
\mbox{}\verb@ int ContinueExecution(pExeList self);@\\
\mbox{}\verb@@\\
-\mbox{}\verb@@$\diamond$
+\mbox{}\verb@@$\Diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
@@ -226,7 +233,7 @@ $\langle$devlock {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ void LockDeviceExecutor(pExeList self);@\\
\mbox{}\verb@ void UnlockDeviceExecutor(pExeList self);@\\
\mbox{}\verb@@\\
-\mbox{}\verb@@$\diamond$
+\mbox{}\verb@@$\Diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
@@ -283,6 +290,9 @@ to the global SICS device executor.
\mbox{}\verb@#define DEVERROR 2@\\
\mbox{}\verb@#define DEVBUSY 3@\\
\mbox{}\verb@@\\
+\mbox{}\verb@/* run level codes */@\\
+\mbox{}\verb@#define RUNRUN 0@\\
+\mbox{}\verb@#define RUNDRIVE 1@\\
\mbox{}\verb@/*------------------------------------------------------------------------@\\
\mbox{}\verb@ B I R T H & D E A T H@\\
\mbox{}\verb@*/@\\
@@ -355,10 +365,17 @@ to the global SICS device executor.
\mbox{}\verb@ @\\
\mbox{}\verb@ pExeList GetExecutor(void);@\\
\mbox{}\verb@ void SetExecutor(pExeList pExe);@\\
+\mbox{}\verb@ @\\
+\mbox{}\verb@ /**@\\
+\mbox{}\verb@ * This is only used in sicshdbadapter.c@\\
+\mbox{}\verb@ * It became a void pointer because of circular dependencies in the @\\
+\mbox{}\verb@ * header files.@\\
+\mbox{}\verb@ */ @\\
+\mbox{}\verb@ void *GetExecutorCallback(pExeList self);@\\
\mbox{}\verb@/*----------------------- Logging -----------------------------------------*/@\\
\mbox{}\verb@ void DevexecLog(char *op, char *device); @\\
\mbox{}\verb@#endif @\\
-\mbox{}\verb@@$\diamond$
+\mbox{}\verb@@$\Diamond$
\end{list}
\vspace{-2ex}
\end{minipage}\\[4ex]
diff --git a/devexec.w b/devexec.w
index 12acf662..0f2cca05 100644
--- a/devexec.w
+++ b/devexec.w
@@ -42,11 +42,11 @@ functions are provided.
@d devreg @{
int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,
- void *pData, SConnection *pCon, float fNew);
+ void *pData, SConnection *pCon, int level, float fNew);
int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon,
- char *name, float fNew);
+ char *name, int level, float fNew);
int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon,
- char *name);
+ int level, char *name);
@}
The main interface function is {\bf StartDevice}. The parameters are:
@@ -55,6 +55,7 @@ The main interface function is {\bf StartDevice}. The parameters are:
\item {\bf name}. The name of the object which operates.
\item {\bf pDes}. A pointer to the ObjectDescriptor of the object to drive or count.
\item {\bf pData}. A pointer to the data structure coming with the object.
+\item {\bf level} The start level of the device.
\item {\bf pCon}. A pointer to the client connection on whose request the
operation was initiated.
\item {\bf fNew}. A floating point value which sets the target value for
@@ -95,6 +96,8 @@ From within the SICS main loops this special function is called:
long GetDevexecID(pExeList self);
+ int DevExecLevelRunning(pExeList self, int level);
+
int DevExecTask(void *pEL);
void DevExecSignal(void *pEL, int iSignal, void *pSigData);
@@ -130,6 +133,8 @@ properly finished operation, DEVERROR for an operation which finished
with an error code and DEVINT for an aoperation which was interrupted
by the user.
+ {\bf DevExeclevelRunning} tests if the level given as a parameter is still running.
+
\subsubsection{Influencing Execution}
In certain cases it is necessary to interact with running devices directly.
This is done via the following interface.
@@ -144,6 +149,8 @@ This is done via the following interface.
StopExeWait will stop all running things and wait for the stop
to complete.
*/
+ int StopByData(pExeList self, void *data);
+ /* stop the entry with the given data from execution */
/*------------------------------------------------------------------------*/
void ClearExecutor(pExeList self);
/*
@@ -229,6 +236,9 @@ to the global SICS device executor.
#define DEVERROR 2
#define DEVBUSY 3
+/* run level codes */
+#define RUNRUN 0
+#define RUNDRIVE 1
/*------------------------------------------------------------------------
B I R T H & D E A T H
*/
@@ -301,6 +311,13 @@ to the global SICS device executor.
pExeList GetExecutor(void);
void SetExecutor(pExeList pExe);
+
+ /**
+ * This is only used in sicshdbadapter.c
+ * It became a void pointer because of circular dependencies in the
+ * header files.
+ */
+ void *GetExecutorCallback(pExeList self);
/*----------------------- Logging -----------------------------------------*/
void DevexecLog(char *op, char *device);
#endif
diff --git a/devser.c b/devser.c
index 4f70e653..506a168e 100644
--- a/devser.c
+++ b/devser.c
@@ -1,6 +1,8 @@
+#include
#include
#include "ascon.h"
#include "devser.h"
+#include "dynstring.h"
typedef struct DevAction {
struct DevAction *next;
@@ -8,147 +10,276 @@ typedef struct DevAction {
DevActionHandler *hdl;
DevPrio prio;
DevKillActionData *kill;
+ double interval; /* -1 for a queued action */
+ double timeDue; /* 0 for a queued action */
+ DevInfoFunc *infoFunc;
} DevAction;
-typedef struct SchedHeader {
- struct SchedHeader *next;
- DevAction *actions; /* list of actions for given interval and prio */
- DevAction *followingAction;
- double interval;
- double timeDue;
- DevPrio prio;
-} SchedHeader;
-
struct DevSer {
- Ascon *asyncConn; /* connection */
+ Ascon *ascon; /* connection */
DevAction *current;
int killCurrent;
- DevAction *actions; /* the action queue */
- SchedHeader *headers;
- ErrMsg *errmsg;
+ DevAction *actions; /* the action queue */
+ DevAction *toKill; /* list of actions to be killed */
int steps;
- int stopTask;
-};
+ AsconStatus status;
-static char *devPrio[NumberOfPRIO] = {
- "null", "slow", "read", "progress", "write", "halt"
+ /* fields for statistics: */
+ double startTime;
+ double comCount;
+ long nComCount;
+ int comMaxState;
+ double comMax;
+ long errorCount;
+ int inError;
+ double asconStart;
+ double asconSum;
+ double asconMax;
+ long asconCount;
+ int asconState, asconMaxState;
+ int maxCount;
};
-char *DevPrio2Text(DevPrio prio) {
+static char *devPrio[NumberOfPRIO] = {
+ "null", "slow", "read", "progress", "write", "halt", "start"
+};
+
+char *DevPrio2Text(DevPrio prio)
+{
if (prio <= 0 || prio >= NumberOfPRIO) {
prio = NullPRIO;
}
- return devPrio[prio];
+ return devPrio[prio];
}
-DevPrio DevText2Prio(char *text) {
+DevPrio DevText2Prio(char *text)
+{
DevPrio prio;
for (prio = 0; prio < NumberOfPRIO; prio++) {
- if (strcasecmp(text, devPrio[prio]) == 0) return prio;
+ if (strcasecmp(text, devPrio[prio]) == 0)
+ return prio;
}
return NullPRIO;
}
-static void DevFreeActionList(DevAction *actions) {
+static void DevFreeActionList(DevAction * actions)
+{
DevAction *victim;
while (actions != NULL) {
victim = actions;
actions = victim->next;
- if (victim->kill != NULL) victim->kill(victim->data);
+ assert(victim->data != NULL);
+ if (victim->kill != NULL)
+ victim->kill(victim->data);
+ victim->data=NULL;
free(victim);
}
}
-static void DevKillTask(void *ds) {
- DevSer *devser = ds;
-
- if (devser->stopTask) {
- free(devser);
+static double nextTime(double due,
+ double lastInterval,
+ double now,
+ double interval) {
+ double base;
+ /* nextTime gives the next possible time according to the
+ * following rules:
+ * (1) result > now
+ * (2) result is a multiple of interval
+ * (3) result >= due OR result >= due - lastInterval + interval
+ */
+ if (interval > lastInterval) {
+ base = due - lastInterval * 0.01;
} else {
- devser->stopTask = 1;
+ base = due - lastInterval + interval * 0.99;
}
+ if (now > base) {
+ base = now;
+ }
+ return (floor(base / interval) + 1) * interval;
}
-DevAction *DevNextAction(DevSer *devser) {
+
+static DevAction *DevNextAction(DevSer * devser)
+{
+/* the action queue is primarily ordered by priority (high priority first),
+ * within one priority by usage (last used action at end)
+ */
DevPrio prio;
- double now;
- SchedHeader *header;
-
+ double now, next;
+ DevAction *action, **ptr2prev;
devser->current = NULL;
- if (devser->actions) {
- prio = devser->actions->prio;
- } else {
- prio = NullPRIO;
- }
now = DoubleTime();
- for (header = devser->headers;
- header != NULL && header->prio > prio;
- header = header->next) {
- if (header->followingAction == NULL) {
- if (now >= header->timeDue) {
- header->followingAction = header->actions;
- if (header->interval <= 0) {
- header->timeDue = now;
+ for (ptr2prev = &devser->actions, action = devser->actions;
+ action != NULL;
+ ptr2prev = &action->next, action = action->next) {
+ if (now >= action->timeDue) {
+ /* remove action from queue */
+ *ptr2prev = action->next;
+ devser->current = action;
+ if (action->interval >= 0) {
+ /* this is a scheduled action, to be preserved after use */
+ devser->killCurrent = 0;
+ if (action->interval == 0) {
+ action->timeDue = now;
} else {
- header->timeDue = (floor(now / header->interval) + 1)
- * header->interval;
+ /* increase timeDue according to interval */
+ action->timeDue = nextTime(0, 0, now, action->interval);
}
+ prio = action->prio;
+
+ /* insert devser->current before the next lower priority */
+ for (action = action->next; /* start after this */
+ action != NULL && action->prio >= prio;
+ ptr2prev = &action->next, action = action->next);
+
+ /* action is now NULL or the next action with lower priority */
+ *ptr2prev = devser->current;
+ devser->current->next = action;
+ } else {
+ /* this is a queued action, to be killed after use */
+ devser->killCurrent = 1;
}
- }
- if (header->followingAction != NULL) {
- devser->current = header->followingAction;
- devser->killCurrent = 0;
- header->followingAction = header->followingAction->next;
return devser->current;
}
+ if (action->prio == StartPRIO) {
+ /* if a poll with StartPRIO is scheduled, block all other actions */
+ return NULL;
+ }
}
- if (devser->actions) {
- devser->current = devser->actions;
- devser->killCurrent = 1;
- devser->actions = devser->actions->next;
- }
- return devser->current;
+ return NULL;
+}
+static void LogStart(DevSer *self)
+{
+ if(self->startTime > 0){
+ printf("DEVSER: there is something fucked up in LogStart. Investigate!\n");
+ }
+ self->startTime = DoubleTime();
+}
+static void LogResponse(DevSer *self, int error)
+{
+ double responseTime;
+
+ if(self->startTime < 0){
+ printf("DEVSER: there is something fucked up in LogResponse, Investigate!\n");
+ self->startTime = -1;
+ return;
+ }
+ responseTime = DoubleTime() - self->startTime;
+ self->comCount += responseTime;
+ if(responseTime > self->comMax){
+ self->comMax = responseTime;
+ }
+ self->nComCount++;
+ if(error == 1 && self->inError == 0){
+ self->errorCount++;
+ self->inError = 1;
+ } else if(error == 0){
+ self->inError = 0;
+ }
+ self->startTime = -1;
+ if(responseTime > self->comMax/2.){
+ self->comMaxState++;
+ }
+}
+static void StartAscon(DevSer *self)
+{
+ self->asconStart = DoubleTime();
+ self->asconState = AsconLastState(self->ascon);
+}
+static void AsconLog(DevSer *self)
+{
+ double used;
+
+ used = DoubleTime() - self->asconStart;
+ self->asconSum += used;
+ self->asconCount++;
+ if(used > self->asconMax){
+ self->asconMax = used;
+ self->asconMaxState = self->asconState;
+ }
+ if(used > self->asconMax/2.){
+ self->maxCount++;
+ }
+}
+void DevStatistics(DevSer *devser, double *avg, double *max,
+ int *maxCount, long *errCount, int *errState)
+{
+ if(devser->nComCount > 0){
+ *avg = devser->comCount/devser->nComCount;
+ } else {
+ *avg = 0; /* no data!*/
+ }
+ *max = devser->comMax;
+ *errCount = devser->errorCount;
+ *errState = devser->inError;
+ *maxCount = devser->maxCount;
+}
+void DevAsconStatistics(DevSer *self, double *avg, \
+ double *max, int *maxState, int *longCount)
+{
+ if(self->asconCount > 0){
+ *avg = self->asconSum/self->asconCount;
+ } else {
+ *avg = .0;
+ }
+ *max = self->asconMax;
+ *maxState = self->asconMaxState;
+ *longCount = self->maxCount;
}
-int DevQueueTask(void *ds) {
+static int DevQueueTask(void *ds)
+{
DevSer *devser = ds;
- AsconStatus status;
DevAction *action;
char *sendData;
- char *replyData;
+ char *replyData = NULL;
+ if (devser->steps == 0)
+ return 1;
+
+ /* deferred deallocation of removed actions */
+ DevFreeActionList(devser->toKill);
+ devser->toKill = NULL;
- if (devser->steps == 0) return 1;
- if (devser->stopTask) {
- return 0;
- }
action = devser->current;
if (action == NULL) {
action = DevNextAction(devser);
}
while (action != NULL) {
- status = AsconTask(devser->asyncConn);
- if (status == AsconFailure) {
- devser->errmsg = AsconGetErrList(devser->asyncConn);
- } else if (status != AsconReady) {
- return 1;
+ StartAscon(devser);
+ devser->status = AsconTask(devser->ascon);
+ AsconLog(devser);
+ if (devser->status >= AsconFailure) {
+ replyData = AsconGetError(devser->ascon);
+ /**
+ * TODO: this may be a place to record the end time
+ */
+ if(devser->startTime > 0){
+ LogResponse(devser,1);
+ } else {
+ /* This is a follow up error and should not go into statistics */
+ }
+ } else if (devser->status == AsconReady) {
+ replyData = AsconRead(devser->ascon);
+ if(replyData != NULL){
+ LogResponse(devser,0);
+ }
+ } else {
+ return 1;
}
- if (devser->steps > 0) { /* debugging mode */
+ if (devser->steps > 0) { /* debugging mode */
devser->steps--;
}
- if(status == AsconFailure){
- replyData = devser->errmsg->text;
- } else {
- replyData = AsconRead(devser->asyncConn);
- }
- sendData = action->hdl(action->data, replyData);
+ sendData = action->hdl(action->data, replyData, (devser->status != AsconReady));
if (sendData != NULL) {
- AsconWrite(devser->asyncConn, sendData, 0);
+ AsconWrite(devser->ascon, sendData, 0);
+ LogStart(devser);
return 1;
}
if (devser->killCurrent) {
- if (action->kill != NULL) action->kill(action->data);
+ if (action->kill != NULL)
+ action->kill(action->data);
devser->killCurrent = 0;
free(action);
devser->current = NULL;
@@ -158,219 +289,315 @@ int DevQueueTask(void *ds) {
return 1;
}
-void DevSigFun(void *ds, int iSignal, void *pSigData) {
- DevSer *devser = ds;
- AsconStatus status;
- DevAction *action;
- SchedHeader *header;
-
- if (devser->stopTask) {
- return;
- }
- for (header = devser->headers; header != NULL; header = header->next) {
- // TODO ffr Set interrupt level on the action handler node's sics_int property
- // An action handler should clear the sics_int property after it is called.
- }
-}
-
-DevSer *DevMake(SConnection *con, int argc, char *argv[]) {
+DevSer *DevMake(SConnection * con, int argc, char *argv[])
+{
DevSer *devser = NULL;
- Ascon *asyncConn = NULL;
-
- asyncConn = AsconMake(con, argc, argv);
- if (!asyncConn) {
+ Ascon *ascon = NULL;
+
+ ascon = AsconMake(con, argc, argv);
+ if (!ascon) {
return NULL;
}
devser = calloc(1, sizeof(*devser));
assert(devser);
- devser->asyncConn = asyncConn;
+ devser->ascon = ascon;
devser->current = NULL;
devser->killCurrent = 0;
devser->actions = NULL;
- devser->headers = NULL;
- devser->stopTask = 0;
- devser->steps = -1; /* no debugging by default */
- TaskRegister(pServ->pTasker, DevQueueTask, NULL, DevKillTask, devser, 0);
+ devser->toKill = NULL;
+ devser->steps = -1; /* no debugging by default */
+ devser->status = AsconUnconnected;
+ devser->startTime = -1;
+ TaskRegister(pServ->pTasker, DevQueueTask, NULL, NULL, devser, 0);
return devser;
}
-void DevDebugMode(DevSer *devser, int steps) {
+void DevDebugMode(DevSer * devser, int steps)
+{
devser->steps = steps;
}
-DevAction *DevNewAction(void *data, DevActionHandler hdl,
- DevKillActionData *killFunc, DevPrio prio) {
- DevAction *action;
- action = calloc(1, sizeof(*action));
- assert(action);
- action->data = data;
- action->hdl = hdl;
- action->kill = killFunc;
- action->prio = prio;
- action->next = NULL;
- return action;
-}
-
-void DevKill(DevSer *devser) {
- SchedHeader *h, *victim;
-
- if (devser->asyncConn) {
- AsconKill(devser->asyncConn);
- }
+static void DevReset(DevSer * devser)
+{
+ /*
DevFreeActionList(devser->actions);
- h = devser->headers;
- while (h != NULL) {
- victim = h;
- h = victim->next;
- DevFreeActionList(victim->actions);
- free(victim);
- }
- if (devser->stopTask) {
- free(devser);
- } else {
- devser->stopTask = 1;
- }
-}
-
-void DevQueue(DevSer *devser, void *actionData, DevPrio prio,
- DevActionHandler hdl, DevActionMatch *matchFunc,
- DevKillActionData *killFunc) {
- DevAction *action, **ptr2Last;
- DevAction *new;
-
- if (prio <= NullPRIO) prio = NullPRIO + 1;
- if (prio >= NumberOfPRIO) prio = NumberOfPRIO - 1;
- ptr2Last = &devser->actions;
- for (action = devser->actions; action != NULL && action->prio >= prio; action = action->next) {
- if (action->hdl == hdl && matchFunc(actionData, action->data)) {
- return; /* there is already an identical action */
+ devser->actions = NULL;
+ */
+ DevFreeActionList(devser->toKill);
+ devser->toKill = NULL;
+ if (devser->killCurrent) {
+ if (devser->current->kill != NULL) {
+ devser->current->kill(devser->current->data);
}
- ptr2Last = &action->next;
+ devser->killCurrent = 0;
+ /* free(devser->current); */
}
- new = DevNewAction(actionData, hdl, killFunc, prio);
- new->next = action;
- *ptr2Last = new;
}
-int DevUnschedule(DevSer *devser, void *actionData,
- DevActionHandler hdl, DevActionMatch *matchFunc) {
- SchedHeader *header = NULL;
- DevAction **ptr2Last = NULL;
- DevAction *action = NULL;
- int cnt=0;
-
- /* scan through all headers */
- for (header = devser->headers; header != NULL; header = header->next) {
- ptr2Last = &header->actions;
- for (action = header->actions; action != NULL; action = *ptr2Last) {
- if (action->hdl == hdl && matchFunc(actionData, action->data)) {
- if (action == header->followingAction) {
- /* advance followingAction if equal*/
- header->followingAction = action->next;
- }
- if (action == devser->current) {
- devser->current = NULL;
- devser->killCurrent = 0; /* should already be 0 */
- }
- cnt++;
- /* remove from list */
- *ptr2Last = action->next;
- if (action->kill != NULL) action->kill(action->data);
- free(action);
- } else {
- ptr2Last = &action->next;
+void DevKill(DevSer * devser)
+{
+ if (devser->ascon) {
+ AsconKill(devser->ascon);
+ }
+ DevReset(devser);
+ TaskRemove(pServ->pTasker, DevQueueTask, devser);
+ free(devser);
+}
+
+void DevDisconnect(DevSer * devser)
+{
+ DevReset(devser);
+ if (devser->ascon) {
+ AsconDisconnect(devser->ascon);
+ }
+ devser->status = AsconOffline;
+}
+
+void DevReconnect(DevSer * devser, char *hostport)
+{
+ /* DevReset(devser); */
+ if (devser->ascon) {
+ AsconReconnect(devser->ascon, hostport);
+ }
+}
+
+int DevUnschedule(DevSer * devser, void *callData,
+ DevActionHandler * hdl, DevActionMatch * matchFunc)
+{
+ DevAction **ptr2prev = NULL;
+ DevAction *action = NULL;
+ int cnt = 0;
+
+ /* scan through the queue */
+ for (ptr2prev = &devser->actions, action = devser->actions;
+ action != NULL;
+ action = action->next) {
+ if (action->hdl == hdl && matchFunc(callData, action->data)) {
+ if (action == devser->current) {
+ devser->current = NULL;
+ devser->killCurrent = 0;
}
+ cnt++;
+ /* remove from list */
+ *ptr2prev = action->next;
+ /* add to kill list */
+ action->next = devser->toKill;
+ devser->toKill = action;
+ } else {
+ ptr2prev = &action->next;
}
}
return cnt;
}
-int DevSchedule(DevSer *devser, void *actionData,
+int DevSchedule(DevSer * devser, void *actionData,
DevPrio prio, double interval,
- DevActionHandler hdl, DevActionMatch *matchFunc,
- DevKillActionData *killFunc) {
- SchedHeader *header = NULL;
- SchedHeader **ptr2LastHeader = NULL;
- SchedHeader *newHeader;
- DevAction *action = NULL;
- DevAction **ptr2Last = NULL;
- DevAction *newAction;
+ DevActionHandler * hdl, DevActionMatch * matchFunc,
+ DevKillActionData * killFunc, DevInfoFunc * infoFunc)
+{
+ DevAction *action;
+ DevAction *foundAction = NULL;
+ DevAction **ptr2prev;
+ DevAction **ptr2insertPos = NULL;
int ret;
- if (prio <= NullPRIO) prio = NullPRIO + 1;
- if (prio >= NumberOfPRIO) prio = NumberOfPRIO - 1;
- ret = DevUnschedule(devser, actionData, hdl, matchFunc);
+ assert(killFunc == NULL || actionData != NULL);
+ if (prio <= NullPRIO) {
+ prio = NullPRIO + 1;
+ }
+ if (prio >= NumberOfPRIO) {
+ prio = NumberOfPRIO - 1;
+ }
- newAction = DevNewAction(actionData, hdl, killFunc, prio);
- /* find matching header */
- ptr2LastHeader = &devser->headers;
- for (header = devser->headers; header != NULL; header = *ptr2LastHeader) {
- if (header->prio == newAction->prio && header->interval == interval) {
- /* append new action at the tail */
- ptr2Last = &header->actions;
- for (action = header->actions; action != NULL; action=action->next) {
- ptr2Last = &action->next;
- }
- *ptr2Last = newAction;
- assert(newAction->next == NULL);
- return ret;
- } else if (header->prio < newAction->prio ||
- (header->prio == newAction->prio
- && header->interval > interval)) {
- break;
+ /* find similar action and the point, where we have to insert */
+ for (ptr2prev = &devser->actions, action = devser->actions;
+ action != NULL;
+ action = action->next) {
+ if (action->prio < prio && ptr2insertPos == NULL) {
+ ptr2insertPos = ptr2prev;
}
- if (header->actions == NULL) {
- /* remove empty header */
- *ptr2LastHeader = header->next;
- free(header);
+ /* check if it is the same action (only once) */
+ if (action->hdl == hdl
+ && action->kill == killFunc
+ && (interval < 0) == (action->interval < 0)
+ && foundAction == NULL
+ && matchFunc(actionData, action->data)) {
+ if (prio == action->prio && interval < 0) {
+ /* do not move an action with equal prio */
+ if (killFunc) {
+ killFunc(actionData);
+ }
+ return 0; /* not queued */
+ }
+ /* remove action from list */
+ *ptr2prev = action->next;
+ foundAction = action;
} else {
- ptr2LastHeader = &header->next;
+ ptr2prev = &action->next;
}
}
- /* insert new header */
- newHeader = calloc(1, sizeof(*newHeader));
- assert(newHeader);
- newHeader->actions = newAction;
- newHeader->followingAction = NULL;
- newHeader->prio = newAction->prio;
- newHeader->interval = interval;
- newHeader->next = header;
- newHeader->timeDue = DoubleTime() + interval;
- *ptr2LastHeader = newHeader;
- return ret;
+ if (foundAction != NULL) {
+ /* a similar action was found */
+ action = foundAction;
+ if (killFunc) {
+ killFunc(actionData);
+ }
+ ret = 0;
+ } else {
+ /* create if needed */
+ action = calloc(1, sizeof(*action));
+ assert(action);
+ action->data = actionData;
+ action->hdl = hdl;
+ action->kill = killFunc;
+ action->infoFunc = infoFunc;
+ action->timeDue = 0;
+ ret = 1;
+ }
+
+ action->prio = prio;
+ /* insert into queue */
+ if (ptr2insertPos == NULL) {
+ ptr2insertPos = ptr2prev;
+ }
+ action->next = *ptr2insertPos;
+ *ptr2insertPos = action;
+
+ if (interval < 0) { /* case "queued" */
+ action->interval = -1.0;
+ } else { /* case "scheduled" */
+ if (action->timeDue == 0) { /* not yet scheduled: do it immediately */
+ action->timeDue = DoubleTime();
+ } else { /* calculate next time */
+ action->timeDue = nextTime(action->timeDue, action->interval,
+ DoubleTime(), interval);
+ }
+ action->interval = interval;
+ }
+ return ret; /* when 0, actionData was killed */
}
-int DevRemoveAction(DevSer *devser, void *actionData) {
- SchedHeader *header = NULL;
- DevAction **ptr2Last = NULL;
+int DevQueue(DevSer * devser, void *actionData, DevPrio prio,
+ DevActionHandler * hdl, DevActionMatch * matchFunc,
+ DevKillActionData * killFunc, DevInfoFunc *infoFunc)
+{
+ return DevSchedule(devser, actionData, prio, -1.0, hdl
+ , matchFunc, killFunc, infoFunc);
+}
+
+int DevRemoveAction(DevSer * devser, void *actionData)
+{
+ DevAction **ptr2prev = NULL;
DevAction *action = NULL;
- int cnt=0;
+ int cnt = 0;
-
- /* Remove current action, if matched. If a reply is pending, the next action will
- get the reply. But as in the inital state no reply is expected, this should not harm. */
+ /* Remove current action, if matched. If a reply is pending, the next
+ action will get the reply. But as in the inital state no reply is
+ expected, this should not harm. */
action = devser->current;
if (action != NULL && actionData == action->data) {
if (devser->killCurrent) {
- if (action->kill != NULL) action->kill(action->data);
+ if (action->kill != NULL)
+ action->kill(action->data);
devser->killCurrent = 0;
free(action);
}
devser->current = NULL;
}
/* remove from queue */
- ptr2Last = &devser->actions;
- for (action = devser->actions; action != NULL; action = action->next) {
+ ptr2prev = &devser->actions;
+ for (action = devser->actions; action != NULL; action = *ptr2prev) {
if (actionData == action->data) {
cnt++;
/* remove from list */
- *ptr2Last = action->next;
- if (action->kill != NULL) action->kill(action->data);
+ *ptr2prev = action->next;
+ if (action->kill != NULL)
+ action->kill(action->data);
free(action);
} else {
- ptr2Last = &action->next;
+ ptr2prev = &action->next;
}
}
return cnt++;
}
+
+int DevIsPending(DevSer * devser, void *callData,
+ DevActionHandler * hdl, DevActionMatch * matchFunc)
+{
+ DevAction *action = devser->current;
+
+ if (action) {
+ if (action->hdl == hdl && matchFunc(callData, action->data)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+char * DevList(DevSer * devser) {
+ DevAction * action;
+ pDynString result, info;
+ char text[80];
+ char *str;
+
+ result = CreateDynString(63,64);
+ for (action = devser->actions; action != NULL; action = action->next) {
+ if (action->interval < 0) {
+ snprintf(text, sizeof text, "%-8s queued ", DevPrio2Text(action->prio));
+ } else {
+ snprintf(text, sizeof text, "%-8s %8.3g %14.3f ",
+ DevPrio2Text(action->prio), action->interval, action->timeDue);
+ }
+ DynStringConcat(result, text);
+ if (action == devser->current) {
+ DynStringConcat(result, "ACTIVE ");
+ }
+ if (action->infoFunc) {
+ str = action->infoFunc(action->data);
+ DynStringConcat(result, str);
+ free(str);
+ } else {
+ snprintf(text, sizeof text, "%8.8x", (unsigned int)action->data);
+ DynStringConcat(result, text);
+ }
+ DynStringConcat(result, "\n");
+ }
+ str = strdup(GetCharArray(result));
+ DeleteDynString(result);
+ return str;
+}
+
+char *DevHostport(DevSer *devser) {
+ return AsconHostport(devser->ascon);
+}
+
+char *DevStatus(DevSer *devser) {
+ char *str, *pos;
+ static char buf[64];
+
+ switch (devser->status) {
+ case AsconOffline: return "disconnected";
+ case AsconUnconnected: return "unconnected";
+ /*
+ case AsconPending: return "busy";
+ case AsconReady: return "ready";
+ case AsconFailure: return AsconGetError(devser->ascon);
+ */
+ }
+ str = AsconGetError(devser->ascon);
+ if (strncmp(str, "ASCERR: ", 8) == 0) {
+ str += 8;
+ }
+ pos = strchr(str, '(');
+ if (pos != 0) {
+ snprintf(buf, sizeof buf, "%s", str);
+ buf[pos-str] = 0;
+ str = buf;
+ }
+ return str;
+}
+
+double DevGetSetTimeout(DevSer *devser, double timeout, int setmode) {
+ return AsconGetSetTimeout(devser->ascon, timeout, setmode);
+}
diff --git a/devser.h b/devser.h
index 95f29a8a..b91e8f51 100644
--- a/devser.h
+++ b/devser.h
@@ -10,10 +10,12 @@ typedef struct DevSer DevSer;
/** \brief The action handler to be called
* \param actionData the data stored with the action
* \param lastReply the last reply or NULL when no command was
- * sent in the last action
+ * sent in the last action, or the error message (when commError == 1)
+ * \param commError 0: ok, 1: there was a communication error
* \return the command to be sent or NULL if no command has to be sent
*/
-typedef char *DevActionHandler(void *actionData, char *lastReply);
+typedef char *DevActionHandler(void *actionData, char *lastReply,
+ int commError);
/** \brief Check if an action matches the call data
* \param callData the callers data
@@ -27,11 +29,21 @@ typedef int DevActionMatch(void *callData, void *actionData);
*/
typedef void DevKillActionData(void *actionData);
+/** \brief ActionData info function
+ * \param actionData action data
+ * \return textual information about action for listing
+ * the result is an allocated string and has to be freed after use
+ */
+typedef char * DevInfoFunc(void *actionData);
+
/** \brief possible priorities.
* NullPRIO and NumberOfPRIO must not be used as priority
+ * if an action with StartPRIO is scheduled, all other activities
+ * are blocked until the action is unscheduled
*/
typedef enum {
- NullPRIO, SlowPRIO, ReadPRIO, ProgressPRIO, WritePRIO, HaltPRIO, NumberOfPRIO
+ NullPRIO, SlowPRIO, ReadPRIO, ProgressPRIO, WritePRIO, HaltPRIO,
+ StartPRIO, NumberOfPRIO
} DevPrio;
/** \brief Make a new device serializer and async connection.
@@ -40,21 +52,30 @@ typedef enum {
* \param argv the args
* \return the created device serializer or NULL on failure
*/
-DevSer *DevMake(SConnection *con, int argc, char *argv[]);
+DevSer *DevMake(SConnection * con, int argc, char *argv[]);
/** \brief put the device serializer into debug mode
* \param devser the device serializer
* \param steps the number of steps to be executed or -1 for disable debugging mode
*/
-void DevDebugMode(DevSer *devser, int steps);
+void DevDebugMode(DevSer * devser, int steps);
/** \brief Kill the contents of the device serializer and its async connection.
*
* The data structure itself is killed at some time later
* \param devser the device serializer
*/
-void DevKill(DevSer *devser);
-
+void DevKill(DevSer * devser);
+/** \brief disconnect and disable the serializer
+ * \param devser The device serializer to disconnect
+ */
+void DevDisconnect(DevSer * devser);
+/** \brief reconnect the serializer
+ * \param devser The device serializer to reconnect
+ * \param hostport : to reconnect to another port
+ * ar an empty string to reconnect to the same port
+ */
+void DevReconnect(DevSer * devser, char *hostport);
/** \brief Queue an action
*
* If a matching action with the same action handler
@@ -63,14 +84,18 @@ void DevKill(DevSer *devser);
* \param actionData the action data
* \param prio the priority
* \param hdl the action handler
- * \param matchFunc the match function
+ * \param matchFunc a match function with two arguments of the same type
* \param killFunc the action data kill function (called from DevKill and
* after the action has finished, i.e. when hdl returned NULL)
* or NULL if no kill function is needed.
+ * \param infoFunc the actions info function or NULL if no info function
+ * is defined.
+ * \return 1 when this was a new action, 0 when an action was overwritten
+ * in the second case the actionData's kill Function is immediately called
*/
-void DevQueue(DevSer *devser, void *actionData, DevPrio prio,
- DevActionHandler hdl, DevActionMatch *matchFunc,
- DevKillActionData *killFunc) ;
+int DevQueue(DevSer * devser, void *actionData, DevPrio prio,
+ DevActionHandler * hdl, DevActionMatch * matchFunc,
+ DevKillActionData * killFunc, DevInfoFunc * infoFunc);
/** \brief Schedule a periodic action
*
@@ -81,31 +106,43 @@ void DevQueue(DevSer *devser, void *actionData, DevPrio prio,
* \param prio the priority
* \param interval the interval in seconds (0 is allowed)
* \param hdl the action handler
- * \param matchFunc the match function (callData must be of the same type as actionData)
- * \param killFunc the action data kill function (called from DevKill and
- * from DevUnschedule) or NULL if no kill function is needed.
- * \return 0 when this was a new action, > 0 when an action was overwritten
+ * \param matchFunc a match function with two arguments of the same type
+ * \param killFunc the action data kill function or NULL if no kill function is needed.
+ * \param infoFunc the actions info function or NULL if no info function
+ * is defined.
+ * \return 1 when this was a new action, 0 when an action was overwritten
+ * in the second case the actionData's kill Function is immediately called
*/
-int DevSchedule(DevSer *devser, void *actionData,
- DevPrio prio, double interval,
- DevActionHandler hdl, DevActionMatch *matchFunc,
- DevKillActionData *killFunc);
+int DevSchedule(DevSer * devser, void *actionData,
+ DevPrio prio, double interval,
+ DevActionHandler * hdl, DevActionMatch * matchFunc,
+ DevKillActionData * killFunc, DevInfoFunc * infoFunc);
/** \brief Unschedule matching actions
* \param devser the device serializer
- * \param callData the callers data to be as first argument of the match function
+ * \param callData the callers data to be used as first argument of the match function
* \param hdl the action handler
- * \param matchFunc the match function (callData does not need to have the same type as actionData)
+ * \param matchFunc a match function (the first argument might have an other type than the second)
* \return the number of unscheduled actions
*/
-int DevUnschedule(DevSer *devser, void *actionData,
- DevActionHandler hdl, DevActionMatch *matchFunc);
+int DevUnschedule(DevSer * devser, void *callData,
+ DevActionHandler * hdl, DevActionMatch * matchFunc);
/** \brief remove action from the serializer
* \param devser the device serializer
* \param actionData the action data to be compared for a match
*/
-int DevRemoveAction(DevSer *devser, void *actionData);
+int DevRemoveAction(DevSer * devser, void *actionData);
+
+/** \brief check if an action is pending
+ * \param devser the device serializer
+ * \param callData the callers data to be used as first argument of the match function
+ * \param hdl the action handler
+ * \param matchFunc a match function (the first argument might have an other type than the second)
+ * \return the number of unscheduled actions
+ */
+int DevIsPending(DevSer * devser, void *callData,
+ DevActionHandler * hdl, DevActionMatch * matchFunc);
/** \brief Convert integer priority to text
* \param prio
@@ -119,5 +156,55 @@ char *DevPrio2Text(DevPrio prio);
*/
DevPrio DevText2Prio(char *text);
+/** \brief List registered actions
+ * \param devser the device serializer
+ * \return the listing text
+ */
+char * DevList(DevSer * devser);
+
+/**
+ * \brief Get statistics
+ * \param devser The device serializer
+ * \param avg The average response time
+ * \param max The maximum response time
+ * \param maxCount how often the communication took longer then max/2.
+ * \param errCount The count of communication errors detected so far.
+ * \param errFlag A flag if the device is in an error state or not
+ */
+void DevStatistics(DevSer *devser, double *avg, double *max,
+ int *maxCount,
+ long *errCount, int *errFlag);
+/**
+ * \brief Get Ascon invocation statistics. This can help to stop
+ * blocking behaviour in protocol handlers.
+ * \param devser The device serializer to query
+ * \param avg The avgerage time spent in AsconTask invocations
+ * \param max The maximum time spent in a AsconTask call.
+ */
+void DevAsconStatistics(DevSer *self, double *avg,
+ double *max, int *maxState, int *longCount);
+
+/**
+ * \brief return host:port
+ * \param devser The device serializer to query
+ * \return the host and port
+ */
+char *DevHostport(DevSer *devser);
+
+/**
+ * \brief return status of device server ("offline", "unconnected", "")
+ * \param devser The device serializer to query
+ * \return the status
+ */
+char *DevStatus(DevSer *devser);
+
+/**
+ * \brief set or get timeout
+ * \param devser The device serializer to change
+ * \param timeout the timeout to set
+ * \param setmode 0: get, 1: set
+ * \return the timeout value
+ */
+double DevGetSetTimeout(DevSer *devser, double timeout, int setmode);
#endif
diff --git a/dict.c b/dict.c
index d850c288..86da6170 100644
--- a/dict.c
+++ b/dict.c
@@ -19,63 +19,61 @@
#include "napi.h"
#include "nxdict.h"
- int main(int argc, char *argv[])
- {
- NXdict pDict = NULL;
- NXhandle hfil;
- void *pData = NULL;
- float fTina[3] = { 0.123, 0.234, 0.456};
- float fTest[3], fDelta;
- float fTust[20*20];
- char pBuffer[132];
- int i;
+int main(int argc, char *argv[])
+{
+ NXdict pDict = NULL;
+ NXhandle hfil;
+ void *pData = NULL;
+ float fTina[3] = { 0.123, 0.234, 0.456 };
+ float fTest[3], fDelta;
+ float fTust[20 * 20];
+ char pBuffer[132];
+ int i;
- /* test nxdict */
- NXDinitfromfile("test.dict",&pDict);
- NXopen("test.hdf",NXACC_CREATE,&hfil);
- NXDadd(pDict,"Gundula",
- "/entry1,NXentry/SphereOmeter,NXinstrument/SDS");
- NXDupdate(pDict,"Bea","/entry1,NXentry/SDS");
- NXDget(pDict,"Bea",pBuffer,131);
- printf("Bea = %s\n",pBuffer);
- NXDget(pDict,"Linda",pBuffer,131);
- NXDopendef(hfil,pDict,pBuffer);
- NXDputalias(hfil,pDict,"Tina",fTina);
- NXDputalias(hfil,pDict,"Gina",fTina);
- NXDgetalias(hfil,pDict,"Tina",fTest);
- NXDgetalias(hfil,pDict,"Gina",fTest);
- NXDputalias(hfil,pDict,"Linda",fTust);
- NXDaliaslink(hfil,pDict,"Eva","Linda");
- NXDclose(pDict,"close.dict");
- NXclose(&hfil);
- printf("NXDICT seemed to have worked \n");
+ /* test nxdict */
+ NXDinitfromfile("test.dict", &pDict);
+ NXopen("test.hdf", NXACC_CREATE, &hfil);
+ NXDadd(pDict, "Gundula",
+ "/entry1,NXentry/SphereOmeter,NXinstrument/SDS");
+ NXDupdate(pDict, "Bea", "/entry1,NXentry/SDS");
+ NXDget(pDict, "Bea", pBuffer, 131);
+ printf("Bea = %s\n", pBuffer);
+ NXDget(pDict, "Linda", pBuffer, 131);
+ NXDopendef(hfil, pDict, pBuffer);
+ NXDputalias(hfil, pDict, "Tina", fTina);
+ NXDputalias(hfil, pDict, "Gina", fTina);
+ NXDgetalias(hfil, pDict, "Tina", fTest);
+ NXDgetalias(hfil, pDict, "Gina", fTest);
+ NXDputalias(hfil, pDict, "Linda", fTust);
+ NXDaliaslink(hfil, pDict, "Eva", "Linda");
+ NXDclose(pDict, "close.dict");
+ NXclose(&hfil);
+ printf("NXDICT seemed to have worked \n");
- /* test Utility functions */
- printf(" Proceeding to test of utility functions \n");
- NXopen("test2.hdf",NXACC_CREATE,&hfil);
- NXUwriteglobals(hfil,
- "test2.hdf",
- "Willibald Wuergehals",
- "Rue des Martyrs, 26505 Timbuktu, Legoland ",
- "+41-56-3102512",
- "Nobody@nowhere.edu",
- " 755-898767",
- "Dingsbums");
- NXUentergroup(hfil, "TestGroup", "NXtest");
- NXclosegroup(hfil);
- NXUentergroup(hfil, "TestGroup", "NXtest");
+ /* test Utility functions */
+ printf(" Proceeding to test of utility functions \n");
+ NXopen("test2.hdf", NXACC_CREATE, &hfil);
+ NXUwriteglobals(hfil,
+ "test2.hdf",
+ "Willibald Wuergehals",
+ "Rue des Martyrs, 26505 Timbuktu, Legoland ",
+ "+41-56-3102512",
+ "Nobody@nowhere.edu", " 755-898767", "Dingsbums");
+ NXUentergroup(hfil, "TestGroup", "NXtest");
+ NXclosegroup(hfil);
+ NXUentergroup(hfil, "TestGroup", "NXtest");
- i = 120;
- NXUenterdata(hfil,"TestData",DFNT_INT8, 1,&i,"Testis");
- NXclosedata(hfil);
- NXUenterdata(hfil,"TestData",DFNT_INT8, 1,&i,"Testis");
+ i = 120;
+ NXUenterdata(hfil, "TestData", DFNT_INT8, 1, &i, "Testis");
+ NXclosedata(hfil);
+ NXUenterdata(hfil, "TestData", DFNT_INT8, 1, &i, "Testis");
- NXUallocSDS(hfil,&pData);
- NXUfreeSDS(&pData);
- NXclose(&hfil);
- printf("All tests seem to have worked OK, %s %s\n",
- "but the test is pathetic\n",
- "Do not rely, in any circumstances, on this test alone");
+ NXUallocSDS(hfil, &pData);
+ NXUfreeSDS(&pData);
+ NXclose(&hfil);
+ printf("All tests seem to have worked OK, %s %s\n",
+ "but the test is pathetic\n",
+ "Do not rely, in any circumstances, on this test alone");
-
- }
+
+}
diff --git a/diffscan.c b/diffscan.c
index 32252513..0dd9e54d 100644
--- a/diffscan.c
+++ b/diffscan.c
@@ -15,139 +15,142 @@
#include "drive.h"
#include "counter.h"
-extern double DoubleTime(void);
-
#define DIFFMONITOR 0
#define SKIP 1
/*-------------------------------------------------------------------*/
-static void KillDiffScan(void *data){
- pDiffScan self = (pDiffScan)data;
-
- if(self == NULL){
+static void KillDiffScan(void *data)
+{
+ pDiffScan self = (pDiffScan) data;
+
+ if (self == NULL) {
return;
}
-
- if(self->pDes != NULL){
+
+ if (self->pDes != NULL) {
DeleteDescriptor(self->pDes);
}
- if(self->parArray != NULL){
+ if (self->parArray != NULL) {
ObParDelete(self->parArray);
}
free(self);
}
+
/*---------------------------------------------------------------------*/
-static int SaveDiffScan(void *data, char *name, FILE *fd){
- pDiffScan self = (pDiffScan)data;
- if(self == NULL){
+static int SaveDiffScan(void *data, char *name, FILE * fd)
+{
+ pDiffScan self = (pDiffScan) data;
+ if (self == NULL) {
return 0;
}
- fprintf(fd,"%s monitor %f\n",name,ObVal(self->parArray,DIFFMONITOR));
- fprintf(fd,"%s skip %f\n",name,ObVal(self->parArray,SKIP));
+ fprintf(fd, "%s monitor %f\n", name, ObVal(self->parArray, DIFFMONITOR));
+ fprintf(fd, "%s skip %f\n", name, ObVal(self->parArray, SKIP));
return 1;
}
+
/*----------------------------------------------------------------------*/
-int MakeDiffScan(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]){
+int MakeDiffScan(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
pDiffScan pNew = NULL;
int status;
- pNew = (pDiffScan)malloc(sizeof(DiffScan));
- if(pNew == NULL){
- SCWrite(pCon,"ERROR: out of memory creating differential scan",
- eError);
+ pNew = (pDiffScan) malloc(sizeof(DiffScan));
+ if (pNew == NULL) {
+ SCWrite(pCon, "ERROR: out of memory creating differential scan",
+ eError);
return 0;
}
- memset(pNew,0,sizeof(DiffScan));
+ memset(pNew, 0, sizeof(DiffScan));
pNew->pDes = CreateDescriptor("DiffScan");
pNew->parArray = ObParCreate(2);
- if(!pNew->pDes || !pNew->parArray){
- SCWrite(pCon,"ERROR: out of memory creating differential scan",
- eError);
+ if (!pNew->pDes || !pNew->parArray) {
+ SCWrite(pCon, "ERROR: out of memory creating differential scan",
+ eError);
KillDiffScan(pNew);
return 0;
- }
- ObParInit(pNew->parArray, DIFFMONITOR,"monitor",4.0,usUser);
- ObParInit(pNew->parArray, SKIP,"skip",.0,usUser);
+ }
+ ObParInit(pNew->parArray, DIFFMONITOR, "monitor", 4.0, usUser);
+ ObParInit(pNew->parArray, SKIP, "skip", .0, usUser);
pNew->pDes->SaveStatus = SaveDiffScan;
- if(argc > 1) {
- status = AddCommand(pSics,argv[1],
- DiffScanWrapper,
- KillDiffScan,
- pNew);
-
+ if (argc > 1) {
+ status = AddCommand(pSics, argv[1],
+ DiffScanWrapper, KillDiffScan, pNew);
+
} else {
- status = AddCommand(pSics,"diffscan",
- DiffScanWrapper,
- KillDiffScan,
- pNew);
-
+ status = AddCommand(pSics, "diffscan",
+ DiffScanWrapper, KillDiffScan, pNew);
+
}
- if(status != 1){
- SCWrite(pCon,"ERROR: duplicate diffscan not created",eError);
+ if (status != 1) {
+ SCWrite(pCon, "ERROR: duplicate diffscan not created", eError);
return 0;
}
return 1;
}
+
/*----------------------------------------------------------------------*/
-int DiffScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]){
+int DiffScanWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
pDiffScan self = NULL;
pScanData pScan = NULL;
ObPar *par = NULL;
char pBueffel[255];
int status;
- self = (pDiffScan)pData;
+ self = (pDiffScan) pData;
assert(self);
- if(argc < 2){
- SCWrite(pCon,"ERROR: need arguments to diffscan",eError);
+ if (argc < 2) {
+ SCWrite(pCon, "ERROR: need arguments to diffscan", eError);
return 0;
}
- if(!SCMatchRights(pCon,usUser)){
+ if (!SCMatchRights(pCon, usUser)) {
return 0;
}
/*
- first try to find a scan object and to run
- */
+ first try to find a scan object and to run
+ */
strtolower(argv[1]);
- pScan = (pScanData)FindCommandData(pSics,argv[1],"ScanObject");
- if(pScan != NULL && argc > 2){
- status = RunDiffScan(self,pScan,pCon, atof(argv[2]));
+ pScan = (pScanData) FindCommandData(pSics, argv[1], "ScanObject");
+ if (pScan != NULL && argc > 2) {
+ status = RunDiffScan(self, pScan, pCon, atof(argv[2]));
return status;
}
/*
- if we end here we are treating variables
- */
- if(argc > 2){
+ if we end here we are treating variables
+ */
+ if (argc > 2) {
/*
- set case
- */
- return ObParSet(self->parArray,argv[0],argv[1],atof(argv[2]),pCon);
+ set case
+ */
+ return ObParSet(self->parArray, argv[0], argv[1], atof(argv[2]), pCon);
} else {
/*
- get case
- */
- par = ObParFind(self->parArray,argv[1]);
- if(par != NULL){
- snprintf(pBueffel,255,"%s.%s = %f",argv[0],argv[1],par->fVal);
- SCWrite(pCon,pBueffel,eValue);
+ get case
+ */
+ par = ObParFind(self->parArray, argv[1]);
+ if (par != NULL) {
+ snprintf(pBueffel, 255, "%s.%s = %f", argv[0], argv[1], par->fVal);
+ SCWrite(pCon, pBueffel, eValue);
return 1;
} else {
- snprintf(pBueffel,255,"ERROR: parameter %s not found",argv[1]);
- SCWrite(pCon,pBueffel,eError);
+ snprintf(pBueffel, 255, "ERROR: parameter %s not found", argv[1]);
+ SCWrite(pCon, pBueffel, eError);
return 0;
}
}
return 1;
}
+
/*--------------------------------------------------------------------*/
-static int StartDiffScan(pDiffScan self, pScanData pScan,
- SConnection *pCon, float fEnd){
+static int StartDiffScan(pDiffScan self, pScanData pScan,
+ SConnection * pCon, float fEnd)
+{
pVarEntry pVar = NULL;
void *pPtr = NULL;
pCounter pCount = NULL;
@@ -155,105 +158,110 @@ static int StartDiffScan(pDiffScan self, pScanData pScan,
int status;
/*
- error checks
- */
- if(pScan->iScanVar < 1) {
- SCWrite(pCon,"ERROR: no scan variable to diffscan",eError);
+ error checks
+ */
+ if (pScan->iScanVar < 1) {
+ SCWrite(pCon, "ERROR: no scan variable to diffscan", eError);
return 0;
}
- if(pScan->iScanVar > 1) {
- snprintf(pBueffel,255,
- "WARNING: diffscan handles only first scan variable, %d %s",
- pScan->iScanVar - 1,
- "scan variables ignored");
- SCWrite(pCon,pBueffel, eWarning);
+ if (pScan->iScanVar > 1) {
+ snprintf(pBueffel, 255,
+ "WARNING: diffscan handles only first scan variable, %d %s",
+ pScan->iScanVar - 1, "scan variables ignored");
+ SCWrite(pCon, pBueffel, eWarning);
}
/*
- initialize data structure
- */
+ initialize data structure
+ */
self->scanObject = pScan;
self->scanObject->pCon = pCon;
- self->skip = (int)ObVal(self->parArray,SKIP);
- self->scaleMonitor = (int)ObVal(self->parArray,DIFFMONITOR);
+ self->skip = (int) ObVal(self->parArray, SKIP);
+ self->scaleMonitor = (int) ObVal(self->parArray, DIFFMONITOR);
self->normalizationScale = -1;
pScan->iCounts = 0;
- pScan->iNP = 0;
-
- /*
- get variable
- */
- DynarGet(pScan->pScanVar,0,&pPtr);
- pVar = (pVarEntry)pPtr;
- if(pVar == NULL){
- SCWrite(pCon,"ERROR: cannot access scan variable",eError);
- return 0;
- }
- InitScanVar(pVar);
/*
- drive to start position
- */
- status = Drive(pCon,pServ->pSics,ScanVarName(pVar),ScanVarStart(pVar));
- if(status != 1){
+ get variable
+ */
+ DynarGet(pScan->pScanVar, 0, &pPtr);
+ pVar = (pVarEntry) pPtr;
+ if (pVar == NULL) {
+ SCWrite(pCon, "ERROR: cannot access scan variable", eError);
return 0;
}
/*
- Configure counter. We operate in timer mode with a very long
- preset mode. Stopping is done explicitly in the diffscan task
- */
- SetCounterMode(pScan->pCounterData,eTimer);
- SetCounterPreset(pScan->pCounterData,3600.);
+ drive to start position
+ */
+ status =
+ Drive(pCon, pServ->pSics, ScanVarName(pVar), ScanVarStart(pVar));
+ if (status != 1) {
+ return 0;
+ }
/*
- start motor and counter
- */
- status = pVar->pInter->SetValue(pVar->pObject,pCon,fEnd);
- if(status != OKOK){
+ Configure counter. We operate in timer mode with a very long
+ preset mode. Stopping is done explicitly in the diffscan task
+ */
+ SetCounterMode(pScan->pCounterData, eTimer);
+ SetCounterPreset(pScan->pCounterData, 3600.);
+
+ /*
+ start motor and counter
+ */
+ status = pVar->pInter->SetValue(pVar->pObject, pCon, fEnd);
+ if (status != OKOK) {
/*
- errors will already have been reported in SetValue
- */
+ errors will already have been reported in SetValue
+ */
return 0;
}
- pCount = (pCounter)pScan->pCounterData;
+ pCount = (pCounter) pScan->pCounterData;
assert(pCount);
- status = pCount->pCountInt->StartCount(pCount,pCon);
- if(status != OKOK){
+ status = pCount->pCountInt->StartCount(pCount, pCon);
+ if (status != OKOK) {
return 0;
}
return 1;
}
+
/*--------------------------------------------------------------------*/
-static float normalizeEntry(pCountEntry pCount, pCountEntry last,
- long monValue, int scaleMon){
+static float normalizeEntry(pCountEntry pCount, pCountEntry last,
+ long monValue, int scaleMon)
+{
int i;
float fScale;
float value;
long diff;
/*
- calculate scale
- */
- diff = pCount->Monitors[scaleMon-1] - last->Monitors[scaleMon-1];
- if(diff > 0) {
- fScale = (float)monValue/(float)diff;
+ calculate scale
+ */
+ diff = pCount->Monitors[scaleMon - 1] - last->Monitors[scaleMon - 1];
+ if (diff > 0) {
+ fScale = (float) monValue / (float) diff;
} else {
fScale = 0.;
}
- value = ((float)(pCount->lCount - last->lCount))*fScale;
- pCount->lCount = (long)value;
- for(i = 0; i < 10; i++){
- pCount->Monitors[i] = (pCount->Monitors[i] - last->Monitors[i])*fScale;
+ value = ((float) (pCount->lCount - last->lCount)) * fScale;
+ pCount->lCount = (long) value;
+ for (i = 0; i < 10; i++) {
+ pCount->Monitors[i] =
+ (pCount->Monitors[i] - last->Monitors[i]) * fScale;
}
return value;
}
+
/*--------------------------------------------------------------------*/
-static void copyCountData(pCountEntry last, pCountEntry pCount){
- memcpy(last,pCount,sizeof(CountEntry));
+static void copyCountData(pCountEntry last, pCountEntry pCount)
+{
+ memcpy(last, pCount, sizeof(CountEntry));
}
+
/*---------------------------------------------------------------------*/
-static int DiffScanTask(void *pData){
+static int DiffScanTask(void *pData)
+{
pCounter pCount = NULL;
pCountEntry data;
pVarEntry pVar = NULL;
@@ -263,127 +271,130 @@ static int DiffScanTask(void *pData){
char pBueffel[255];
long rawCount, rawMon;
CountEntry rawCopy;
- double now;
- pDiffScan self = (pDiffScan)pData;
+ pDiffScan self = (pDiffScan) pData;
/*
- manage skip
- */
-#if 1
- now = DoubleTime();
- if(self->skip > 0) {
- if (now - self->last_report_time < 0.001 * self->skip) {
- return 1;
- }
- }
- else {
- if (now - self->last_report_time < 0.1) {
- return 1;
- }
- }
- self->last_report_time = now;
-#else
- if(self->skip > 0){
- if(self->skipCount > self->skip){
+ manage skip
+ */
+ if (self->skip > 0) {
+ if (self->skipCount > self->skip) {
self->skipCount = 0;
} else {
self->skipCount++;
return 1;
}
}
-#endif
/*
- read motor status
- */
- DynarGet(self->scanObject->pScanVar,0,&pPtr);
- pVar = (pVarEntry)pPtr;
- status = pVar->pInter->CheckStatus(pVar->pObject,self->scanObject->pCon);
- if(status != HWBusy) {
+ read motor status
+ */
+ DynarGet(self->scanObject->pScanVar, 0, &pPtr);
+ pVar = (pVarEntry) pPtr;
+ status =
+ pVar->pInter->CheckStatus(pVar->pObject, self->scanObject->pCon);
+ if (status != HWBusy) {
finish = 0;
}
/*
- read values
- */
- status = GetDrivablePosition(pVar->pObject,self->scanObject->pCon,
- &fPos);
- if(status == 0){
+ read values
+ */
+ status = GetDrivablePosition(pVar->pObject, self->scanObject->pCon,
+ &fPos);
+ if (status == 0) {
+ ReleaseCountLock(pCount->pCountInt);
return finish;
}
- AppendScanVar(pVar,fPos);
- pCount = (pCounter)self->scanObject->pCounterData;
- pCount->pCountInt->TransferData(pCount,self->scanObject->pCon);
+ AppendScanVar(pVar, fPos);
+ pCount = (pCounter) self->scanObject->pCounterData;
+ pCount->pCountInt->TransferData(pCount, self->scanObject->pCon);
CollectCounterData(self->scanObject);
/*
- normalize (or not)
- */
- DynarGet(self->scanObject->pCounts,self->scanObject->iCounts-1,&pPtr);
- data = (pCountEntry)pPtr;
- copyCountData(&rawCopy,data);
- if(self->normalizationScale < 0){
- countValue = (float)data->lCount;
+ normalize (or not)
+ */
+ DynarGet(self->scanObject->pCounts, self->scanObject->iCounts - 1,
+ &pPtr);
+ data = (pCountEntry) pPtr;
+ copyCountData(&rawCopy, data);
+ if (self->normalizationScale < 0) {
+ countValue = (float) data->lCount;
rawCount = data->lCount;
- rawMon = data->Monitors[self->scaleMonitor-1];
- self->normalizationScale = data->Monitors[self->scaleMonitor-1];
+ rawMon = data->Monitors[self->scaleMonitor - 1];
+ if(rawMon > 100){
+ self->normalizationScale = rawMon;
+ traceSys("diffscan","START:normalizing on %d, scale monitor is %d",
+ self->normalizationScale, self->scaleMonitor);
+ } else {
+ traceSys("diffscan","START:normalization count %d, on scale monitor is %d and is to low",
+ rawMon, self->scaleMonitor);
+ SCWrite(self->scanObject->pCon,"WARNING: Skipping first point because of low count rate", eWarning);
+ return finish;
+ }
} else {
- if(data->Monitors[self->scaleMonitor -1] -
- self->last.Monitors[self->scaleMonitor-1] < 5) {
- SCWrite(self->scanObject->pCon,
- "WARNING: low count rate",eWarning);
+ if (data->Monitors[self->scaleMonitor - 1] -
+ self->last.Monitors[self->scaleMonitor - 1] < 5) {
+ SCWrite(self->scanObject->pCon, "WARNING: low count rate", eLog);
+ traceSys("diffscan","RUN:low monitor difference from %d to %d",data->Monitors[self->scaleMonitor-1],
+ self->last.Monitors[self->scaleMonitor -1]);
}
rawCount = data->lCount;
- rawMon = data->Monitors[self->scaleMonitor-1];
- countValue = normalizeEntry(data,&self->last,
- self->normalizationScale,
- self->scaleMonitor);
+ rawMon = data->Monitors[self->scaleMonitor - 1];
+ countValue = normalizeEntry(data, &self->last,
+ self->normalizationScale,
+ self->scaleMonitor);
}
- copyCountData(&self->last,&rawCopy);
+ copyCountData(&self->last, &rawCopy);
/*
- print progress
- */
- snprintf(pBueffel,255,"%5d %12.4f %12.4f RAW: %10ld %10ld",
- self->scanObject->iCounts -1,
- fPos, countValue, rawCount,
- rawMon);
- SCWrite(self->scanObject->pCon,pBueffel,eWarning);
- InvokeCallBack(self->scanObject->pCall,SCANPOINT,self->scanObject);
+ print progress
+ */
+ snprintf(pBueffel, 255, "%5d %12.4f %12.4f RAW: %10ld %10ld",
+ self->scanObject->iCounts - 1,
+ fPos, countValue, rawCount, rawMon);
+ SCWrite(self->scanObject->pCon, pBueffel, eLog);
+ InvokeCallBack(self->scanObject->pCall, SCANPOINT, self->scanObject);
+ traceSys("diffscan","RUN: pos, count, rawcount, rawmon: %f, %d, %d, %d",
+ fPos, countValue, rawCount, rawMon);
/*
- check for interrupt
- */
- if(SCGetInterrupt(self->scanObject->pCon) >= eAbortScan){
+ check for interrupt
+ */
+ if (SCGetInterrupt(self->scanObject->pCon) >= eAbortScan) {
pCount->pCountInt->Halt(pCount);
pVar->pInter->Halt(pVar->pObject);
SicsWait(1);
finish = 0;
}
+ if(finish == 0) {
+ ReleaseCountLock(pCount->pCountInt);
+ }
+
return finish;
}
+
/*----------------------------------------------------------------------*/
-int RunDiffScan(pDiffScan self, pScanData pScan,
- SConnection *pCon, float fEnd){
+int RunDiffScan(pDiffScan self, pScanData pScan,
+ SConnection * pCon, float fEnd)
+{
long lID;
pCounter pCount = NULL;
-
- if(StartDiffScan(self,pScan,pCon,fEnd) != 1) {
+
+ if (StartDiffScan(self, pScan, pCon, fEnd) != 1) {
return 0;
}
- self->last_report_time = DoubleTime();
- InvokeCallBack(self->scanObject->pCall,SCANSTART,self->scanObject);
+ InvokeCallBack(self->scanObject->pCall, SCANSTART, self->scanObject);
-
- lID = TaskRegister(pServ->pTasker,DiffScanTask,NULL,NULL,self,10);
- TaskWait(pServ->pTasker,lID);
-
- pCount = (pCounter)self->scanObject->pCounterData;
+ lID = TaskRegister(pServ->pTasker, DiffScanTask, NULL, NULL, self, 10);
+ TaskWait(pServ->pTasker, lID);
+
+
+ pCount = (pCounter) self->scanObject->pCounterData;
pCount->pCountInt->Halt(pCount);
- InvokeCallBack(self->scanObject->pCall,SCANEND,self->scanObject);
-
+ InvokeCallBack(self->scanObject->pCall, SCANEND, self->scanObject);
+
return 1;
}
diff --git a/diffscan.h b/diffscan.h
index 847ed3cf..75adce42 100644
--- a/diffscan.h
+++ b/diffscan.h
@@ -14,17 +14,16 @@
#include "scan.i"
typedef struct {
- pObjectDescriptor pDes;
- ObPar *parArray;
- int normalizationScale;
- int scaleMonitor;
- CountEntry last;
- int skip;
- int skipCount;
- pScanData scanObject;
- double last_report_time;
- } DiffScan, *pDiffScan;
-
+ pObjectDescriptor pDes;
+ ObPar *parArray;
+ int normalizationScale;
+ int scaleMonitor;
+ CountEntry last;
+ int skip;
+ int skipCount;
+ pScanData scanObject;
+} DiffScan, *pDiffScan;
+
/*==================================================================*/
/**
@@ -35,14 +34,14 @@ typedef struct {
* @param pCon The connection to use for output and errors.
* @param fEnd The end value for the diffscan
*/
- int RunDiffScan(pDiffScan self, pScanData pScan,
- SConnection *pCon, float fEnd);
+int RunDiffScan(pDiffScan self, pScanData pScan,
+ SConnection * pCon, float fEnd);
/*==================== interpreter wrappers ==========================*/
- int DiffScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
- int MakeDiffScan(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int DiffScanWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+int MakeDiffScan(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
+
-
#endif
diff --git a/difrac.c b/difrac.c
index 4f09755a..8b3213fd 100644
--- a/difrac.c
+++ b/difrac.c
@@ -31,8 +31,8 @@
---------------------------------------------------------------------------*/
#define MAXSTACK 50
- static SConnection *ConStack[MAXSTACK];
- static int iConStackPtr = -1;
+static SConnection *ConStack[MAXSTACK];
+static int iConStackPtr = -1;
/*--------------------------------------------------------------------------
In order to do the four circle work we need to know the motors of the
@@ -41,358 +41,322 @@
These data structures are initialized by the installation routine.
---------------------------------------------------------------------------*/
- static pMotor pTTH, pOM, pCHI, pPHI;
- static pCounter counter;
+static pMotor pTTH, pOM, pCHI, pPHI;
+static pCounter counter;
/*---------------------------------------------------------------------------
The following routines will be called from F77. Their names take care of the
system dependent name mangling scheme for calling C from F77. This may
need adjustment when porting to another system
---------------------------------------------------------------------------*/
/*========= read angles */
- void sicsanget_(float *fTH, float *fOM, float *fCHI, float *fPHI)
- {
- int iRet;
+void sicsanget_(float *fTH, float *fOM, float *fCHI, float *fPHI)
+{
+ int iRet;
- /* this is just security, may never happen */
- if(iConStackPtr < 0)
- {
- return;
- }
- if(ConStack[iConStackPtr] == NULL)
- {
- return;
- }
-
- iRet = MotorGetSoftPosition(pTTH,ConStack[iConStackPtr],fTH);
- if(iRet != 1)
- {
- SCWrite(ConStack[iConStackPtr],
- "ERROR: failed to read two theta, DIFRAC may be confused now",
- eError);
- }
- iRet = MotorGetSoftPosition(pOM,ConStack[iConStackPtr],fOM);
- if(iRet != 1)
- {
- SCWrite(ConStack[iConStackPtr],
- "ERROR: failed to read omega, DIFRAC may be confused now",
- eError);
- }
- iRet = MotorGetSoftPosition(pCHI,ConStack[iConStackPtr],fCHI);
- if(iRet != 1)
- {
- SCWrite(ConStack[iConStackPtr],
- "ERROR: failed to read chi, DIFRAC may be confused now",
- eError);
- }
- iRet = MotorGetSoftPosition(pPHI,ConStack[iConStackPtr],fPHI);
- if(iRet != 1)
- {
- SCWrite(ConStack[iConStackPtr],
- "ERROR: failed to read two theta, DIFRAC may be confused now",
- eError);
- }
+ /* this is just security, may never happen */
+ if (iConStackPtr < 0) {
+ return;
}
-#define ABS(x) (x < 0 ? -(x) : (x))
+ if (ConStack[iConStackPtr] == NULL) {
+ return;
+ }
+
+ iRet = MotorGetSoftPosition(pTTH, ConStack[iConStackPtr], fTH);
+ if (iRet != 1) {
+ SCWrite(ConStack[iConStackPtr],
+ "ERROR: failed to read two theta, DIFRAC may be confused now",
+ eError);
+ }
+ iRet = MotorGetSoftPosition(pOM, ConStack[iConStackPtr], fOM);
+ if (iRet != 1) {
+ SCWrite(ConStack[iConStackPtr],
+ "ERROR: failed to read omega, DIFRAC may be confused now",
+ eError);
+ }
+ iRet = MotorGetSoftPosition(pCHI, ConStack[iConStackPtr], fCHI);
+ if (iRet != 1) {
+ SCWrite(ConStack[iConStackPtr],
+ "ERROR: failed to read chi, DIFRAC may be confused now",
+ eError);
+ }
+ iRet = MotorGetSoftPosition(pPHI, ConStack[iConStackPtr], fPHI);
+ if (iRet != 1) {
+ SCWrite(ConStack[iConStackPtr],
+ "ERROR: failed to read two theta, DIFRAC may be confused now",
+ eError);
+ }
+}
+
+#define ABS(x) (x < 0 ? -(x) : (x))
/*=========== check angles */
- void sicsangcheck_(float *fTH, float *fOM, float *fCHI, float *fPHI,
- int *iInvalid)
- {
- int iRet;
- SConnection *pCon = NULL;
- float fHard;
- char pBueffel[256], pError[131];
+void sicsangcheck_(float *fTH, float *fOM, float *fCHI, float *fPHI,
+ int *iInvalid)
+{
+ int iRet;
+ SConnection *pCon = NULL;
+ float fHard;
+ char pBueffel[256], pError[131];
- /* this is just security, may never happen */
- if(iConStackPtr < 0)
- {
- return;
- }
- if(ConStack[iConStackPtr] == NULL)
- {
- return;
- }
- pCon = ConStack[iConStackPtr];
-
- *iInvalid = 0;
- iRet = MotorCheckBoundary(pTTH,*fTH,&fHard,pError,131);
- if(iRet != 1)
- {
- sprintf(pBueffel,
- "ERROR: %6.2f %6.2f %6.2f %6.2f violates twotheta limits",
- *fTH, *fOM, *fCHI, *fPHI);
- SCWrite(pCon,pBueffel,eError);
- *iInvalid = 4;
- return;
- }
- iRet = MotorCheckBoundary(pOM,*fOM,&fHard,pError,131);
- if(iRet != 1)
- {
- sprintf(pBueffel,
- "ERROR: %6.2f %6.2f %6.2f %6.2f violates omega limits",
- *fTH, *fOM, *fCHI, *fPHI);
- SCWrite(pCon,pBueffel,eError);
- *iInvalid = 4;
- return;
- }
- iRet = MotorCheckBoundary(pCHI,*fCHI,&fHard,pError,131);
- if(iRet != 1)
- {
- sprintf(pBueffel,
- "ERROR: %6.2f %6.2f %6.2f %6.2f violates chi limits",
- *fTH, *fOM, *fCHI, *fPHI);
- SCWrite(pCon,pBueffel,eError);
- *iInvalid = 4;
- return;
- }
- iRet = MotorCheckBoundary(pPHI,*fPHI,&fHard,pError,131);
- if(iRet != 1)
- {
- sprintf(pBueffel,
- "ERROR: %6.2f %6.2f %6.2f %6.2f violates phi limits",
- *fTH, *fOM, *fCHI, *fPHI);
- SCWrite(pCon,pBueffel,eError);
- *iInvalid = 4;
- return;
- }
+ /* this is just security, may never happen */
+ if (iConStackPtr < 0) {
+ return;
}
+ if (ConStack[iConStackPtr] == NULL) {
+ return;
+ }
+ pCon = ConStack[iConStackPtr];
+
+ *iInvalid = 0;
+ iRet = MotorCheckBoundary(pTTH, *fTH, &fHard, pError, 131);
+ if (iRet != 1) {
+ sprintf(pBueffel,
+ "ERROR: %6.2f %6.2f %6.2f %6.2f violates twotheta limits",
+ *fTH, *fOM, *fCHI, *fPHI);
+ SCWrite(pCon, pBueffel, eError);
+ *iInvalid = 4;
+ return;
+ }
+ iRet = MotorCheckBoundary(pOM, *fOM, &fHard, pError, 131);
+ if (iRet != 1) {
+ sprintf(pBueffel,
+ "ERROR: %6.2f %6.2f %6.2f %6.2f violates omega limits",
+ *fTH, *fOM, *fCHI, *fPHI);
+ SCWrite(pCon, pBueffel, eError);
+ *iInvalid = 4;
+ return;
+ }
+ iRet = MotorCheckBoundary(pCHI, *fCHI, &fHard, pError, 131);
+ if (iRet != 1) {
+ sprintf(pBueffel,
+ "ERROR: %6.2f %6.2f %6.2f %6.2f violates chi limits",
+ *fTH, *fOM, *fCHI, *fPHI);
+ SCWrite(pCon, pBueffel, eError);
+ *iInvalid = 4;
+ return;
+ }
+ iRet = MotorCheckBoundary(pPHI, *fPHI, &fHard, pError, 131);
+ if (iRet != 1) {
+ sprintf(pBueffel,
+ "ERROR: %6.2f %6.2f %6.2f %6.2f violates phi limits",
+ *fTH, *fOM, *fCHI, *fPHI);
+ SCWrite(pCon, pBueffel, eError);
+ *iInvalid = 4;
+ return;
+ }
+}
+
/*======== set angles */
- void sicsangset_(float *fTTH, float *fOM, float *fCHI, float *fPHI,
- int *icol)
- {
- pDummy pDum;
- int iRet;
- SConnection *pCon = NULL;
- float fT1, fT2, fT3, fT4;
+void sicsangset_(float *fTTH, float *fOM, float *fCHI, float *fPHI,
+ int *icol)
+{
+ pDummy pDum;
+ int iRet;
+ SConnection *pCon = NULL;
+ float fT1, fT2, fT3, fT4;
- *icol = 0;
+ *icol = 0;
- /* this is just security, may never happen */
- if(iConStackPtr < 0)
- {
- return;
- }
- if(ConStack[iConStackPtr] == NULL)
- {
- return;
- }
- pCon = ConStack[iConStackPtr];
-
-
- /* check if this is possible, if not complain */
- sicsangcheck_(fTTH, fOM,fCHI,fPHI, &iRet);
- if(iRet >= 4)
- {
- *icol = 1;
- return;
- }
-
- /* start */
- pDum = (pDummy)pTTH;
- iRet = StartDevice(pServ->pExecutor, "TTH",
- pDum->pDescriptor, pDum,pCon, *fTTH);
- if(!iRet)
- {
- SCWrite(pCon,"ERROR: cannot start two theta motor",eError);
- StopExe(pServ->pExecutor,"all");
- *icol = 10;
- }
- pDum = (pDummy)pOM;
- iRet = StartDevice(pServ->pExecutor, "OM",
- pDum->pDescriptor, pDum,pCon, *fOM);
- if(!iRet)
- {
- SCWrite(pCon,"ERROR: cannot start omega motor",eError);
- StopExe(pServ->pExecutor,"all");
- *icol = 10;
- }
- pDum = (pDummy)pCHI;
- iRet = StartDevice(pServ->pExecutor, "CHI",
- pDum->pDescriptor, pDum,pCon, *fCHI);
- if(!iRet)
- {
- SCWrite(pCon,"ERROR: cannot start chi motor",eError);
- StopExe(pServ->pExecutor,"all");
- *icol = 10;
- }
- pDum = (pDummy)pPHI;
- iRet = StartDevice(pServ->pExecutor, "PHI",
- pDum->pDescriptor, pDum,pCon, *fPHI);
- if(!iRet)
- {
- SCWrite(pCon,"ERROR: cannot start two theta motor",eError);
- StopExe(pServ->pExecutor,"all");
- *icol = 10;
- }
-
- /* wait for end of it */
- iRet = Wait4Success(pServ->pExecutor);
- switch(iRet)
- {
- case DEVINT:
- if(SCGetInterrupt(pCon) == eAbortOperation)
- {
- SCSetInterrupt(pCon,eContinue);
- SCSetError(pCon,OKOK);
- }
- break;
- case DEVDONE:
- break;
- default:
- break;
- }
-
- /*
- As TRICS has such a shitty cradle check angles and report error
- if bad
- */
- sicsanget_(&fT1, &fT2, &fT3, &fT4);
- if(ABS(fT1 - *fTTH) > .2)
- {
- *icol = 10;
- }
- if(ABS(fT2 - *fOM) > .2)
- {
- *icol = 10;
- }
- if(ABS(fT3 - *fCHI) > .2)
- {
- *icol = 10;
- }
- if(ABS(fT4 - *fPHI) > .2)
- {
- *icol = 10;
- }
+ /* this is just security, may never happen */
+ if (iConStackPtr < 0) {
+ return;
}
+ if (ConStack[iConStackPtr] == NULL) {
+ return;
+ }
+ pCon = ConStack[iConStackPtr];
+
+
+ /* check if this is possible, if not complain */
+ sicsangcheck_(fTTH, fOM, fCHI, fPHI, &iRet);
+ if (iRet >= 4) {
+ *icol = 1;
+ return;
+ }
+
+ /* start */
+ pDum = (pDummy) pTTH;
+ iRet = StartDevice(pServ->pExecutor, "TTH",
+ pDum->pDescriptor, pDum, pCon, *fTTH);
+ if (!iRet) {
+ SCWrite(pCon, "ERROR: cannot start two theta motor", eError);
+ StopExe(pServ->pExecutor, "all");
+ *icol = 10;
+ }
+ pDum = (pDummy) pOM;
+ iRet = StartDevice(pServ->pExecutor, "OM",
+ pDum->pDescriptor, pDum, pCon, *fOM);
+ if (!iRet) {
+ SCWrite(pCon, "ERROR: cannot start omega motor", eError);
+ StopExe(pServ->pExecutor, "all");
+ *icol = 10;
+ }
+ pDum = (pDummy) pCHI;
+ iRet = StartDevice(pServ->pExecutor, "CHI",
+ pDum->pDescriptor, pDum, pCon, *fCHI);
+ if (!iRet) {
+ SCWrite(pCon, "ERROR: cannot start chi motor", eError);
+ StopExe(pServ->pExecutor, "all");
+ *icol = 10;
+ }
+ pDum = (pDummy) pPHI;
+ iRet = StartDevice(pServ->pExecutor, "PHI",
+ pDum->pDescriptor, pDum, pCon, *fPHI);
+ if (!iRet) {
+ SCWrite(pCon, "ERROR: cannot start two theta motor", eError);
+ StopExe(pServ->pExecutor, "all");
+ *icol = 10;
+ }
+
+ /* wait for end of it */
+ iRet = Wait4Success(pServ->pExecutor);
+ switch (iRet) {
+ case DEVINT:
+ if (SCGetInterrupt(pCon) == eAbortOperation) {
+ SCSetInterrupt(pCon, eContinue);
+ SCSetError(pCon, OKOK);
+ }
+ break;
+ case DEVDONE:
+ break;
+ default:
+ break;
+ }
+
+ /*
+ As TRICS has such a shitty cradle check angles and report error
+ if bad
+ */
+ sicsanget_(&fT1, &fT2, &fT3, &fT4);
+ if (ABS(fT1 - *fTTH) > .2) {
+ *icol = 10;
+ }
+ if (ABS(fT2 - *fOM) > .2) {
+ *icol = 10;
+ }
+ if (ABS(fT3 - *fCHI) > .2) {
+ *icol = 10;
+ }
+ if (ABS(fT4 - *fPHI) > .2) {
+ *icol = 10;
+ }
+}
+
/*=========== count */
- void sicscount_(float *fPreset, float *fCounts)
- {
- pDummy pDum;
- int iRet;
- SConnection *pCon = NULL;
- long lTask;
+void sicscount_(float *fPreset, float *fCounts)
+{
+ pDummy pDum;
+ int iRet;
+ SConnection *pCon = NULL;
+ long lTask;
- /* this is just security, may never happen */
- if(iConStackPtr < 0)
- {
- return;
- }
- if(ConStack[iConStackPtr] == NULL)
- {
- return;
- }
- pCon = ConStack[iConStackPtr];
-
- pDum = (pDummy)counter;
- SetCounterPreset(counter,*fPreset);
- iRet = StartDevice(pServ->pExecutor,
- "DifracCount",
- pDum->pDescriptor,
- counter,
- pCon,
- *fPreset);
- if(!iRet)
- {
- SCWrite(pCon,"ERROR: Failed to start counting ",eError);
- return;
- }
- SetStatus(eCounting);
- /* wait for finish */
- lTask = GetDevexecID(pServ->pExecutor);
- if(lTask > 0);
- {
- TaskWait(pServ->pTasker,lTask);
- }
- *fCounts = (float)GetCounts(counter,pCon);
+ /* this is just security, may never happen */
+ if (iConStackPtr < 0) {
+ return;
}
+ if (ConStack[iConStackPtr] == NULL) {
+ return;
+ }
+ pCon = ConStack[iConStackPtr];
+
+ pDum = (pDummy) counter;
+ SetCounterPreset(counter, *fPreset);
+ iRet = StartDevice(pServ->pExecutor,
+ "DifracCount",
+ pDum->pDescriptor, counter, pCon, *fPreset);
+ if (!iRet) {
+ SCWrite(pCon, "ERROR: Failed to start counting ", eError);
+ return;
+ }
+ SetStatus(eCounting);
+ /* wait for finish */
+ lTask = GetDevexecID(pServ->pExecutor);
+ if (lTask > 0);
+ {
+ TaskWait(pServ->pTasker, lTask);
+ }
+ *fCounts = (float) GetCounts(counter, pCon);
+}
+
/*========= sicswrite */
- void sicswrite_(int *iText, int *iLen)
- {
- SConnection *pCon = NULL;
- char pBueffel[256];
- int i;
+void sicswrite_(int *iText, int *iLen)
+{
+ SConnection *pCon = NULL;
+ char pBueffel[256];
+ int i;
- if(*iLen > 255)
- return;
+ if (*iLen > 255)
+ return;
- for(i = 0; i < *iLen; i++)
- {
- pBueffel[i] = (char)iText[i];
- }
- pBueffel[i] = '\0';
-
- /* this is just security, may never happen */
- if(iConStackPtr < 0)
- {
- puts(pBueffel);
- return;
- }
- if(ConStack[iConStackPtr] == NULL)
- {
- puts(pBueffel);
- return;
- }
- pCon = ConStack[iConStackPtr];
-
- SCWrite(pCon,pBueffel,eValue);
+ for (i = 0; i < *iLen; i++) {
+ pBueffel[i] = (char) iText[i];
}
+ pBueffel[i] = '\0';
+
+ /* this is just security, may never happen */
+ if (iConStackPtr < 0) {
+ puts(pBueffel);
+ return;
+ }
+ if (ConStack[iConStackPtr] == NULL) {
+ puts(pBueffel);
+ return;
+ }
+ pCon = ConStack[iConStackPtr];
+
+ SCWrite(pCon, pBueffel, eValue);
+}
+
/*========== sicsgetline */
- void sicsgetline_(int *iText, int *iLen)
- {
- SConnection *pCon = NULL;
- char pBueffel[256];
- int i, iRet;
+void sicsgetline_(int *iText, int *iLen)
+{
+ SConnection *pCon = NULL;
+ char pBueffel[256];
+ int i, iRet;
- /* this is just security, may never happen */
- if(iConStackPtr < 0)
- {
- return;
- }
- if(ConStack[iConStackPtr] == NULL)
- {
- return;
- }
- pCon = ConStack[iConStackPtr];
-
- iRet = SCPrompt(pCon,"Enter data please >>" , pBueffel, 255);
- /* difrac cannot handle an interrupted input operation */
- if(iRet == 0)
- {
- SCSetInterrupt(pCon,eContinue);
- }
- for(i = 0; i < strlen(pBueffel); i++)
- {
- iText[i] = (int)pBueffel[i];
- }
- *iLen = strlen(pBueffel);
+ /* this is just security, may never happen */
+ if (iConStackPtr < 0) {
+ return;
}
+ if (ConStack[iConStackPtr] == NULL) {
+ return;
+ }
+ pCon = ConStack[iConStackPtr];
+
+ iRet = SCPrompt(pCon, "Enter data please >>", pBueffel, 255);
+ /* difrac cannot handle an interrupted input operation */
+ if (iRet == 0) {
+ SCSetInterrupt(pCon, eContinue);
+ }
+ for (i = 0; i < strlen(pBueffel); i++) {
+ iText[i] = (int) pBueffel[i];
+ }
+ *iLen = strlen(pBueffel);
+}
+
/*============= checkint */
- void checkint_(int *iK)
- {
- SConnection *pCon = NULL;
- char pBueffel[256];
- int i;
+void checkint_(int *iK)
+{
+ SConnection *pCon = NULL;
+ char pBueffel[256];
+ int i;
- /* this is just security, may never happen */
- if(iConStackPtr < 0)
- {
- *iK = 0;
- return;
- }
- if(ConStack[iConStackPtr] == NULL)
- {
- return;
- }
- pCon = ConStack[iConStackPtr];
-
- if(SCGetInterrupt(pCon) >= eAbortScan)
- {
- *iK = 0;
- }
- else
- {
- *iK = 1;
- }
+ /* this is just security, may never happen */
+ if (iConStackPtr < 0) {
+ *iK = 0;
+ return;
}
+ if (ConStack[iConStackPtr] == NULL) {
+ return;
+ }
+ pCon = ConStack[iConStackPtr];
+
+ if (SCGetInterrupt(pCon) >= eAbortScan) {
+ *iK = 0;
+ } else {
+ *iK = 1;
+ }
+}
+
/*--------------------------------------------------------------------------
DifracAction is the interface routine between the SICS interpreter and
the DIFRAC subsystem. What it basically does is: pop the connection onto
@@ -402,138 +366,116 @@
-------------------------------------------------------------------------*/
/* some protoypes for things defined in F77 */
- extern void difini_(void);
- extern void difint_(int *iText, int *iLen);
+extern void difini_(void);
+extern void difint_(int *iText, int *iLen);
- int DifracAction(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[])
- {
- char pInput[256];
- int iInput[256];
- int iLen, i;
-
-
- if(argc < 2)
- {
- SCWrite(pCon,"ERROR: dif expects at least one argument",eError);
- return 0;
- }
-
- /* user privilege required */
- if(!SCMatchRights(pCon,usUser))
- {
- return 0;
- }
-
- /* steal: redirect the I/O to me */
- strcpy(pInput,argv[1]);
- strtolower(pInput);
- if(strcmp(pInput,"steal") == 0)
- {
- if(iConStackPtr >= 0)
- {
- ConStack[iConStackPtr] = pCon;
- }
- SCSendOK(pCon);
- return 1;
- }
-
- iConStackPtr++;
- ConStack[iConStackPtr] = pCon;
-
- Arg2Text(argc-1, &argv[1],pInput,255);
- iLen = strlen(pInput);
- for(i = 0; i < iLen; i++)
- {
- iInput[i] = toupper((int)pInput[i]);
- }
-
- /* do difrac */
- difint_(iInput, &iLen);
- SCWrite(pCon,"Difrac subsystem finished",eWarning);
-
- iConStackPtr--;
- if(SCGetInterrupt(pCon) != eContinue)
- {
- return 0;
- }
- else
- {
- return 1;
- }
- }
-/*-------------------- The initialization routine ----------------------*/
- int MakeDifrac(SConnection *pCon, SicsInterp *pSics, void *pData,
+int DifracAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
- {
- CommandList *pCom = NULL;
- pICountable pCts = NULL;
- int iRet;
-
- if(argc < 6)
- {
- SCWrite(pCon,
- "ERROR: Insufficient number of arguments to MakeDifrac",eError);
- return 0;
- }
-
- /* find motors */
- pTTH = FindMotor(pSics,argv[1]);
- if(!pTTH)
- {
- SCWrite(pCon,"ERROR: cannot find two theta motor",eError);
- return 0;
- }
- pOM = FindMotor(pSics,argv[2]);
- if(!pOM)
- {
- SCWrite(pCon,"ERROR: cannot find omega motor",eError);
- return 0;
- }
- pCHI = FindMotor(pSics,argv[3]);
- if(!pTTH)
- {
- SCWrite(pCon,"ERROR: cannot find chi motor",eError);
- return 0;
- }
- pPHI = FindMotor(pSics,argv[4]);
- if(!pTTH)
- {
- SCWrite(pCon,"ERROR: cannot find phi motor",eError);
- return 0;
- }
+{
+ char pInput[256];
+ int iInput[256];
+ int iLen, i;
- /* locate counter */
- pCom = FindCommand(pSics,argv[5]);
- if(pCom == NULL)
- {
- SCWrite(pCon,"ERROR: counter not found in MakeDifrac",
- eError);
- return 0;
- }
- pCts = GetCountableInterface(pCom->pData);
- if(!pCts)
- {
- SCWrite(pCon,"ERROR: argument to MakeDifrac is no counter",
- eError);
- return 0;
- }
- counter = (pCounter)pCom->pData;
- /* initialize difrac */
- difini_();
-
- /* install command */
- iRet = AddCommand(pSics,
- "dif",
- DifracAction,
- NULL,
- NULL);
- if(!iRet)
- {
- SCWrite(pCon,"ERROR: duplicate command dif NOT created",
- eError);
- }
- return iRet;
+ if (argc < 2) {
+ SCWrite(pCon, "ERROR: dif expects at least one argument", eError);
+ return 0;
}
-
+
+ /* user privilege required */
+ if (!SCMatchRights(pCon, usUser)) {
+ return 0;
+ }
+
+ /* steal: redirect the I/O to me */
+ strcpy(pInput, argv[1]);
+ strtolower(pInput);
+ if (strcmp(pInput, "steal") == 0) {
+ if (iConStackPtr >= 0) {
+ ConStack[iConStackPtr] = pCon;
+ }
+ SCSendOK(pCon);
+ return 1;
+ }
+
+ iConStackPtr++;
+ ConStack[iConStackPtr] = pCon;
+
+ Arg2Text(argc - 1, &argv[1], pInput, 255);
+ iLen = strlen(pInput);
+ for (i = 0; i < iLen; i++) {
+ iInput[i] = toupper((int) pInput[i]);
+ }
+
+ /* do difrac */
+ difint_(iInput, &iLen);
+ SCWrite(pCon, "Difrac subsystem finished", eWarning);
+
+ iConStackPtr--;
+ if (SCGetInterrupt(pCon) != eContinue) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/*-------------------- The initialization routine ----------------------*/
+int MakeDifrac(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[])
+{
+ CommandList *pCom = NULL;
+ pICountable pCts = NULL;
+ int iRet;
+
+ if (argc < 6) {
+ SCWrite(pCon,
+ "ERROR: Insufficient number of arguments to MakeDifrac",
+ eError);
+ return 0;
+ }
+
+ /* find motors */
+ pTTH = FindMotor(pSics, argv[1]);
+ if (!pTTH) {
+ SCWrite(pCon, "ERROR: cannot find two theta motor", eError);
+ return 0;
+ }
+ pOM = FindMotor(pSics, argv[2]);
+ if (!pOM) {
+ SCWrite(pCon, "ERROR: cannot find omega motor", eError);
+ return 0;
+ }
+ pCHI = FindMotor(pSics, argv[3]);
+ if (!pTTH) {
+ SCWrite(pCon, "ERROR: cannot find chi motor", eError);
+ return 0;
+ }
+ pPHI = FindMotor(pSics, argv[4]);
+ if (!pTTH) {
+ SCWrite(pCon, "ERROR: cannot find phi motor", eError);
+ return 0;
+ }
+
+ /* locate counter */
+ pCom = FindCommand(pSics, argv[5]);
+ if (pCom == NULL) {
+ SCWrite(pCon, "ERROR: counter not found in MakeDifrac", eError);
+ return 0;
+ }
+ pCts = GetCountableInterface(pCom->pData);
+ if (!pCts) {
+ SCWrite(pCon, "ERROR: argument to MakeDifrac is no counter", eError);
+ return 0;
+ }
+ counter = (pCounter) pCom->pData;
+
+ /* initialize difrac */
+ difini_();
+
+ /* install command */
+ iRet = AddCommand(pSics, "dif", DifracAction, NULL, NULL);
+ if (!iRet) {
+ SCWrite(pCon, "ERROR: duplicate command dif NOT created", eError);
+ }
+ return iRet;
+}
diff --git a/difrac.h b/difrac.h
index b10a62f5..35ef1515 100644
--- a/difrac.h
+++ b/difrac.h
@@ -9,6 +9,6 @@
#ifndef DIFRAC
#define DIFRAC
- int MakeDifrac(SConnection *pCon, SicsInterp *pSics, void *pData,
- int argc, char *argv[]);
+int MakeDifrac(SConnection * pCon, SicsInterp * pSics, void *pData,
+ int argc, char *argv[]);
#endif
diff --git a/doc/manager/gencom.htm b/doc/manager/gencom.htm
index 07dd82db..1a7fc8c1 100644
--- a/doc/manager/gencom.htm
+++ b/doc/manager/gencom.htm
@@ -112,7 +112,9 @@ time intervalls. This can be achieved with the sicscron command:
sicscron intervall bla blab blab
This command installs a reoccuring task into SICS. The first
parameter is the intervall in seconds between calls to the SICS
-command. Everything behind that is treated as the command to execute.
+command. Everything behind that is treated as the command to execute.
+ The script has to be designed such that it does not return errors.
+ Errors in a cron script cause the cron task to be stopped.
The SICS Online Help System
diff --git a/doc/manager/managerman.dvi b/doc/manager/managerman.dvi
index f100bf2d..077356c0 100644
Binary files a/doc/manager/managerman.dvi and b/doc/manager/managerman.dvi differ
diff --git a/doc/manager/nxscript.htm b/doc/manager/nxscript.htm
index 803d6fe0..6c27eff5 100644
--- a/doc/manager/nxscript.htm
+++ b/doc/manager/nxscript.htm
@@ -104,6 +104,20 @@ the dictionary file:
would denote the normal counting tube at a scanning type of
experiment.
+nxscript puthdb path ?alias
+Put a hipadaba path. The alias to put the data too is found in one of two places: as the nxalias
+ property on the node or as given on the command line. The alias is expected to match the size and type of
+ the data. Please note that hipadaba stores all floats as double which is NX_FLOAT64 as number type.
+nxscript puthdboff path offset ?alias
+ Put a hipadaba path. The alias to put the data too is found in one of two places: as the nxalias
+ property on the node or as given on the command line. The alias is expected to match the size and type of
+ the data. Please note that hipadaba stores all floats as double which is NX_FLOAT64 as number type. Writing
+ data is started with the offset specified from the start of the data. This is useful to split a histogram
+ memory area into separate detectors or whatever.
+ nxscript puthdbslab path start size
+Put a hipdaba node as a slab. The node must have a property nxalias to determine where to write to.
+ Start and size are Tcl lists which give the start point where to write and the size of the data
+ to write. See nxscript putslab for more information.
nxscript puthm hmAlias hmName ?start? ?length? ?bank?
Writes data from the histogram memory hmName to a NeXus file using
the alias hmAlias. Nxscript automatically updates the dim0, dim1, ..., timedim
@@ -149,6 +163,10 @@ designated by targetAlias.
to write as a Tcl list and obj is the SICS object to write. Obj can be a
histogram memory; then the histogram memory data is written. Or it can be
a sicsdata object, the value of which will then be written.
+nxscript putslab16 alias startlist sizelist obj
+Writes a slab of data as above. Parameters are as setailed above.
+ The difference is that this converts the data to a6 bit int before writing.
+ And SICSData objects are not supported.
Automatic Updating of NeXus Files
diff --git a/doc/programmer/command.tex b/doc/programmer/command.tex
index b8467eb6..95382780 100644
--- a/doc/programmer/command.tex
+++ b/doc/programmer/command.tex
@@ -226,7 +226,7 @@ A valid SICS object structure has to look like this:
Please note that the first item in the data structure MUST be a
pointer to an SICS object descriptor. Add your own stuff below
that. If you do not adhere to this requirement, SICS will dump core on
-you rather sooner than later.
+you rather sooner then later.
SICS needs this object descriptor for its own internal purposes. The
@@ -566,7 +566,7 @@ This code also shows the necessary error checking. It also shows how
to check for possible interrupts after such an operation. It is very
advisable to do this because the user may have interrupted the
process. And she might not be all to happy if the new command just
-continues with the next step rather than aborting the process.
+continues with the next step rather then aborting the process.
\section{SICS Interfaces}\label{interface}\label{inter}
diff --git a/doc/programmer/motor.tex b/doc/programmer/motor.tex
index c5e3f695..a7fb83b8 100644
--- a/doc/programmer/motor.tex
+++ b/doc/programmer/motor.tex
@@ -8,7 +8,7 @@ subdivided into a driver and the logical object.
There is a problem here. There are some data fields and functions
which must be present for any motor driver. Then there are fields
which are specific just to a special implementation of a mot
-driver. There are several ways to deal with this. The way chosen for
+driver. There are several ways to deal with this. The way choosen for
the motor driver is a kind of overlay. The first few fields of a valid
motor driver structure MUST be specified in the same order as given
below. A special motor driver can add additional fields at the end of
@@ -122,12 +122,12 @@ creates a simulation motor driver.
\end{description}
\subsubsection{The Motor Logical Object}
-The motor object represents the motor to SICS. One of its responsibilities
+The motor object represents the motor to SICS. One of its responsabilities
is to drive motor operations and error checking. The scheme
implemented is that the motor object tries to bring the motor to its
position at least three times before a failure is recorded. Also the
motor object keeps track of a count of failed operations. If this
-count gets too high an interrupt is issued to stop the instrument. This
+count gets to high an interrupt is issued to stop the instrument. This
was put in after Druechal tried to drive over a slab of concrete for a
whole night and subsequently broke a clutch.
Motors are represented by the
@@ -164,7 +164,7 @@ object.
Much of the action of the motor is hidden in the implementation of the
drivable interface to the motor. Additionally the functions as given below
are defined. All functions take a pointer to the motor object data structure
-as a parameter. They return 0 on success or 1 on failure while not stated
+as a parameter. They retun 0 on success or 1 on failure while not stated
otherwise.
\begin{description}
\item[int MotorGetPar(pMotor self, char *name, float *fVal)] retrieves the
diff --git a/doc/user/drive.htm b/doc/user/drive.htm
index 938d914e..5634190e 100644
--- a/doc/user/drive.htm
+++ b/doc/user/drive.htm
@@ -9,7 +9,8 @@
run var newval var newval ... can be called with one to n pairs of object new value pairs. This command will set the variables in motion and return to the command prompt without waiting for the requested operations to finish. This feature allows to operate other devices of the instrument while perhaps a slow device is still running into position.
- Success waits and blocks the command connection until all pending operations have finished (or an interrupt occured).
+ Success [RUNDRIVE] waits and blocks the command connection until all pending operations have finished (or an interrupt occured). The option argument RUNDRIVE causes succes to only wait for motors and counts but not for sample environment.
+
drive var newval var newval ... can be called with one to n pairs of object new value pairs. This command will set the variables in motion and wait until the driving has finished. A drive can be seen as a sequence of a run command as stated above immediatly followed by a Success command.